Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: start refactor of modals and tooltips #346

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
41e62cd
start refactor of modals and tooltips
jamesscottbrown May 17, 2024
c9d1c3d
auto-format
jamesscottbrown May 17, 2024
f5a8623
re-add accidentally removed import
jamesscottbrown May 20, 2024
5dbd126
merge in changes from dev
jamesscottbrown Jan 10, 2025
01fd42a
Merge branch 'dev' of https://github.com/Greater-London-Authority/ldn…
halimahLDN Jan 29, 2025
cef2a13
Update package-lock
halimahLDN Jan 29, 2025
c710896
Attempting to rerun build lint
halimahLDN Jan 29, 2025
696f438
reinit package-lock
halimahLDN Jan 29, 2025
c7efdfa
recreate package-lock
halimahLDN Jan 29, 2025
3d549ff
attempting to fix build error
halimahLDN Jan 29, 2025
60bbd55
moved Trigger into separate folder and updated imports
halimahLDN Jan 29, 2025
d4516f2
Merge branch 'dev' of https://github.com/Greater-London-Authority/ldn…
halimahLDN Jan 29, 2025
3963c6b
refactored Tooltip to use Melt UI library
halimahLDN Jan 29, 2025
3d6dfef
refactored Trigger to use Melt UI library and added customAction and …
halimahLDN Jan 29, 2025
b69022d
deleted redundant tooltip.ts
halimahLDN Jan 29, 2025
a2572fc
updated customAction types
halimahLDN Jan 29, 2025
1d363a6
updated comments and moved action variable below customAction for eas…
halimahLDN Jan 29, 2025
58b96b7
removed div wrapper
halimahLDN Jan 29, 2025
fd21740
added trigger props to tooltip and trigger and implemented in stories
halimahLDN Jan 29, 2025
21d1554
created placementOptions type for use in createTooltip placement object
halimahLDN Jan 29, 2025
4c22bb5
added logic to pass hint into Trigger button
halimahLDN Jan 30, 2025
afdc5e8
refactored Modal to use new Trigger element and added comments for se…
halimahLDN Jan 30, 2025
ae3732b
deleted code that's no longer needed
halimahLDN Jan 30, 2025
a47b9a7
set open focus to focus whole modal so screen reader can read content…
halimahLDN Jan 30, 2025
e2790d8
refactoring MultipleActionButton to use Trigger and refactoring use: …
halimahLDN Jan 31, 2025
8d9d525
Added tabindex to title element to enable setting focus to first elem…
halimahLDN Jan 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
751 changes: 385 additions & 366 deletions package-lock.json

Large diffs are not rendered by default.

69 changes: 34 additions & 35 deletions packages/ui/src/lib/button/Button.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
openInNewTab: boolean;
type: 'button' | 'submit';
title: string;
customAction: ((node: HTMLElement) => MeltActionReturn<'keydown' | 'pointerdown'>) | undefined;
customAction:
| ((node: HTMLElement) => MeltActionReturn<'keydown' | 'pointerdown' | 'click'>)
| undefined;
}

type ButtonStyle = Record<
Expand Down Expand Up @@ -78,12 +80,13 @@
export let title: ButtonProps['title'] = '';

/**
* MeltUI Action passed down from MultipleActionButton
* MeltUI actions passed down from Trigger
*/
export let customAction: ButtonProps['customAction'] = undefined;
const action = customAction ? customAction : () => {};

/**
* MeltUI action props passed down from MultipleActionButton, which include ARIA attributes and tabindex.
* MeltUI action props passed down from Trigger, which include ARIA attributes and tabindex.
*/
export let actionProps = {};

Expand Down Expand Up @@ -233,37 +236,33 @@
href && disabled === true ? 'pointer-events-none' : '',
$$props.class
);

const action = customAction ? customAction : () => {};
</script>

<div class="flex">
<svelte:element
this={href ? 'a' : 'button'}
type={href ? undefined : type}
target={href && openInNewTab ? '_blank' : undefined}
rel={href && openInNewTab ? 'noopener noreferrer' : undefined}
{href}
{disabled}
{title}
class={buttonClass}
aria-label={ariaLabel}
{id}
on:click
on:change
on:keydown
on:keyup
on:touchstart
on:touchend
on:touchcancel
on:mouseenter
on:mouseleave
role="button"
tabindex="0"
use:action
{...actionProps}
>
<!-- contents of the button -->
<slot />
</svelte:element>
</div>
<svelte:element
this={href ? 'a' : 'button'}
type={href ? undefined : type}
target={href && openInNewTab ? '_blank' : undefined}
rel={href && openInNewTab ? 'noopener noreferrer' : undefined}
{href}
{disabled}
{title}
class={buttonClass}
aria-label={ariaLabel}
{id}
on:click
on:change
on:keydown
on:keyup
on:touchstart
on:touchend
on:touchcancel
on:mouseenter
on:mouseleave
role="button"
tabindex="0"
use:action
{...actionProps}
>
<!-- contents of the button -->
<slot />
</svelte:element>
42 changes: 33 additions & 9 deletions packages/ui/src/lib/modal/Modal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,27 @@
* @component
*/

import { createDialog } from '@melt-ui/svelte';
import { createDialog, type FocusProp } from '@melt-ui/svelte';
import { XMark } from '@steeze-ui/heroicons';
import { Icon } from '@steeze-ui/svelte-icon';
import { writable } from 'svelte/store';
import Button from '../button/Button.svelte';
import Trigger from '../trigger/Trigger.svelte';
import { classNames } from '../utils/classNames';

/**
* boolean Svelte store that determines whether the modal is currently open.
*/
export let isOpen = writable(false);

const customOpenFocus: FocusProp = () => {
const customElToFocus = document.getElementById($meltTitle.id);
return customElToFocus;
};

const {
elements: {
trigger,
portalled,
overlay,
content,
Expand All @@ -30,7 +37,7 @@
close
},
states: { open }
} = createDialog({ open: isOpen });
} = createDialog({ open: isOpen, openFocus: customOpenFocus });

/**
* title that appears at the top of the modal
Expand Down Expand Up @@ -64,6 +71,9 @@
| '7xl'
| 'full' = 'md';

export let hintLabel = 'More info';
export let showTrigger = false;

const hasChildren = Object.keys($$slots).length > 0;

const widthClasses = {
Expand All @@ -87,17 +97,30 @@
);
</script>

<div {...$portalled} use:$portalled.action>
{#if showTrigger}
{#if $$slots.hint}
<Trigger customAction={trigger} actionProps={$trigger}>
<slot name="hint" />
</Trigger>
{:else}
<Trigger {hintLabel} customAction={trigger} actionProps={$trigger} />
{/if}
{/if}

<div {...$portalled} use:portalled>
{#if $open}
<div {...$overlay} use:$overlay.action class="fixed inset-0 bg-black bg-opacity-40 z-40" />
<!-- The dim background that is behind the modal -->
<div {...$overlay} use:overlay class="fixed inset-0 bg-black bg-opacity-40 z-40" />

<div class="fixed inset-8 flex items-center justify-center pointer-events-none z-50">
<div {...$content} use:$content.action class={modalClass}>
<!-- Modal content -->
<div {...$content} use:content class={modalClass}>
<!-- Header -->
<div
class={`bg-color-container-level-1 text-color-text-primary p-2 pl-3 relative flex items-center justify-between border-l-[5px] border-color-static-brand ${headerTheme}`}
class="bg-color-container-level-1 text-color-text-primary p-2 pl-3 relative flex items-center justify-between border-l-[5px] border-color-static-brand {headerTheme}"
>
<div class="text-lg font-medium" {...$meltTitle} use:$meltTitle.action>{title}</div>
<div {...$close} use:$close.action>
<div class="text-lg font-medium" tabindex="-1" {...$meltTitle} use:meltTitle>{title}</div>
<div {...$close} use:close>
<Button
variant="square"
emphasis="secondary"
Expand All @@ -110,10 +133,11 @@
</div>
</div>

<!-- Modal body -->
<div class="overflow-y-auto">
<div class="p-4">
{#if description}
<div {...$meltDescription} use:$meltDescription.action>{description}</div>
<div {...$meltDescription} use:meltDescription>{description}</div>
{/if}

{#if hasChildren}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import { Icon } from '@steeze-ui/svelte-icon';
import type { ButtonProps } from '../button/Button.svelte';
import Button from '../button/Button.svelte';
import Trigger from '../trigger/Trigger.svelte';
import { randomId } from '../utils/randomId';

/**
Expand Down Expand Up @@ -142,25 +143,25 @@
</div>
</Button>

<Button
<Trigger
variant="square"
{emphasis}
{condition}
{size}
{disabled}
customAction={$trigger.action}
customAction={trigger}
actionProps={$trigger}
class={`${variant === 'outline' ? ' border-l-0 ' : 'border-l border-color-action-border-secondary'}`}
ariaLabel={menuTitle ? 'Open popover to ' + menuTitle : 'Open popover'}
>
<Icon src={ChevronDown} theme="mini" class="h-5 w-5" />
</Button>
<Icon src={ChevronDown} theme="mini" class="h-5 w-5" slot="hint" />
</Trigger>
</div>

{#if $open}
<div
class="bg-color-container-level-1 z-40 max-w-sm p-2 shadow flex flex-col space-y-2"
use:$menu.action
use:menu
{...$menu}
transition:fly={{ duration: 150, y: -10 }}
>
Expand All @@ -174,7 +175,7 @@
<button
class="text-left w-full p-2 hover:bg-color-action-background-primary-hover hover:text-color-static-white"
on:click={() => changeOption(option)}
use:$item.action
use:item
{...$item}
>
<div class="flex items-center">
Expand All @@ -189,6 +190,6 @@
{/each}
</div>
</div>
<div use:$arrow.action {...$arrow} />
<div use:arrow {...$arrow} />
{/if}
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,17 @@
</SidebarHint></Template
>

<Story name="Default (Modal)" source />
<Story name="Default (tooltip)" source />

<Story name="Modal" source>
<SidebarHint hintType="modal">
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat
non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
</SidebarHint>
</Story>

<Story name="Modal width" source>
<SidebarHint hintType="modal" modalWidth="5xl">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
* @component
*/

import Modal from '../../../modal/Modal.svelte';
import Popover from '../../../popover/Popover.svelte';
import Tooltip from '../../../tooltip/Tooltip.svelte';
import SidebarHintModal from './SidebarHintModal.svelte';

/**
* Form in which the help text should be displayed.
Expand Down Expand Up @@ -58,8 +58,12 @@
<slot />
</Popover>
{:else if hintType === 'modal'}
<SidebarHintModal {hintLabel} {modalTitle} {modalDescription} {modalWidth}>
<Modal title={modalTitle || ''} description={modalDescription} width={modalWidth} showTrigger>
<svelte:fragment slot="hintText">
{hintLabel}
</svelte:fragment>

<!-- The help message. -->
<slot />
</SidebarHintModal>
</Modal>
{/if}
38 changes: 34 additions & 4 deletions packages/ui/src/lib/tooltip/Tooltip.stories.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,32 @@
hintSize: {
options: ['sm', 'md', 'lg'],
control: { type: 'select' }
},
triggerClass: { type: 'string', control: 'text' },
triggerVariant: {
options: ['brand', 'solid', 'outline', 'text'], //square
control: { type: 'select' }
},
triggerEmphasis: {
options: ['primary', 'secondary'],
control: { type: 'radio' }
},
placement: {
options: [
'top',
'top-start',
'top-end',
'right',
'right-start',
'right-end',
'bottom',
'bottom-start',
'bottom-end',
'left',
'left-start',
'left-end'
],
control: { type: 'select' }
}
}
};
Expand All @@ -26,22 +52,26 @@
<Tooltip {...args}>This is some text</Tooltip>
</Template>

<Story name="Default" source />
<Story name="Default" source args={{ triggerClass: '!p-0' }} />

<Story name="Hint Size">
<Tooltip hintSize="sm">This is some text</Tooltip>
<Tooltip hintSize="sm" triggerClass="!p-0">This is some text</Tooltip>
</Story>

<Story name="Custom hint label">
<Tooltip hintLabel="Hover over me!">This is some text</Tooltip>
<Tooltip hintLabel="Hover over me!" triggerClass="!p-0">This is some text</Tooltip>
</Story>

<Story name="Custom hint icon">
<Tooltip>
<Tooltip triggerClass="!p-0">
<svelte:fragment slot="hint">
I have a different icon
<Icon src={Cog6Tooth} theme="mini" class="w-[18px] h-[18px] ml-0.5" aria-hidden="true" />
</svelte:fragment>
But I still work the same
</Tooltip>
</Story>

<Story name="Custom trigger styling">
<Tooltip triggerVariant="square">This is a test!</Tooltip>
</Story>
Loading
Loading