immich/web/src/lib/components/shared-components/context-menu/menu-option.svelte

80 lines
2.1 KiB
Svelte
Raw Normal View History

feat(web): keyboard accessible context menus (#10017) * feat(web,a11y): context menu keyboard navigation * wip: all context menus visible * wip: more migrations to the ButtonContextMenu, usability improvements * wip: migrate Administration, PeopleCard * wip: refocus the button on click, docs * fix: more intuitive RightClickContextMenu - configurable title - focus management: tab keys, clicks, closing the menu - automatically closing when an option is selected * fix: refining the little details - adjust the aria attributes - intuitive escape key propagation - extract context into its own file * fix: dropdown options not clickable in a <Portal> * wip: small fixes - export selectedColor to prevent unexpected styling - better context function naming * chore: revert changes to list navigation, to reduce scope of the PR * fix: remove topBorder prop * feat: automatically select the first option on enter or space keypress * fix: use Svelte store instead to handle selecting menu options - better prop naming for ButtonContextMenu * feat: hovering the mouse can change the active element * fix: remove Portal, more predictable open/close behavior * feat: make selected item visible using a scroll - also: minor cleanup of the context-menu-navigation Svelte action * feat: maintain context menu position on resize * fix: use the whole padding class as better tailwind convention * fix: options not announcing with screen reader for ButtonContextMenu * fix: screen reader announcing right click context menu options * fix: handle focus out scenario --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
2024-06-18 03:52:38 +00:00
<script lang="ts">
import type { Shortcut } from '$lib/actions/shortcut';
import { shortcut as bindShortcut, shortcutLabel as computeShortcutLabel } from '$lib/actions/shortcut';
feat(web): keyboard accessible context menus (#10017) * feat(web,a11y): context menu keyboard navigation * wip: all context menus visible * wip: more migrations to the ButtonContextMenu, usability improvements * wip: migrate Administration, PeopleCard * wip: refocus the button on click, docs * fix: more intuitive RightClickContextMenu - configurable title - focus management: tab keys, clicks, closing the menu - automatically closing when an option is selected * fix: refining the little details - adjust the aria attributes - intuitive escape key propagation - extract context into its own file * fix: dropdown options not clickable in a <Portal> * wip: small fixes - export selectedColor to prevent unexpected styling - better context function naming * chore: revert changes to list navigation, to reduce scope of the PR * fix: remove topBorder prop * feat: automatically select the first option on enter or space keypress * fix: use Svelte store instead to handle selecting menu options - better prop naming for ButtonContextMenu * feat: hovering the mouse can change the active element * fix: remove Portal, more predictable open/close behavior * feat: make selected item visible using a scroll - also: minor cleanup of the context-menu-navigation Svelte action * feat: maintain context menu position on resize * fix: use the whole padding class as better tailwind convention * fix: options not announcing with screen reader for ButtonContextMenu * fix: screen reader announcing right click context menu options * fix: handle focus out scenario --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
2024-06-18 03:52:38 +00:00
import { optionClickCallbackStore, selectedIdStore } from '$lib/stores/context-menu.store';
import { generateId } from '$lib/utils/generate-id';
2025-09-16 21:40:43 +02:00
import { Icon } from '@immich/ui';
interface Props {
text: string;
subtitle?: string;
icon?: string;
activeColor?: string;
textColor?: string;
onClick: () => void;
shortcut?: Shortcut | null;
shortcutLabel?: string;
}
let {
text,
subtitle = '',
icon = '',
activeColor = 'bg-slate-300',
textColor = 'text-immich-fg dark:text-immich-dark-bg',
onClick,
shortcut = null,
shortcutLabel = '',
}: Props = $props();
feat(web): keyboard accessible context menus (#10017) * feat(web,a11y): context menu keyboard navigation * wip: all context menus visible * wip: more migrations to the ButtonContextMenu, usability improvements * wip: migrate Administration, PeopleCard * wip: refocus the button on click, docs * fix: more intuitive RightClickContextMenu - configurable title - focus management: tab keys, clicks, closing the menu - automatically closing when an option is selected * fix: refining the little details - adjust the aria attributes - intuitive escape key propagation - extract context into its own file * fix: dropdown options not clickable in a <Portal> * wip: small fixes - export selectedColor to prevent unexpected styling - better context function naming * chore: revert changes to list navigation, to reduce scope of the PR * fix: remove topBorder prop * feat: automatically select the first option on enter or space keypress * fix: use Svelte store instead to handle selecting menu options - better prop naming for ButtonContextMenu * feat: hovering the mouse can change the active element * fix: remove Portal, more predictable open/close behavior * feat: make selected item visible using a scroll - also: minor cleanup of the context-menu-navigation Svelte action * feat: maintain context menu position on resize * fix: use the whole padding class as better tailwind convention * fix: options not announcing with screen reader for ButtonContextMenu * fix: screen reader announcing right click context menu options * fix: handle focus out scenario --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
2024-06-18 03:52:38 +00:00
let id: string = generateId();
let isActive = $derived($selectedIdStore === id);
feat(web): keyboard accessible context menus (#10017) * feat(web,a11y): context menu keyboard navigation * wip: all context menus visible * wip: more migrations to the ButtonContextMenu, usability improvements * wip: migrate Administration, PeopleCard * wip: refocus the button on click, docs * fix: more intuitive RightClickContextMenu - configurable title - focus management: tab keys, clicks, closing the menu - automatically closing when an option is selected * fix: refining the little details - adjust the aria attributes - intuitive escape key propagation - extract context into its own file * fix: dropdown options not clickable in a <Portal> * wip: small fixes - export selectedColor to prevent unexpected styling - better context function naming * chore: revert changes to list navigation, to reduce scope of the PR * fix: remove topBorder prop * feat: automatically select the first option on enter or space keypress * fix: use Svelte store instead to handle selecting menu options - better prop naming for ButtonContextMenu * feat: hovering the mouse can change the active element * fix: remove Portal, more predictable open/close behavior * feat: make selected item visible using a scroll - also: minor cleanup of the context-menu-navigation Svelte action * feat: maintain context menu position on resize * fix: use the whole padding class as better tailwind convention * fix: options not announcing with screen reader for ButtonContextMenu * fix: screen reader announcing right click context menu options * fix: handle focus out scenario --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
2024-06-18 03:52:38 +00:00
const handleClick = () => {
$optionClickCallbackStore?.();
onClick();
feat(web): keyboard accessible context menus (#10017) * feat(web,a11y): context menu keyboard navigation * wip: all context menus visible * wip: more migrations to the ButtonContextMenu, usability improvements * wip: migrate Administration, PeopleCard * wip: refocus the button on click, docs * fix: more intuitive RightClickContextMenu - configurable title - focus management: tab keys, clicks, closing the menu - automatically closing when an option is selected * fix: refining the little details - adjust the aria attributes - intuitive escape key propagation - extract context into its own file * fix: dropdown options not clickable in a <Portal> * wip: small fixes - export selectedColor to prevent unexpected styling - better context function naming * chore: revert changes to list navigation, to reduce scope of the PR * fix: remove topBorder prop * feat: automatically select the first option on enter or space keypress * fix: use Svelte store instead to handle selecting menu options - better prop naming for ButtonContextMenu * feat: hovering the mouse can change the active element * fix: remove Portal, more predictable open/close behavior * feat: make selected item visible using a scroll - also: minor cleanup of the context-menu-navigation Svelte action * feat: maintain context menu position on resize * fix: use the whole padding class as better tailwind convention * fix: options not announcing with screen reader for ButtonContextMenu * fix: screen reader announcing right click context menu options * fix: handle focus out scenario --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
2024-06-18 03:52:38 +00:00
};
if (shortcut && !shortcutLabel) {
shortcutLabel = computeShortcutLabel(shortcut);
}
const bindShortcutIfSet = shortcut
? (n: HTMLElement) => bindShortcut(n, { shortcut, onShortcut: onClick })
: () => {};
</script>
<svelte:document use:bindShortcutIfSet />
<!-- svelte-ignore a11y_click_events_have_key_events -->
<!-- svelte-ignore a11y_mouse_events_have_key_events -->
feat(web): keyboard accessible context menus (#10017) * feat(web,a11y): context menu keyboard navigation * wip: all context menus visible * wip: more migrations to the ButtonContextMenu, usability improvements * wip: migrate Administration, PeopleCard * wip: refocus the button on click, docs * fix: more intuitive RightClickContextMenu - configurable title - focus management: tab keys, clicks, closing the menu - automatically closing when an option is selected * fix: refining the little details - adjust the aria attributes - intuitive escape key propagation - extract context into its own file * fix: dropdown options not clickable in a <Portal> * wip: small fixes - export selectedColor to prevent unexpected styling - better context function naming * chore: revert changes to list navigation, to reduce scope of the PR * fix: remove topBorder prop * feat: automatically select the first option on enter or space keypress * fix: use Svelte store instead to handle selecting menu options - better prop naming for ButtonContextMenu * feat: hovering the mouse can change the active element * fix: remove Portal, more predictable open/close behavior * feat: make selected item visible using a scroll - also: minor cleanup of the context-menu-navigation Svelte action * feat: maintain context menu position on resize * fix: use the whole padding class as better tailwind convention * fix: options not announcing with screen reader for ButtonContextMenu * fix: screen reader announcing right click context menu options * fix: handle focus out scenario --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
2024-06-18 03:52:38 +00:00
<li
{id}
onclick={handleClick}
onmouseover={() => ($selectedIdStore = id)}
onmouseleave={() => ($selectedIdStore = undefined)}
2025-04-28 09:53:53 -04:00
class="w-full p-4 text-start text-sm font-medium {textColor} focus:outline-none focus:ring-2 focus:ring-inset cursor-pointer border-gray-200 flex gap-2 items-center {isActive
? activeColor
: 'bg-slate-100'}"
role="menuitem"
>
{#if icon}
2025-09-16 21:40:43 +02:00
<Icon {icon} aria-hidden size="18" />
{/if}
<div class="w-full">
<div class="flex justify-between">
{text}
{#if shortcutLabel}
2025-04-28 09:53:53 -04:00
<span class="text-gray-500 ps-4">
{shortcutLabel}
</span>
{/if}
</div>
{#if subtitle}
<p class="text-xs text-gray-500">
{subtitle}
</p>
{/if}
</div>
feat(web): keyboard accessible context menus (#10017) * feat(web,a11y): context menu keyboard navigation * wip: all context menus visible * wip: more migrations to the ButtonContextMenu, usability improvements * wip: migrate Administration, PeopleCard * wip: refocus the button on click, docs * fix: more intuitive RightClickContextMenu - configurable title - focus management: tab keys, clicks, closing the menu - automatically closing when an option is selected * fix: refining the little details - adjust the aria attributes - intuitive escape key propagation - extract context into its own file * fix: dropdown options not clickable in a <Portal> * wip: small fixes - export selectedColor to prevent unexpected styling - better context function naming * chore: revert changes to list navigation, to reduce scope of the PR * fix: remove topBorder prop * feat: automatically select the first option on enter or space keypress * fix: use Svelte store instead to handle selecting menu options - better prop naming for ButtonContextMenu * feat: hovering the mouse can change the active element * fix: remove Portal, more predictable open/close behavior * feat: make selected item visible using a scroll - also: minor cleanup of the context-menu-navigation Svelte action * feat: maintain context menu position on resize * fix: use the whole padding class as better tailwind convention * fix: options not announcing with screen reader for ButtonContextMenu * fix: screen reader announcing right click context menu options * fix: handle focus out scenario --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
2024-06-18 03:52:38 +00:00
</li>