@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,67 +1,188 @@
1
- <script lang="ts">
2
- import { cn } from '../../utils/cn.js';
3
- import Surface from '../primitives/Surface.svelte';
4
- import type { Snippet } from 'svelte';
5
-
6
- interface Props {
7
- /** Controls popover visibility. */
8
- open?: boolean;
9
- /** Placement relative to anchor. */
10
- placement?: 'top' | 'bottom' | 'left' | 'right';
11
- /** Additional CSS classes. */
12
- class?: string;
13
- /** Popover content. */
14
- children?: Snippet;
15
- }
16
-
17
- let {
18
- open = false,
19
- placement = 'bottom',
20
- class: className = '',
21
- children,
22
- }: Props = $props();
23
-
24
- const placementStyles: Record<string, string> = {
25
- top: 'bottom: 100%; left: 50%; transform: translateX(-50%); margin-bottom: 0.5rem;',
26
- bottom: 'top: 100%; left: 50%; transform: translateX(-50%); margin-top: 0.5rem;',
27
- left: 'right: 100%; top: 50%; transform: translateY(-50%); margin-right: 0.5rem;',
28
- right: 'left: 100%; top: 50%; transform: translateY(-50%); margin-left: 0.5rem;',
29
- };
30
- </script>
31
-
32
- {#if open}
33
- <div class={cn('hyvui-popover', className)} style={placementStyles[placement]}>
34
- <Surface variant="card" class="hyvui-popover-surface">
35
- {#if children}{@render children()}{/if}
36
- </Surface>
37
- </div>
38
- {/if}
39
-
40
- <style>
41
- .hyvui-popover {
42
- position: absolute;
43
- z-index: var(--z-overlay);
44
- animation: popover-in 0.2s cubic-bezier(0.22, 1, 0.36, 1);
45
- }
46
-
47
- :global(.hyvui-popover-surface) {
48
- padding: 0.5rem 0.75rem;
49
- }
50
-
51
- @keyframes popover-in {
52
- from {
53
- opacity: 0;
54
- transform: translateX(-50%) translateY(4px);
55
- }
56
- to {
57
- opacity: 1;
58
- transform: translateX(-50%) translateY(0);
59
- }
60
- }
61
-
62
- @media (prefers-reduced-motion: reduce) {
63
- .hyvui-popover {
64
- animation: none;
65
- }
66
- }
67
- </style>
1
+ <script lang="ts">
2
+ import { cn } from '../../utils/cn.js';
3
+ import Surface from '../primitives/Surface.svelte';
4
+ import type { Snippet } from 'svelte';
5
+ import {
6
+ autoUpdate,
7
+ computePosition,
8
+ flip,
9
+ offset as fuiOffset,
10
+ shift,
11
+ size as fuiSize,
12
+ type Placement
13
+ } from '@floating-ui/dom';
14
+
15
+ // In SSR builds, Svelte strips $effect bodies, which can make these imports appear unused to Rollup.
16
+ // Keeping a tiny reference avoids noisy build warnings without changing runtime behavior.
17
+ const _fui = [autoUpdate, computePosition, flip, fuiOffset, shift, fuiSize];
18
+ void _fui;
19
+
20
+ /**
21
+ * Typically used via DropdownMenu. Use directly only when you need full positioning control.
22
+ * Requires an `anchor` HTMLElement ref and a controlled `open` boolean.
23
+ * @example
24
+ * <button bind:this={anchorEl} onclick={() => open = true}>open</button>
25
+ * <Popover {open} anchor={anchorEl} placement="bottom-start" onclose={() => open = false}>
26
+ * <Text variant="caption">popover content</Text>
27
+ * </Popover>
28
+ */
29
+ interface Props {
30
+ /** Controls popover visibility. */
31
+ open?: boolean;
32
+ /** Anchor element the popover positions against. */
33
+ anchor?: HTMLElement | null;
34
+ /** Placement relative to anchor. */
35
+ placement?: Placement;
36
+ /** Offset in pixels from the anchor. */
37
+ offset?: number;
38
+ /** When true, move the popover element to document.body on mount. */
39
+ portal?: boolean;
40
+ /** Additional CSS classes. */
41
+ class?: string;
42
+ /** Popover content. */
43
+ children?: Snippet;
44
+ /** Fires when the popover should close (outside click, Escape). */
45
+ onclose?: () => void;
46
+ }
47
+
48
+ let {
49
+ open = false,
50
+ anchor = null,
51
+ placement = 'bottom-start',
52
+ offset = 8,
53
+ portal = true,
54
+ class: className = '',
55
+ children,
56
+ onclose
57
+ }: Props = $props();
58
+
59
+ let popoverEl: HTMLDivElement | undefined = $state();
60
+
61
+ function close() {
62
+ onclose?.();
63
+ }
64
+
65
+ $effect(() => {
66
+ if (typeof document === 'undefined') return;
67
+ if (!portal) return;
68
+ if (!popoverEl) return;
69
+
70
+ // Manual portal: move the floating node to document.body. Svelte 5's event
71
+ // delegation supports this (see internal render.js comment re: portals).
72
+ document.body.appendChild(popoverEl);
73
+
74
+ return () => {
75
+ popoverEl?.remove();
76
+ };
77
+ });
78
+
79
+ $effect(() => {
80
+ if (typeof window === 'undefined') return;
81
+ if (!open) return;
82
+ if (!anchor || !popoverEl) return;
83
+
84
+ const a = anchor;
85
+ const el = popoverEl;
86
+
87
+ function position() {
88
+ computePosition(a, el, {
89
+ placement,
90
+ strategy: 'fixed',
91
+ middleware: [
92
+ fuiOffset(offset),
93
+ flip(),
94
+ shift({ padding: 8 }),
95
+ fuiSize({
96
+ padding: 8,
97
+ apply({ availableWidth, availableHeight, elements }) {
98
+ Object.assign(elements.floating.style, {
99
+ maxWidth: `${Math.max(0, availableWidth)}px`,
100
+ maxHeight: `${Math.max(0, availableHeight)}px`
101
+ });
102
+ }
103
+ })
104
+ ]
105
+ }).then(({ x, y }) => {
106
+ Object.assign(el.style, {
107
+ left: `${x}px`,
108
+ top: `${y}px`
109
+ });
110
+ });
111
+ }
112
+
113
+ position();
114
+
115
+ const stop = autoUpdate(a, el, position);
116
+
117
+ function onPointerDown(e: PointerEvent) {
118
+ const t = e.target as Node | null;
119
+ if (!t) return;
120
+ if (a.contains(t) || el.contains(t)) return;
121
+ close();
122
+ }
123
+
124
+ function onKeyDown(e: KeyboardEvent) {
125
+ if (e.key === 'Escape') close();
126
+ }
127
+
128
+ const pointerOpts: AddEventListenerOptions = { capture: true };
129
+ window.addEventListener('pointerdown', onPointerDown, pointerOpts);
130
+ window.addEventListener('keydown', onKeyDown);
131
+
132
+ return () => {
133
+ stop();
134
+ window.removeEventListener('pointerdown', onPointerDown, pointerOpts);
135
+ window.removeEventListener('keydown', onKeyDown);
136
+ };
137
+ });
138
+ </script>
139
+
140
+ {#if open && anchor}
141
+ <div bind:this={popoverEl} class={cn('hyvui-popover', className)}>
142
+ <Surface variant="card" class="hyvui-popover-surface">
143
+ <div class="hyvui-popover-content">
144
+ {#if children}{@render children()}{/if}
145
+ </div>
146
+ </Surface>
147
+ </div>
148
+ {/if}
149
+
150
+ <style>
151
+ .hyvui-popover {
152
+ position: fixed;
153
+ z-index: var(--z-overlay);
154
+ left: 0;
155
+ top: 0;
156
+ backface-visibility: hidden;
157
+ animation: popover-in 0.2s cubic-bezier(0.22, 1, 0.36, 1);
158
+ max-inline-size: min(90dvw, 28rem);
159
+ }
160
+
161
+ :global(.hyvui-popover-surface) {
162
+ padding: 0;
163
+ }
164
+
165
+ .hyvui-popover-content {
166
+ padding: 0.5rem 0.75rem;
167
+ max-block-size: min(60dvh, 32rem);
168
+ overflow: auto;
169
+ overscroll-behavior: contain;
170
+ }
171
+
172
+ @keyframes popover-in {
173
+ from {
174
+ opacity: 0;
175
+ transform: translateY(4px);
176
+ }
177
+ to {
178
+ opacity: 1;
179
+ transform: translateY(0);
180
+ }
181
+ }
182
+
183
+ @media (prefers-reduced-motion: reduce) {
184
+ .hyvui-popover {
185
+ animation: none;
186
+ }
187
+ }
188
+ </style>
@@ -1,13 +1,31 @@
1
1
  import type { Snippet } from 'svelte';
2
+ import { type Placement } from '@floating-ui/dom';
3
+ /**
4
+ * Typically used via DropdownMenu. Use directly only when you need full positioning control.
5
+ * Requires an `anchor` HTMLElement ref and a controlled `open` boolean.
6
+ * @example
7
+ * <button bind:this={anchorEl} onclick={() => open = true}>open</button>
8
+ * <Popover {open} anchor={anchorEl} placement="bottom-start" onclose={() => open = false}>
9
+ * <Text variant="caption">popover content</Text>
10
+ * </Popover>
11
+ */
2
12
  interface Props {
3
13
  /** Controls popover visibility. */
4
14
  open?: boolean;
15
+ /** Anchor element the popover positions against. */
16
+ anchor?: HTMLElement | null;
5
17
  /** Placement relative to anchor. */
6
- placement?: 'top' | 'bottom' | 'left' | 'right';
18
+ placement?: Placement;
19
+ /** Offset in pixels from the anchor. */
20
+ offset?: number;
21
+ /** When true, move the popover element to document.body on mount. */
22
+ portal?: boolean;
7
23
  /** Additional CSS classes. */
8
24
  class?: string;
9
25
  /** Popover content. */
10
26
  children?: Snippet;
27
+ /** Fires when the popover should close (outside click, Escape). */
28
+ onclose?: () => void;
11
29
  }
12
30
  declare const Popover: import("svelte").Component<Props, {}, "">;
13
31
  type Popover = ReturnType<typeof Popover>;
@@ -1,53 +1,65 @@
1
- <script lang="ts">
2
- import { cn } from '../../utils/cn.js';
3
- import type { Snippet } from 'svelte';
4
-
5
- interface Props {
6
- /** Stack direction. */
7
- direction?: 'vertical' | 'horizontal';
8
- /** Gap between items (CSS size string). */
9
- gap?: string;
10
- /** CSS align-items value. */
11
- align?: string;
12
- /** CSS justify-content value. */
13
- justify?: string;
14
- /** Enable flex-wrap. */
15
- wrap?: boolean;
16
- /** HTML tag to render. */
17
- as?: string;
18
- /** Additional CSS classes. */
19
- class?: string;
20
- /** Stack children. */
21
- children?: Snippet;
22
- }
23
-
24
- let {
25
- direction = 'vertical',
26
- gap = 'var(--space-md)',
27
- align = 'stretch',
28
- justify = 'flex-start',
29
- wrap = false,
30
- as = 'div',
31
- class: className = '',
32
- children,
33
- }: Props = $props();
34
- </script>
35
-
36
- <svelte:element
37
- this={as}
38
- class={cn('hyvui-stack', className)}
39
- style:flex-direction={direction === 'horizontal' ? 'row' : 'column'}
40
- style:gap={gap}
41
- style:align-items={align}
42
- style:justify-content={justify}
43
- style:flex-wrap={wrap ? 'wrap' : 'nowrap'}
44
- >
45
- {#if children}{@render children()}{/if}
46
- </svelte:element>
47
-
48
- <style>
49
- .hyvui-stack {
50
- display: flex;
51
- min-width: 0;
52
- }
53
- </style>
1
+ <script lang="ts">
2
+ import { cn } from '../../utils/cn.js';
3
+ import type { Snippet } from 'svelte';
4
+
5
+ /**
6
+ * @see surface — add `use:surface` on Stack for an entrance animation on mount.
7
+ * @example
8
+ * <Stack gap="var(--space-lg)">
9
+ * <Text variant="heading">title</Text>
10
+ * <Text>body text here.</Text>
11
+ * </Stack>
12
+ * <Stack direction="horizontal" align="center" gap="0.75rem">
13
+ * <Button variant="primary">confirm</Button>
14
+ * <Button variant="ghost">cancel</Button>
15
+ * </Stack>
16
+ */
17
+ interface Props {
18
+ /** Stack direction. */
19
+ direction?: 'vertical' | 'horizontal';
20
+ /** Gap between items (CSS size string). */
21
+ gap?: string;
22
+ /** CSS align-items value. */
23
+ align?: string;
24
+ /** CSS justify-content value. */
25
+ justify?: string;
26
+ /** Enable flex-wrap. */
27
+ wrap?: boolean;
28
+ /** HTML tag to render. */
29
+ as?: string;
30
+ /** Additional CSS classes. */
31
+ class?: string;
32
+ /** Stack children. */
33
+ children?: Snippet;
34
+ }
35
+
36
+ let {
37
+ direction = 'vertical',
38
+ gap = 'var(--space-md)',
39
+ align = 'stretch',
40
+ justify = 'flex-start',
41
+ wrap = false,
42
+ as = 'div',
43
+ class: className = '',
44
+ children
45
+ }: Props = $props();
46
+ </script>
47
+
48
+ <svelte:element
49
+ this={as}
50
+ class={cn('hyvui-stack', className)}
51
+ style:flex-direction={direction === 'horizontal' ? 'row' : 'column'}
52
+ style:gap
53
+ style:align-items={align}
54
+ style:justify-content={justify}
55
+ style:flex-wrap={wrap ? 'wrap' : 'nowrap'}
56
+ >
57
+ {#if children}{@render children()}{/if}
58
+ </svelte:element>
59
+
60
+ <style>
61
+ .hyvui-stack {
62
+ display: flex;
63
+ min-width: 0;
64
+ }
65
+ </style>
@@ -1,4 +1,16 @@
1
1
  import type { Snippet } from 'svelte';
2
+ /**
3
+ * @see surface — add `use:surface` on Stack for an entrance animation on mount.
4
+ * @example
5
+ * <Stack gap="var(--space-lg)">
6
+ * <Text variant="heading">title</Text>
7
+ * <Text>body text here.</Text>
8
+ * </Stack>
9
+ * <Stack direction="horizontal" align="center" gap="0.75rem">
10
+ * <Button variant="primary">confirm</Button>
11
+ * <Button variant="ghost">cancel</Button>
12
+ * </Stack>
13
+ */
2
14
  interface Props {
3
15
  /** Stack direction. */
4
16
  direction?: 'vertical' | 'horizontal';
@@ -1,73 +1,78 @@
1
- <script lang="ts">
2
- import { cn } from '../../utils/cn.js';
3
-
4
- interface BreadcrumbItem {
5
- label: string;
6
- href?: string;
7
- }
8
-
9
- interface Props {
10
- /** Breadcrumb trail items. */
11
- items?: BreadcrumbItem[];
12
- /** Additional CSS classes. */
13
- class?: string;
14
- }
15
-
16
- let {
17
- items = [],
18
- class: className = '',
19
- }: Props = $props();
20
- </script>
21
-
22
- <nav class={cn('hyvui-breadcrumb', className)} aria-label="breadcrumb">
23
- {#each items as item, i}
24
- {#if i > 0}
25
- <span class="hyvui-breadcrumb-sep">/</span>
26
- {/if}
27
- {#if item.href && i < items.length - 1}
28
- <a href={item.href} class="hyvui-breadcrumb-link">{item.label}</a>
29
- {:else}
30
- <span class="hyvui-breadcrumb-current">{item.label}</span>
31
- {/if}
32
- {/each}
33
- </nav>
34
-
35
- <style>
36
- .hyvui-breadcrumb {
37
- display: flex;
38
- align-items: center;
39
- flex-wrap: wrap;
40
- gap: var(--space-xs);
41
- font-family: var(--font-mono);
42
- font-size: 0.68rem;
43
- letter-spacing: 0.16em;
44
- text-transform: uppercase;
45
- min-width: 0;
46
- }
47
-
48
- .hyvui-breadcrumb-sep {
49
- color: var(--muted-strong);
50
- opacity: 0.7;
51
- }
52
-
53
- .hyvui-breadcrumb-link {
54
- color: var(--muted);
55
- text-decoration: none;
56
- transition: color var(--transition-fast);
57
- }
58
-
59
- .hyvui-breadcrumb-link:hover {
60
- color: var(--accent);
61
- }
62
-
63
- .hyvui-breadcrumb-current {
64
- color: var(--text-soft);
65
- white-space: nowrap;
66
- }
67
-
68
- @media (prefers-reduced-motion: reduce) {
69
- .hyvui-breadcrumb-link {
70
- transition: none;
71
- }
72
- }
73
- </style>
1
+ <script lang="ts">
2
+ import { cn } from '../../utils/cn.js';
3
+
4
+ interface BreadcrumbItem {
5
+ label: string;
6
+ href?: string;
7
+ }
8
+
9
+ /**
10
+ * @example
11
+ * <Breadcrumb items={[
12
+ * { label: 'home', href: '/' },
13
+ * { label: 'projects', href: '/projects' },
14
+ * { label: 'alpha' }
15
+ * ]} />
16
+ */
17
+ interface Props {
18
+ /** Breadcrumb trail items. */
19
+ items?: BreadcrumbItem[];
20
+ /** Additional CSS classes. */
21
+ class?: string;
22
+ }
23
+
24
+ let { items = [], class: className = '' }: Props = $props();
25
+ </script>
26
+
27
+ <nav class={cn('hyvui-breadcrumb', className)} aria-label="breadcrumb">
28
+ {#each items as item, i}
29
+ {#if i > 0}
30
+ <span class="hyvui-breadcrumb-sep">/</span>
31
+ {/if}
32
+ {#if item.href && i < items.length - 1}
33
+ <a href={item.href} class="hyvui-breadcrumb-link">{item.label}</a>
34
+ {:else}
35
+ <span class="hyvui-breadcrumb-current">{item.label}</span>
36
+ {/if}
37
+ {/each}
38
+ </nav>
39
+
40
+ <style>
41
+ .hyvui-breadcrumb {
42
+ display: flex;
43
+ align-items: center;
44
+ flex-wrap: wrap;
45
+ gap: var(--space-xs);
46
+ font-family: var(--font-mono);
47
+ font-size: 0.68rem;
48
+ letter-spacing: 0.16em;
49
+ text-transform: uppercase;
50
+ min-width: 0;
51
+ }
52
+
53
+ .hyvui-breadcrumb-sep {
54
+ color: var(--muted-strong);
55
+ opacity: 0.7;
56
+ }
57
+
58
+ .hyvui-breadcrumb-link {
59
+ color: var(--muted);
60
+ text-decoration: none;
61
+ transition: color var(--transition-fast);
62
+ }
63
+
64
+ .hyvui-breadcrumb-link:hover {
65
+ color: var(--accent);
66
+ }
67
+
68
+ .hyvui-breadcrumb-current {
69
+ color: var(--text-soft);
70
+ white-space: nowrap;
71
+ }
72
+
73
+ @media (prefers-reduced-motion: reduce) {
74
+ .hyvui-breadcrumb-link {
75
+ transition: none;
76
+ }
77
+ }
78
+ </style>
@@ -2,6 +2,14 @@ interface BreadcrumbItem {
2
2
  label: string;
3
3
  href?: string;
4
4
  }
5
+ /**
6
+ * @example
7
+ * <Breadcrumb items={[
8
+ * { label: 'home', href: '/' },
9
+ * { label: 'projects', href: '/projects' },
10
+ * { label: 'alpha' }
11
+ * ]} />
12
+ */
5
13
  interface Props {
6
14
  /** Breadcrumb trail items. */
7
15
  items?: BreadcrumbItem[];