@hyvnt/hyvui 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/README.md +294 -253
  2. package/dist/components/ambient/ArcaneVein.svelte +151 -0
  3. package/dist/components/ambient/ArcaneVein.svelte.d.ts +31 -0
  4. package/dist/components/ambient/BrassFiligree.svelte +109 -0
  5. package/dist/components/ambient/BrassFiligree.svelte.d.ts +20 -0
  6. package/dist/components/ambient/CornerBrackets.svelte +91 -87
  7. package/dist/components/ambient/CornerBrackets.svelte.d.ts +8 -0
  8. package/dist/components/ambient/CrystalShard.svelte +151 -0
  9. package/dist/components/ambient/CrystalShard.svelte.d.ts +19 -0
  10. package/dist/components/ambient/DataStream.svelte +117 -94
  11. package/dist/components/ambient/DataStream.svelte.d.ts +6 -0
  12. package/dist/components/ambient/EnergyArc.svelte +189 -0
  13. package/dist/components/ambient/EnergyArc.svelte.d.ts +32 -0
  14. package/dist/components/ambient/GlyphMark.svelte +75 -69
  15. package/dist/components/ambient/GlyphMark.svelte.d.ts +6 -0
  16. package/dist/components/ambient/GridOverlay.svelte +34 -28
  17. package/dist/components/ambient/GridOverlay.svelte.d.ts +8 -0
  18. package/dist/components/ambient/HexGrid.svelte +119 -0
  19. package/dist/components/ambient/HexGrid.svelte.d.ts +21 -0
  20. package/dist/components/ambient/ParallaxLayer.svelte +45 -41
  21. package/dist/components/ambient/ParallaxLayer.svelte.d.ts +7 -0
  22. package/dist/components/ambient/ScanBand.svelte +103 -91
  23. package/dist/components/ambient/ScanBand.svelte.d.ts +8 -0
  24. package/dist/components/ambient/ShimmerCloud.svelte +180 -0
  25. package/dist/components/ambient/ShimmerCloud.svelte.d.ts +21 -0
  26. package/dist/components/ambient/SignalRing.svelte +106 -100
  27. package/dist/components/ambient/SignalRing.svelte.d.ts +6 -0
  28. package/dist/components/ambient/ThreadLine.svelte +78 -78
  29. package/dist/components/ambient/ThreadLine.svelte.d.ts +7 -0
  30. package/dist/components/ambient/Vignette.svelte +30 -26
  31. package/dist/components/ambient/Vignette.svelte.d.ts +6 -0
  32. package/dist/components/depth/DepthLayer.svelte +30 -27
  33. package/dist/components/depth/DepthLayer.svelte.d.ts +8 -0
  34. package/dist/components/depth/DepthStage.svelte +67 -62
  35. package/dist/components/depth/DepthStage.svelte.d.ts +8 -0
  36. package/dist/components/depth/FloatCard.svelte +129 -104
  37. package/dist/components/depth/FloatCard.svelte.d.ts +8 -0
  38. package/dist/components/depth/HorizonGrid.svelte +241 -160
  39. package/dist/components/depth/HorizonGrid.svelte.d.ts +9 -0
  40. package/dist/components/depth/Plinth.svelte +62 -57
  41. package/dist/components/depth/Plinth.svelte.d.ts +10 -0
  42. package/dist/components/display/Avatar.svelte +69 -69
  43. package/dist/components/display/Avatar.svelte.d.ts +5 -0
  44. package/dist/components/display/Badge.svelte +75 -63
  45. package/dist/components/display/Badge.svelte.d.ts +6 -0
  46. package/dist/components/display/Blockquote.svelte +35 -34
  47. package/dist/components/display/Blockquote.svelte.d.ts +4 -0
  48. package/dist/components/display/CodeBlock.svelte +76 -76
  49. package/dist/components/display/CodeBlock.svelte.d.ts +5 -0
  50. package/dist/components/display/MetricCard.svelte +100 -83
  51. package/dist/components/display/MetricCard.svelte.d.ts +6 -0
  52. package/dist/components/display/Table.svelte +106 -104
  53. package/dist/components/display/Table.svelte.d.ts +7 -0
  54. package/dist/components/feedback/Alert.svelte +95 -76
  55. package/dist/components/feedback/Alert.svelte.d.ts +6 -0
  56. package/dist/components/feedback/EmptyState.svelte +75 -68
  57. package/dist/components/feedback/EmptyState.svelte.d.ts +7 -0
  58. package/dist/components/feedback/ErrorState.svelte +78 -73
  59. package/dist/components/feedback/ErrorState.svelte.d.ts +5 -0
  60. package/dist/components/feedback/Skeleton.svelte +58 -52
  61. package/dist/components/feedback/Skeleton.svelte.d.ts +6 -0
  62. package/dist/components/feedback/StatusDot.svelte +84 -54
  63. package/dist/components/feedback/StatusDot.svelte.d.ts +6 -0
  64. package/dist/components/feedback/StatusLine.svelte +128 -122
  65. package/dist/components/feedback/StatusLine.svelte.d.ts +6 -0
  66. package/dist/components/feedback/Toast.svelte +144 -136
  67. package/dist/components/feedback/Toast.svelte.d.ts +10 -0
  68. package/dist/components/inputs/Button.svelte +310 -237
  69. package/dist/components/inputs/Button.svelte.d.ts +8 -0
  70. package/dist/components/inputs/Checkbox.svelte +109 -105
  71. package/dist/components/inputs/Checkbox.svelte.d.ts +5 -0
  72. package/dist/components/inputs/FileUpload.svelte +170 -163
  73. package/dist/components/inputs/FileUpload.svelte.d.ts +5 -0
  74. package/dist/components/inputs/Input.svelte +153 -147
  75. package/dist/components/inputs/Input.svelte.d.ts +7 -0
  76. package/dist/components/inputs/Select.svelte +164 -150
  77. package/dist/components/inputs/Select.svelte.d.ts +8 -0
  78. package/dist/components/inputs/Textarea.svelte +160 -154
  79. package/dist/components/inputs/Textarea.svelte.d.ts +6 -0
  80. package/dist/components/inputs/Toggle.svelte +125 -120
  81. package/dist/components/inputs/Toggle.svelte.d.ts +5 -0
  82. package/dist/components/layout/Card.svelte +81 -76
  83. package/dist/components/layout/Card.svelte.d.ts +11 -0
  84. package/dist/components/layout/Drawer.svelte +140 -109
  85. package/dist/components/layout/Drawer.svelte.d.ts +6 -0
  86. package/dist/components/layout/Grid.svelte +128 -43
  87. package/dist/components/layout/Grid.svelte.d.ts +18 -2
  88. package/dist/components/layout/Modal.svelte +191 -159
  89. package/dist/components/layout/Modal.svelte.d.ts +10 -0
  90. package/dist/components/layout/Panel.svelte +58 -54
  91. package/dist/components/layout/Panel.svelte.d.ts +9 -0
  92. package/dist/components/layout/Popover.svelte +188 -67
  93. package/dist/components/layout/Popover.svelte.d.ts +19 -1
  94. package/dist/components/layout/Stack.svelte +65 -53
  95. package/dist/components/layout/Stack.svelte.d.ts +12 -0
  96. package/dist/components/navigation/Breadcrumb.svelte +78 -73
  97. package/dist/components/navigation/Breadcrumb.svelte.d.ts +8 -0
  98. package/dist/components/navigation/DropdownMenu.svelte +179 -124
  99. package/dist/components/navigation/DropdownMenu.svelte.d.ts +24 -2
  100. package/dist/components/navigation/SidebarNav.svelte +96 -90
  101. package/dist/components/navigation/SidebarNav.svelte.d.ts +9 -0
  102. package/dist/components/navigation/Tabs.svelte +106 -86
  103. package/dist/components/navigation/Tabs.svelte.d.ts +8 -0
  104. package/dist/components/navigation/Topbar.svelte +94 -85
  105. package/dist/components/navigation/Topbar.svelte.d.ts +9 -0
  106. package/dist/components/patterns/ActionBar.svelte +82 -76
  107. package/dist/components/patterns/ActionBar.svelte.d.ts +10 -0
  108. package/dist/components/patterns/ChapterMark.svelte +152 -0
  109. package/dist/components/patterns/ChapterMark.svelte.d.ts +19 -0
  110. package/dist/components/patterns/ConfirmDialog.svelte +75 -64
  111. package/dist/components/patterns/ConfirmDialog.svelte.d.ts +12 -0
  112. package/dist/components/patterns/DepthPortal.svelte +123 -0
  113. package/dist/components/patterns/DepthPortal.svelte.d.ts +24 -0
  114. package/dist/components/patterns/Manifesto.svelte +171 -0
  115. package/dist/components/patterns/Manifesto.svelte.d.ts +25 -0
  116. package/dist/components/patterns/PageHeader.svelte +117 -114
  117. package/dist/components/patterns/PageHeader.svelte.d.ts +8 -0
  118. package/dist/components/patterns/PullQuote.svelte +145 -0
  119. package/dist/components/patterns/PullQuote.svelte.d.ts +23 -0
  120. package/dist/components/patterns/RegisterSwitcher.svelte +132 -0
  121. package/dist/components/patterns/RegisterSwitcher.svelte.d.ts +21 -0
  122. package/dist/components/patterns/SearchBar.svelte +59 -59
  123. package/dist/components/patterns/SearchBar.svelte.d.ts +5 -0
  124. package/dist/components/patterns/ShowcaseFrame.svelte +117 -0
  125. package/dist/components/patterns/ShowcaseFrame.svelte.d.ts +28 -0
  126. package/dist/components/patterns/TerminalBoot.svelte +118 -104
  127. package/dist/components/patterns/TerminalBoot.svelte.d.ts +12 -0
  128. package/dist/components/primitives/Divider.svelte +56 -29
  129. package/dist/components/primitives/Divider.svelte.d.ts +5 -0
  130. package/dist/components/primitives/Icon.svelte +53 -49
  131. package/dist/components/primitives/Icon.svelte.d.ts +9 -0
  132. package/dist/components/primitives/Label.svelte +45 -44
  133. package/dist/components/primitives/Label.svelte.d.ts +6 -0
  134. package/dist/components/primitives/Surface.svelte +154 -87
  135. package/dist/components/primitives/Surface.svelte.d.ts +7 -0
  136. package/dist/components/primitives/Text.svelte +130 -98
  137. package/dist/components/primitives/Text.svelte.d.ts +7 -0
  138. package/dist/components/scenes/ArchiveScene.svelte +102 -95
  139. package/dist/components/scenes/ArchiveScene.svelte.d.ts +17 -1
  140. package/dist/components/scenes/DepthScene.svelte +128 -0
  141. package/dist/components/scenes/DepthScene.svelte.d.ts +36 -0
  142. package/dist/components/scenes/LogScene.svelte +86 -77
  143. package/dist/components/scenes/LogScene.svelte.d.ts +14 -0
  144. package/dist/components/scenes/NarrativeScene.svelte +100 -92
  145. package/dist/components/scenes/NarrativeScene.svelte.d.ts +9 -0
  146. package/dist/components/scenes/ReadoutScene.svelte +131 -107
  147. package/dist/components/scenes/ReadoutScene.svelte.d.ts +14 -1
  148. package/dist/components/scenes/StageScene.svelte +111 -104
  149. package/dist/components/scenes/StageScene.svelte.d.ts +14 -0
  150. package/dist/components/system/AppShell.svelte +62 -0
  151. package/dist/components/system/AppShell.svelte.d.ts +32 -0
  152. package/dist/examples/ArcaneShard.svelte +364 -0
  153. package/dist/examples/ArcaneShard.svelte.d.ts +3 -0
  154. package/dist/examples/FieldReport.svelte +226 -223
  155. package/dist/examples/HextechForge.svelte +324 -0
  156. package/dist/examples/HextechForge.svelte.d.ts +3 -0
  157. package/dist/examples/ObservationDeck.svelte +333 -317
  158. package/dist/examples/SignalLost.svelte +191 -191
  159. package/dist/index.d.ts +15 -1
  160. package/dist/index.js +16 -1
  161. package/dist/styles.css +115 -0
  162. package/dist/system/actions/echo.js +21 -12
  163. package/dist/system/actions/resolve.js +28 -14
  164. package/dist/system/actions/reveal.js +2 -2
  165. package/dist/system/actions/surface.js +12 -2
  166. package/dist/system/depth/depth.css +49 -49
  167. package/dist/system/depth/depth.js +1 -1
  168. package/dist/system/expressions.css +80 -80
  169. package/dist/system/override-template.css +72 -72
  170. package/dist/system/register.css +74 -74
  171. package/dist/system/register.d.ts +1 -1
  172. package/dist/system/register.js +5 -1
  173. package/dist/system/scroll-lock.d.ts +6 -0
  174. package/dist/system/scroll-lock.js +23 -0
  175. package/dist/tokens/arcane.css +96 -0
  176. package/dist/tokens/hextech.css +96 -0
  177. package/dist/tokens/tokens.css +102 -86
  178. package/dist/tokens/tokens.d.ts +41 -0
  179. package/dist/tokens/tokens.js +44 -3
  180. package/dist/utils/motion.js +1 -1
  181. package/package.json +71 -60
@@ -1,124 +1,179 @@
1
- <script lang="ts">
2
- import { cn } from '../../utils/cn.js';
3
- import Surface from '../primitives/Surface.svelte';
4
-
5
- interface MenuItem {
6
- label: string;
7
- value: string;
8
- disabled?: boolean;
9
- destructive?: boolean;
10
- }
11
-
12
- interface Props {
13
- /** Controls menu visibility. */
14
- open?: boolean;
15
- /** Menu items. */
16
- items?: MenuItem[];
17
- /** Additional CSS classes. */
18
- class?: string;
19
- /** Fires when an item is selected with its value. */
20
- onselect?: (value: string) => void;
21
- }
22
-
23
- let {
24
- open = false,
25
- items = [],
26
- class: className = '',
27
- onselect,
28
- }: Props = $props();
29
- </script>
30
-
31
- {#if open}
32
- <div class={cn('hyvui-dropdown', className)}>
33
- <Surface variant="card" class="hyvui-dropdown-surface">
34
- {#each items as item}
35
- <button
36
- type="button"
37
- class={cn(
38
- 'hyvui-dropdown-item',
39
- item.disabled && 'hyvui-dropdown-item-disabled',
40
- item.destructive && 'hyvui-dropdown-item-destructive'
41
- )}
42
- disabled={item.disabled}
43
- onclick={() => onselect?.(item.value)}
44
- >
45
- {item.label}
46
- </button>
47
- {/each}
48
- </Surface>
49
- </div>
50
- {/if}
51
-
52
- <style>
53
- .hyvui-dropdown {
54
- position: absolute;
55
- z-index: var(--z-overlay);
56
- min-width: 13rem;
57
- animation: dropdown-in 0.2s cubic-bezier(0.22, 1, 0.36, 1);
58
- }
59
-
60
- :global(.hyvui-dropdown-surface) {
61
- padding: var(--space-xs);
62
- }
63
-
64
- .hyvui-dropdown-item {
65
- display: block;
66
- width: 100%;
67
- text-align: left;
68
- font-family: var(--font-mono);
69
- font-size: 0.74rem;
70
- font-weight: 400;
71
- letter-spacing: 0.14em;
72
- text-transform: uppercase;
73
- color: var(--text-soft);
74
- background: none;
75
- border: none;
76
- border-radius: var(--radius-sm);
77
- padding: 0.75rem 0.85rem;
78
- cursor: pointer;
79
- transition:
80
- transform var(--transition-fast),
81
- color var(--transition-fast),
82
- background var(--transition-fast);
83
- }
84
-
85
- .hyvui-dropdown-item:hover:not(:disabled) {
86
- transform: translateX(4px);
87
- background: linear-gradient(90deg, rgba(199, 156, 87, 0.12), transparent 72%);
88
- color: var(--text);
89
- }
90
-
91
- .hyvui-dropdown-item-disabled {
92
- opacity: 0.4;
93
- cursor: not-allowed;
94
- }
95
-
96
- .hyvui-dropdown-item-destructive {
97
- color: var(--status-fail);
98
- }
99
-
100
- @keyframes dropdown-in {
101
- from {
102
- opacity: 0;
103
- transform: translateY(4px);
104
- }
105
- to {
106
- opacity: 1;
107
- transform: translateY(0);
108
- }
109
- }
110
-
111
- @media (prefers-reduced-motion: reduce) {
112
- .hyvui-dropdown {
113
- animation: none;
114
- }
115
-
116
- .hyvui-dropdown-item {
117
- transition: none;
118
- }
119
-
120
- .hyvui-dropdown-item:hover:not(:disabled) {
121
- transform: none;
122
- }
123
- }
124
- </style>
1
+ <script lang="ts">
2
+ import { cn } from '../../utils/cn.js';
3
+ import Popover from '../layout/Popover.svelte';
4
+ import type { Placement } from '@floating-ui/dom';
5
+ import type { Snippet } from 'svelte';
6
+
7
+ interface MenuItem {
8
+ label: string;
9
+ value: string;
10
+ disabled?: boolean;
11
+ destructive?: boolean;
12
+ }
13
+
14
+ /**
15
+ * @example
16
+ * <DropdownMenu
17
+ * items={[
18
+ * { label: 'edit', value: 'edit' },
19
+ * { label: 'delete', value: 'delete', destructive: true }
20
+ * ]}
21
+ * onselect={(val) => handleAction(val)}
22
+ * >
23
+ * {#snippet trigger()}<Button variant="ghost" size="sm">actions</Button>{/snippet}
24
+ * </DropdownMenu>
25
+ */
26
+ interface Props {
27
+ /** Menu items. */
28
+ items?: MenuItem[];
29
+ /** Controlled open state. If undefined, the menu manages its own state. */
30
+ open?: boolean;
31
+ /** Placement for the floating menu. */
32
+ placement?: Placement;
33
+ /** Offset in pixels from trigger. */
34
+ offset?: number;
35
+ /** Additional CSS classes. */
36
+ class?: string;
37
+ /** Trigger snippet (required for a usable menu). */
38
+ trigger?: Snippet;
39
+ /** Fires when an item is selected with its value. */
40
+ onselect?: (value: string) => void;
41
+ /** Fires when open state changes. */
42
+ onopenchange?: (open: boolean) => void;
43
+ }
44
+
45
+ let {
46
+ items = [],
47
+ open,
48
+ placement = 'bottom-end',
49
+ offset = 8,
50
+ class: className = '',
51
+ trigger,
52
+ onselect,
53
+ onopenchange
54
+ }: Props = $props();
55
+
56
+ let triggerEl: HTMLElement | null = $state(null);
57
+ let internalOpen = $state(false);
58
+
59
+ const controlled = $derived(open !== undefined);
60
+ const isOpen = $derived(controlled ? !!open : internalOpen);
61
+
62
+ function setOpen(next: boolean) {
63
+ if (!controlled) internalOpen = next;
64
+ onopenchange?.(next);
65
+ }
66
+
67
+ function toggle() {
68
+ setOpen(!isOpen);
69
+ }
70
+
71
+ function close() {
72
+ setOpen(false);
73
+ }
74
+ </script>
75
+
76
+ <div class={cn('hyvui-dropdown-root', className)}>
77
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
78
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
79
+ <span class="hyvui-dropdown-trigger" bind:this={triggerEl} onclick={toggle}>
80
+ {#if trigger}{@render trigger()}{/if}
81
+ </span>
82
+
83
+ <Popover
84
+ open={isOpen}
85
+ anchor={triggerEl}
86
+ {placement}
87
+ {offset}
88
+ onclose={close}
89
+ class="hyvui-dropdown-popover"
90
+ >
91
+ <div class="hyvui-dropdown-menu" role="menu">
92
+ {#each items as item}
93
+ <button
94
+ type="button"
95
+ role="menuitem"
96
+ class={cn(
97
+ 'hyvui-dropdown-item',
98
+ item.disabled && 'hyvui-dropdown-item-disabled',
99
+ item.destructive && 'hyvui-dropdown-item-destructive'
100
+ )}
101
+ disabled={item.disabled}
102
+ onclick={() => {
103
+ if (item.disabled) return;
104
+ onselect?.(item.value);
105
+ close();
106
+ }}
107
+ >
108
+ {item.label}
109
+ </button>
110
+ {/each}
111
+ </div>
112
+ </Popover>
113
+ </div>
114
+
115
+ <style>
116
+ .hyvui-dropdown-root {
117
+ display: inline-flex;
118
+ align-items: center;
119
+ }
120
+
121
+ .hyvui-dropdown-trigger {
122
+ display: inline-flex;
123
+ align-items: center;
124
+ }
125
+
126
+ :global(.hyvui-dropdown-popover) {
127
+ max-inline-size: min(90dvw, 18rem);
128
+ }
129
+
130
+ .hyvui-dropdown-menu {
131
+ padding: var(--space-xs);
132
+ }
133
+
134
+ .hyvui-dropdown-item {
135
+ display: block;
136
+ width: 100%;
137
+ text-align: left;
138
+ font-family: var(--font-mono);
139
+ font-size: 0.74rem;
140
+ font-weight: 400;
141
+ letter-spacing: 0.14em;
142
+ text-transform: uppercase;
143
+ color: var(--text-soft);
144
+ background: none;
145
+ border: none;
146
+ border-radius: var(--radius-sm);
147
+ padding: 0.75rem 0.85rem;
148
+ cursor: pointer;
149
+ transition:
150
+ transform var(--transition-fast),
151
+ color var(--transition-fast),
152
+ background var(--transition-fast);
153
+ }
154
+
155
+ .hyvui-dropdown-item:hover:not(:disabled) {
156
+ transform: translateX(4px);
157
+ background: linear-gradient(90deg, rgba(199, 156, 87, 0.12), transparent 72%);
158
+ color: var(--text);
159
+ }
160
+
161
+ .hyvui-dropdown-item-disabled {
162
+ opacity: 0.4;
163
+ cursor: not-allowed;
164
+ }
165
+
166
+ .hyvui-dropdown-item-destructive {
167
+ color: var(--status-fail);
168
+ }
169
+
170
+ @media (prefers-reduced-motion: reduce) {
171
+ .hyvui-dropdown-item {
172
+ transition: none;
173
+ }
174
+
175
+ .hyvui-dropdown-item:hover:not(:disabled) {
176
+ transform: none;
177
+ }
178
+ }
179
+ </style>
@@ -1,18 +1,40 @@
1
+ import type { Placement } from '@floating-ui/dom';
2
+ import type { Snippet } from 'svelte';
1
3
  interface MenuItem {
2
4
  label: string;
3
5
  value: string;
4
6
  disabled?: boolean;
5
7
  destructive?: boolean;
6
8
  }
9
+ /**
10
+ * @example
11
+ * <DropdownMenu
12
+ * items={[
13
+ * { label: 'edit', value: 'edit' },
14
+ * { label: 'delete', value: 'delete', destructive: true }
15
+ * ]}
16
+ * onselect={(val) => handleAction(val)}
17
+ * >
18
+ * {#snippet trigger()}<Button variant="ghost" size="sm">actions</Button>{/snippet}
19
+ * </DropdownMenu>
20
+ */
7
21
  interface Props {
8
- /** Controls menu visibility. */
9
- open?: boolean;
10
22
  /** Menu items. */
11
23
  items?: MenuItem[];
24
+ /** Controlled open state. If undefined, the menu manages its own state. */
25
+ open?: boolean;
26
+ /** Placement for the floating menu. */
27
+ placement?: Placement;
28
+ /** Offset in pixels from trigger. */
29
+ offset?: number;
12
30
  /** Additional CSS classes. */
13
31
  class?: string;
32
+ /** Trigger snippet (required for a usable menu). */
33
+ trigger?: Snippet;
14
34
  /** Fires when an item is selected with its value. */
15
35
  onselect?: (value: string) => void;
36
+ /** Fires when open state changes. */
37
+ onopenchange?: (open: boolean) => void;
16
38
  }
17
39
  declare const DropdownMenu: import("svelte").Component<Props, {}, "">;
18
40
  type DropdownMenu = ReturnType<typeof DropdownMenu>;
@@ -1,90 +1,96 @@
1
- <script lang="ts">
2
- import { cn } from '../../utils/cn.js';
3
-
4
- interface NavItem {
5
- label: string;
6
- href: string;
7
- active?: boolean;
8
- }
9
-
10
- interface Props {
11
- /** Navigation items. */
12
- items?: NavItem[];
13
- /** Additional CSS classes. */
14
- class?: string;
15
- /** Fires when a nav item is clicked. */
16
- onnavigate?: (item: NavItem) => void;
17
- }
18
-
19
- let {
20
- items = [],
21
- class: className = '',
22
- onnavigate,
23
- }: Props = $props();
24
- </script>
25
-
26
- <nav class={cn('hyvui-sidebar-nav', className)}>
27
- {#each items as item}
28
- <a
29
- href={item.href}
30
- class={cn('hyvui-sidebar-link', item.active && 'hyvui-sidebar-link-active')}
31
- onclick={(e) => {
32
- if (onnavigate) {
33
- e.preventDefault();
34
- onnavigate(item);
35
- }
36
- }}
37
- >
38
- {item.label}
39
- </a>
40
- {/each}
41
- </nav>
42
-
43
- <style>
44
- .hyvui-sidebar-nav {
45
- display: flex;
46
- flex-direction: column;
47
- gap: var(--space-2xs);
48
- }
49
-
50
- .hyvui-sidebar-link {
51
- position: relative;
52
- font-family: var(--font-mono);
53
- font-size: 0.7rem;
54
- font-weight: 400;
55
- letter-spacing: 0.16em;
56
- text-transform: uppercase;
57
- color: var(--muted);
58
- text-decoration: none;
59
- padding: 0.55rem 0.9rem;
60
- border-left: 1px solid transparent;
61
- min-width: 0;
62
- transition:
63
- color var(--transition-fast),
64
- transform var(--transition-fast),
65
- background var(--transition-fast),
66
- border-color var(--transition-fast);
67
- }
68
-
69
- .hyvui-sidebar-link:hover {
70
- color: var(--text-soft);
71
- background: linear-gradient(90deg, rgba(199, 156, 87, 0.08), transparent 76%);
72
- }
73
-
74
- .hyvui-sidebar-link-active {
75
- color: var(--accent);
76
- border-left-color: var(--line-strong);
77
- background: linear-gradient(90deg, rgba(199, 156, 87, 0.14), transparent 72%);
78
- transform: translateX(4px);
79
- }
80
-
81
- @media (prefers-reduced-motion: reduce) {
82
- .hyvui-sidebar-link {
83
- transition: none;
84
- }
85
-
86
- .hyvui-sidebar-link-active {
87
- transform: none;
88
- }
89
- }
90
- </style>
1
+ <script lang="ts">
2
+ import { cn } from '../../utils/cn.js';
3
+
4
+ interface NavItem {
5
+ label: string;
6
+ href: string;
7
+ active?: boolean;
8
+ }
9
+
10
+ /**
11
+ * @see reveal — add `use:reveal={{ target: '.badge' }}` on items for hover metadata.
12
+ * @example
13
+ * <SidebarNav items={[
14
+ * { label: 'overview', href: '/', active: true },
15
+ * { label: 'settings', href: '/settings' },
16
+ * { label: 'archive', href: '/archive' }
17
+ * ]} />
18
+ */
19
+ interface Props {
20
+ /** Navigation items. */
21
+ items?: NavItem[];
22
+ /** Additional CSS classes. */
23
+ class?: string;
24
+ /** Fires when a nav item is clicked. */
25
+ onnavigate?: (item: NavItem) => void;
26
+ }
27
+
28
+ let { items = [], class: className = '', onnavigate }: Props = $props();
29
+ </script>
30
+
31
+ <nav class={cn('hyvui-sidebar-nav', className)}>
32
+ {#each items as item}
33
+ <a
34
+ href={item.href}
35
+ class={cn('hyvui-sidebar-link', item.active && 'hyvui-sidebar-link-active')}
36
+ onclick={(e) => {
37
+ if (onnavigate) {
38
+ e.preventDefault();
39
+ onnavigate(item);
40
+ }
41
+ }}
42
+ >
43
+ {item.label}
44
+ </a>
45
+ {/each}
46
+ </nav>
47
+
48
+ <style>
49
+ .hyvui-sidebar-nav {
50
+ display: flex;
51
+ flex-direction: column;
52
+ gap: var(--space-2xs);
53
+ }
54
+
55
+ .hyvui-sidebar-link {
56
+ position: relative;
57
+ font-family: var(--font-mono);
58
+ font-size: 0.7rem;
59
+ font-weight: 400;
60
+ letter-spacing: 0.16em;
61
+ text-transform: uppercase;
62
+ color: var(--muted);
63
+ text-decoration: none;
64
+ padding: 0.55rem 0.9rem;
65
+ border-left: 1px solid transparent;
66
+ min-width: 0;
67
+ transition:
68
+ color var(--transition-fast),
69
+ transform var(--transition-fast),
70
+ background var(--transition-fast),
71
+ border-color var(--transition-fast);
72
+ }
73
+
74
+ .hyvui-sidebar-link:hover {
75
+ color: var(--text-soft);
76
+ background: linear-gradient(90deg, rgba(199, 156, 87, 0.08), transparent 76%);
77
+ transform: translateX(2px);
78
+ }
79
+
80
+ .hyvui-sidebar-link-active {
81
+ color: var(--accent);
82
+ border-left-color: var(--line-strong);
83
+ background: linear-gradient(90deg, rgba(199, 156, 87, 0.14), transparent 72%);
84
+ transform: translateX(4px);
85
+ }
86
+
87
+ @media (prefers-reduced-motion: reduce) {
88
+ .hyvui-sidebar-link {
89
+ transition: none;
90
+ }
91
+
92
+ .hyvui-sidebar-link-active {
93
+ transform: none;
94
+ }
95
+ }
96
+ </style>
@@ -3,6 +3,15 @@ interface NavItem {
3
3
  href: string;
4
4
  active?: boolean;
5
5
  }
6
+ /**
7
+ * @see reveal — add `use:reveal={{ target: '.badge' }}` on items for hover metadata.
8
+ * @example
9
+ * <SidebarNav items={[
10
+ * { label: 'overview', href: '/', active: true },
11
+ * { label: 'settings', href: '/settings' },
12
+ * { label: 'archive', href: '/archive' }
13
+ * ]} />
14
+ */
6
15
  interface Props {
7
16
  /** Navigation items. */
8
17
  items?: NavItem[];