diff --git a/packages/shared-ui/src/index.ts b/packages/shared-ui/src/index.ts index 1eacc976c..05949bbf6 100644 --- a/packages/shared-ui/src/index.ts +++ b/packages/shared-ui/src/index.ts @@ -21,12 +21,12 @@ export { SkeletonBox, SkeletonText } from './molecules'; export { EmptyState } from './molecules'; // Layout -export { ModalFooter, DataCard, PageHeader } from './molecules'; +export { ModalFooter, DataCard, PageHeader, KeyboardShortcutsPanel } from './molecules'; // Organisms export { Modal, ConfirmationModal, FormModal, AppSlider } from './organisms'; export type { AppItem } from './organisms'; // Navigation -export { NavLink, Navbar, Sidebar } from './navigation'; -export type { NavItem, NavbarProps, SidebarProps, NavLinkProps } from './navigation'; +export { NavLink, Navbar, Sidebar, SidebarSection } from './navigation'; +export type { NavItem, NavbarProps, SidebarProps, NavLinkProps, KeyboardShortcut } from './navigation'; diff --git a/packages/shared-ui/src/molecules/KeyboardShortcutsPanel.svelte b/packages/shared-ui/src/molecules/KeyboardShortcutsPanel.svelte new file mode 100644 index 000000000..da53cb3c4 --- /dev/null +++ b/packages/shared-ui/src/molecules/KeyboardShortcutsPanel.svelte @@ -0,0 +1,181 @@ + + +{#if !compact} +
+ + + + + {#if expanded || !collapsible} +
+ {#each Object.entries(groupedShortcuts()) as [category, categoryShortcuts]} +
+ {#if Object.keys(groupedShortcuts()).length > 1} + + {category} + + {/if} +
+ {#each categoryShortcuts as shortcut} +
+ + {shortcut.label} + +
+ {#each shortcut.keys as key, i} + + {key} + + {#if i < shortcut.keys.length - 1} + + + {/if} + {/each} +
+
+ {/each} +
+
+ {/each} +
+ {/if} +
+{:else} + + +{/if} diff --git a/packages/shared-ui/src/molecules/index.ts b/packages/shared-ui/src/molecules/index.ts index 0c10faf53..6766ee887 100644 --- a/packages/shared-ui/src/molecules/index.ts +++ b/packages/shared-ui/src/molecules/index.ts @@ -24,3 +24,4 @@ export { EmptyState } from './feedback'; export { default as ModalFooter } from './ModalFooter.svelte'; export { default as DataCard } from './DataCard.svelte'; export { default as PageHeader } from './PageHeader.svelte'; +export { default as KeyboardShortcutsPanel } from './KeyboardShortcutsPanel.svelte'; diff --git a/packages/shared-ui/src/navigation/SidebarSection.svelte b/packages/shared-ui/src/navigation/SidebarSection.svelte new file mode 100644 index 000000000..8289f1f88 --- /dev/null +++ b/packages/shared-ui/src/navigation/SidebarSection.svelte @@ -0,0 +1,110 @@ + + + diff --git a/packages/shared-ui/src/navigation/index.ts b/packages/shared-ui/src/navigation/index.ts index 5dbbc3ea3..7571956e0 100644 --- a/packages/shared-ui/src/navigation/index.ts +++ b/packages/shared-ui/src/navigation/index.ts @@ -1,4 +1,5 @@ export { default as NavLink } from './NavLink.svelte'; export { default as Navbar } from './Navbar.svelte'; export { default as Sidebar } from './Sidebar.svelte'; -export type { NavItem, NavbarProps, SidebarProps, NavLinkProps } from './types'; +export { default as SidebarSection } from './SidebarSection.svelte'; +export type { NavItem, NavbarProps, SidebarProps, NavLinkProps, KeyboardShortcut } from './types'; diff --git a/packages/shared-ui/src/navigation/types.ts b/packages/shared-ui/src/navigation/types.ts index 9ba9d0bb5..0bb1e0f72 100644 --- a/packages/shared-ui/src/navigation/types.ts +++ b/packages/shared-ui/src/navigation/types.ts @@ -1,5 +1,14 @@ import type { Snippet } from 'svelte'; +export interface KeyboardShortcut { + /** Key combination (e.g., ['Ctrl', 'S'] or ['Cmd', 'Shift', 'P']) */ + keys: string[]; + /** Description of what the shortcut does */ + label: string; + /** Category for grouping (optional) */ + category?: string; +} + export interface NavItem { /** Display label for the navigation item */ label: string;