@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,237 +1,310 @@
1
- <script lang="ts">
2
- import { cn } from '../../utils/cn.js';
3
- import type { Snippet } from 'svelte';
4
- import { echo as echoAction } from '../../system/actions/echo.js';
5
-
6
- interface Props {
7
- /** Button visual style. */
8
- variant?: 'primary' | 'secondary' | 'ghost' | 'destructive';
9
- /** Button size. */
10
- size?: 'sm' | 'md';
11
- /** Disables the button. */
12
- disabled?: boolean;
13
- /** Shows a pending status indicator instead of the label. */
14
- loading?: boolean;
15
- /** Enables the click echo ripple. */
16
- echo?: boolean;
17
- /** Additional CSS classes. */
18
- class?: string;
19
- /** Button type attribute. */
20
- type?: 'button' | 'submit' | 'reset';
21
- /** Optional href to render an anchor instead of a button. */
22
- href?: string;
23
- /** Anchor target. */
24
- target?: string;
25
- /** Anchor rel. */
26
- rel?: string;
27
- /** Click handler. */
28
- onclick?: (e: MouseEvent) => void;
29
- /** Button label content. */
30
- children?: Snippet;
31
- }
32
-
33
- let {
34
- variant = 'secondary',
35
- size = 'md',
36
- disabled = false,
37
- loading = false,
38
- echo = false,
39
- class: className = '',
40
- type = 'button',
41
- href,
42
- target,
43
- rel,
44
- onclick,
45
- children,
46
- }: Props = $props();
47
-
48
- function activeEcho(node: HTMLElement) {
49
- if (!echo) return {};
50
- return echoAction(node);
51
- }
52
-
53
- function handleAnchorClick(e: MouseEvent) {
54
- if (disabled || loading) {
55
- e.preventDefault();
56
- return;
57
- }
58
-
59
- onclick?.(e);
60
- }
61
- </script>
62
-
63
- {#if href}
64
- <a
65
- {href}
66
- {target}
67
- {rel}
68
- use:activeEcho
69
- class={cn(
70
- 'hyvui-btn',
71
- `hyvui-btn-${variant}`,
72
- `hyvui-btn-${size}`,
73
- loading && 'hyvui-btn-loading',
74
- disabled && 'hyvui-btn-disabled',
75
- className
76
- )}
77
- aria-disabled={disabled || loading}
78
- tabindex={disabled || loading ? -1 : undefined}
79
- onclick={handleAnchorClick}
80
- >
81
- {#if loading}
82
- <span class="hyvui-btn-dot" aria-label="loading"></span>
83
- {:else if children}
84
- {@render children()}
85
- {/if}
86
- </a>
87
- {:else}
88
- <button
89
- {type}
90
- use:activeEcho
91
- class={cn(
92
- 'hyvui-btn',
93
- `hyvui-btn-${variant}`,
94
- `hyvui-btn-${size}`,
95
- loading && 'hyvui-btn-loading',
96
- className
97
- )}
98
- disabled={disabled || loading}
99
- {onclick}
100
- >
101
- {#if loading}
102
- <span class="hyvui-btn-dot" aria-label="loading"></span>
103
- {:else if children}
104
- {@render children()}
105
- {/if}
106
- </button>
107
- {/if}
108
-
109
- <style>
110
- .hyvui-btn {
111
- position: relative;
112
- overflow: clip;
113
- font-family: var(--font-mono);
114
- font-size: 0.72rem;
115
- font-weight: 400;
116
- letter-spacing: 0.16em;
117
- text-transform: uppercase;
118
- border: 1px solid var(--line);
119
- border-radius: var(--radius-md);
120
- cursor: pointer;
121
- display: inline-flex;
122
- align-items: center;
123
- justify-content: center;
124
- gap: var(--control-gap);
125
- transition:
126
- color var(--transition-smooth),
127
- border-color var(--transition-smooth),
128
- background var(--transition-smooth),
129
- transform var(--transition-smooth),
130
- box-shadow var(--transition-smooth);
131
- white-space: nowrap;
132
- text-decoration: none;
133
- line-height: 1;
134
- max-width: 100%;
135
- box-shadow: var(--surface-stroke);
136
- }
137
-
138
- .hyvui-btn:disabled,
139
- .hyvui-btn-disabled {
140
- opacity: 0.46;
141
- cursor: not-allowed;
142
- transform: none !important;
143
- box-shadow: none;
144
- }
145
-
146
- .hyvui-btn-md {
147
- min-height: var(--control-height-md);
148
- padding: 0.75rem 1.15rem;
149
- }
150
-
151
- .hyvui-btn-sm {
152
- min-height: var(--control-height-sm);
153
- padding: 0.5rem 0.8rem;
154
- font-size: 0.68rem;
155
- }
156
-
157
- /* primary */
158
- .hyvui-btn-primary {
159
- background:
160
- linear-gradient(180deg, color-mix(in srgb, var(--accent-strong) 22%, transparent), transparent 70%),
161
- linear-gradient(135deg, var(--accent), var(--accent-strong));
162
- color: var(--bg);
163
- border-color: color-mix(in srgb, var(--accent-strong) 45%, var(--accent));
164
- box-shadow:
165
- inset 0 1px 0 rgba(255, 255, 255, 0.16),
166
- 0 14px 26px rgba(199, 156, 87, 0.16);
167
- }
168
-
169
- .hyvui-btn-primary:hover:not(:disabled):not(.hyvui-btn-disabled) {
170
- transform: translateY(-2px);
171
- filter: brightness(1.03);
172
- }
173
-
174
- /* secondary */
175
- .hyvui-btn-secondary {
176
- background:
177
- linear-gradient(180deg, rgba(121, 166, 163, 0.06), transparent 62%),
178
- rgba(10, 12, 14, 0.74);
179
- color: var(--text-soft);
180
- border-color: var(--line-strong);
181
- }
182
-
183
- .hyvui-btn-secondary:hover:not(:disabled):not(.hyvui-btn-disabled) {
184
- transform: translateY(-2px);
185
- border-color: color-mix(in srgb, var(--accent) 46%, var(--line-strong));
186
- color: var(--text);
187
- }
188
-
189
- /* ghost */
190
- .hyvui-btn-ghost {
191
- background: transparent;
192
- color: var(--muted);
193
- border-color: transparent;
194
- box-shadow: none;
195
- }
196
-
197
- .hyvui-btn-ghost:hover:not(:disabled):not(.hyvui-btn-disabled) {
198
- background: linear-gradient(90deg, rgba(199, 156, 87, 0.12), transparent 78%);
199
- color: var(--text);
200
- transform: translateX(2px);
201
- }
202
-
203
- /* destructive */
204
- .hyvui-btn-destructive {
205
- background: rgba(10, 12, 14, 0.74);
206
- color: var(--text-soft);
207
- border-color: rgba(182, 106, 72, 0.34);
208
- }
209
-
210
- .hyvui-btn-destructive:hover:not(:disabled):not(.hyvui-btn-disabled) {
211
- background-color: rgba(182, 106, 72, 0.1);
212
- transform: translateY(-2px);
213
- }
214
-
215
- /* loading dot */
216
- .hyvui-btn-dot {
217
- width: 6px;
218
- height: 6px;
219
- border-radius: 50%;
220
- background-color: var(--status-pend);
221
- animation: pulse-dot 2s ease-in-out infinite;
222
- }
223
-
224
- @media (prefers-reduced-motion: reduce) {
225
- .hyvui-btn {
226
- transition: none;
227
- }
228
-
229
- .hyvui-btn:hover:not(:disabled):not(.hyvui-btn-disabled) {
230
- transform: none;
231
- }
232
-
233
- .hyvui-btn-dot {
234
- animation: none;
235
- }
236
- }
237
- </style>
1
+ <script lang="ts">
2
+ import { cn } from '../../utils/cn.js';
3
+ import type { Snippet } from 'svelte';
4
+ import { echo as echoAction } from '../../system/actions/echo.js';
5
+
6
+ /**
7
+ * @see echo — add `echo` prop (or `use:echo` directly) for a gold click-pulse ripple.
8
+ * @example
9
+ * <Button variant="primary" onclick={handleSubmit}>submit</Button>
10
+ * <Button variant="ghost" href="/back">go back</Button>
11
+ * <Button variant="destructive" loading>deleting...</Button>
12
+ * <Button variant="primary" echo onclick={confirm}>confirm</Button>
13
+ */
14
+ interface Props {
15
+ /** Button visual style. */
16
+ variant?: 'primary' | 'secondary' | 'ghost' | 'destructive';
17
+ /** Button size. */
18
+ size?: 'sm' | 'md';
19
+ /** Disables the button. */
20
+ disabled?: boolean;
21
+ /** Shows a pending status indicator instead of the label. */
22
+ loading?: boolean;
23
+ /** Enables the click echo ripple. */
24
+ echo?: boolean;
25
+ /** Additional CSS classes. */
26
+ class?: string;
27
+ /** Button type attribute. */
28
+ type?: 'button' | 'submit' | 'reset';
29
+ /** Optional href to render an anchor instead of a button. */
30
+ href?: string;
31
+ /** Anchor target. */
32
+ target?: string;
33
+ /** Anchor rel. */
34
+ rel?: string;
35
+ /** Click handler. */
36
+ onclick?: (e: MouseEvent) => void;
37
+ /** Button label content. */
38
+ children?: Snippet;
39
+ }
40
+
41
+ let {
42
+ variant = 'secondary',
43
+ size = 'md',
44
+ disabled = false,
45
+ loading = false,
46
+ echo = false,
47
+ class: className = '',
48
+ type = 'button',
49
+ href,
50
+ target,
51
+ rel,
52
+ onclick,
53
+ children
54
+ }: Props = $props();
55
+
56
+ function activeEcho(node: HTMLElement) {
57
+ if (!echo) return {};
58
+ return echoAction(node);
59
+ }
60
+
61
+ function handleAnchorClick(e: MouseEvent) {
62
+ if (disabled || loading) {
63
+ e.preventDefault();
64
+ return;
65
+ }
66
+
67
+ onclick?.(e);
68
+ }
69
+ </script>
70
+
71
+ {#if href}
72
+ <a
73
+ {href}
74
+ {target}
75
+ {rel}
76
+ use:activeEcho
77
+ class={cn(
78
+ 'hyvui-btn',
79
+ `hyvui-btn-${variant}`,
80
+ `hyvui-btn-${size}`,
81
+ loading && 'hyvui-btn-loading',
82
+ disabled && 'hyvui-btn-disabled',
83
+ className
84
+ )}
85
+ aria-disabled={disabled || loading}
86
+ tabindex={disabled || loading ? -1 : undefined}
87
+ onclick={handleAnchorClick}
88
+ >
89
+ {#if loading}
90
+ <span class="hyvui-btn-dot" aria-label="loading"></span>
91
+ {:else if children}
92
+ {@render children()}
93
+ {/if}
94
+ </a>
95
+ {:else}
96
+ <button
97
+ {type}
98
+ use:activeEcho
99
+ class={cn(
100
+ 'hyvui-btn',
101
+ `hyvui-btn-${variant}`,
102
+ `hyvui-btn-${size}`,
103
+ loading && 'hyvui-btn-loading',
104
+ className
105
+ )}
106
+ disabled={disabled || loading}
107
+ {onclick}
108
+ >
109
+ {#if loading}
110
+ <span class="hyvui-btn-dot" aria-label="loading"></span>
111
+ {:else if children}
112
+ {@render children()}
113
+ {/if}
114
+ </button>
115
+ {/if}
116
+
117
+ <style>
118
+ .hyvui-btn {
119
+ position: relative;
120
+ overflow: clip;
121
+ font-family: var(--font-mono);
122
+ font-size: 0.72rem;
123
+ font-weight: 400;
124
+ letter-spacing: 0.16em;
125
+ text-transform: uppercase;
126
+ border: 1px solid var(--line);
127
+ border-radius: var(--radius-md);
128
+ cursor: pointer;
129
+ display: inline-flex;
130
+ align-items: center;
131
+ justify-content: center;
132
+ gap: var(--control-gap);
133
+ transition:
134
+ color var(--transition-fast),
135
+ border-color var(--transition-fast),
136
+ background var(--transition-fast),
137
+ filter var(--transition-fast),
138
+ transform var(--transition-smooth),
139
+ box-shadow var(--transition-smooth);
140
+ white-space: nowrap;
141
+ text-decoration: none;
142
+ line-height: 1;
143
+ max-width: 100%;
144
+ box-shadow: var(--surface-stroke);
145
+ }
146
+
147
+ .hyvui-btn:disabled,
148
+ .hyvui-btn-disabled {
149
+ opacity: 0.46;
150
+ cursor: not-allowed;
151
+ transform: none !important;
152
+ box-shadow: none;
153
+ }
154
+
155
+ .hyvui-btn-md {
156
+ min-height: var(--control-height-md);
157
+ padding: 0.75rem 1.15rem;
158
+ }
159
+
160
+ .hyvui-btn-sm {
161
+ min-height: var(--control-height-sm);
162
+ padding: 0.5rem 0.8rem;
163
+ font-size: 0.68rem;
164
+ }
165
+
166
+ /* primary */
167
+ .hyvui-btn-primary {
168
+ background:
169
+ linear-gradient(
170
+ 180deg,
171
+ color-mix(in srgb, var(--accent-strong) 22%, transparent),
172
+ transparent 70%
173
+ ),
174
+ linear-gradient(135deg, var(--accent), var(--accent-strong));
175
+ color: var(--bg);
176
+ border-color: color-mix(in srgb, var(--accent-strong) 45%, var(--accent));
177
+ box-shadow:
178
+ inset 0 1px 0 rgba(255, 255, 255, 0.16),
179
+ 0 14px 26px rgba(199, 156, 87, 0.16);
180
+ }
181
+
182
+ .hyvui-btn-primary:hover:not(:disabled):not(.hyvui-btn-disabled) {
183
+ transform: translateY(-2px);
184
+ filter: brightness(1.03);
185
+ }
186
+
187
+ /* secondary */
188
+ .hyvui-btn-secondary {
189
+ background:
190
+ linear-gradient(180deg, rgba(121, 166, 163, 0.06), transparent 62%), rgba(10, 12, 14, 0.74);
191
+ color: var(--text-soft);
192
+ border-color: var(--line-strong);
193
+ }
194
+
195
+ .hyvui-btn-secondary:hover:not(:disabled):not(.hyvui-btn-disabled) {
196
+ transform: translateY(-2px);
197
+ border-color: color-mix(in srgb, var(--accent) 46%, var(--line-strong));
198
+ color: var(--text);
199
+ }
200
+
201
+ /* ghost */
202
+ .hyvui-btn-ghost {
203
+ background: transparent;
204
+ color: var(--muted);
205
+ border-color: transparent;
206
+ box-shadow: none;
207
+ }
208
+
209
+ .hyvui-btn-ghost:hover:not(:disabled):not(.hyvui-btn-disabled) {
210
+ background: linear-gradient(90deg, rgba(199, 156, 87, 0.12), transparent 78%);
211
+ color: var(--text);
212
+ transform: translateX(2px);
213
+ }
214
+
215
+ /* destructive */
216
+ .hyvui-btn-destructive {
217
+ background: rgba(10, 12, 14, 0.74);
218
+ color: var(--text-soft);
219
+ border-color: rgba(182, 106, 72, 0.34);
220
+ }
221
+
222
+ .hyvui-btn-destructive:hover:not(:disabled):not(.hyvui-btn-disabled) {
223
+ background-color: rgba(182, 106, 72, 0.1);
224
+ transform: translateY(-2px);
225
+ }
226
+
227
+ /* loading dot */
228
+ .hyvui-btn-dot {
229
+ width: 6px;
230
+ height: 6px;
231
+ border-radius: 50%;
232
+ background-color: var(--status-pend);
233
+ animation: pulse-dot 2s cubic-bezier(0.37, 0, 0.63, 1) infinite;
234
+ }
235
+
236
+ @media (prefers-reduced-motion: reduce) {
237
+ .hyvui-btn {
238
+ transition: none;
239
+ }
240
+
241
+ .hyvui-btn:hover:not(:disabled):not(.hyvui-btn-disabled) {
242
+ transform: none;
243
+ }
244
+
245
+ .hyvui-btn-dot {
246
+ animation: none;
247
+ }
248
+ }
249
+
250
+ /* ── hextech ornament ─────────────────────────────────────────────── */
251
+ :global([data-register='hextech']) .hyvui-btn {
252
+ border-radius: var(--radius-sm);
253
+ }
254
+
255
+ /* brass corner pip — top-left notch */
256
+ :global([data-register='hextech']) .hyvui-btn::before {
257
+ content: '';
258
+ position: absolute;
259
+ top: 0;
260
+ left: 0;
261
+ width: 7px;
262
+ height: 7px;
263
+ border-top: 1.5px solid rgba(212, 165, 116, 0.55);
264
+ border-left: 1.5px solid rgba(212, 165, 116, 0.55);
265
+ pointer-events: none;
266
+ }
267
+
268
+ :global([data-register='hextech']) .hyvui-btn-primary:hover:not(:disabled):not(.hyvui-btn-disabled),
269
+ :global([data-register='hextech']) .hyvui-btn-primary:focus-visible {
270
+ box-shadow:
271
+ inset 0 1px 0 rgba(255, 255, 255, 0.2),
272
+ 0 0 18px rgba(93, 217, 240, 0.3),
273
+ 0 14px 26px rgba(184, 115, 51, 0.18);
274
+ }
275
+
276
+ :global([data-register='hextech']) .hyvui-btn-secondary:hover:not(:disabled):not(.hyvui-btn-disabled),
277
+ :global([data-register='hextech']) .hyvui-btn-secondary:focus-visible {
278
+ box-shadow: 0 0 12px rgba(93, 217, 240, 0.2);
279
+ border-color: rgba(93, 217, 240, 0.4);
280
+ }
281
+
282
+ /* ── arcane ornament ──────────────────────────────────────────────── */
283
+
284
+ /* crystal accent — top-right shard corner */
285
+ :global([data-register='arcane']) .hyvui-btn::after {
286
+ content: '';
287
+ position: absolute;
288
+ top: -1px;
289
+ right: -1px;
290
+ width: 8px;
291
+ height: 8px;
292
+ background: rgba(233, 76, 188, 0.55);
293
+ clip-path: polygon(100% 0, 100% 100%, 0 0);
294
+ pointer-events: none;
295
+ }
296
+
297
+ :global([data-register='arcane']) .hyvui-btn-primary:hover:not(:disabled):not(.hyvui-btn-disabled),
298
+ :global([data-register='arcane']) .hyvui-btn-primary:focus-visible {
299
+ box-shadow:
300
+ inset 0 1px 0 rgba(255, 255, 255, 0.14),
301
+ 0 0 22px rgba(184, 69, 201, 0.38),
302
+ 0 14px 26px rgba(184, 69, 201, 0.14);
303
+ }
304
+
305
+ :global([data-register='arcane']) .hyvui-btn-secondary:hover:not(:disabled):not(.hyvui-btn-disabled),
306
+ :global([data-register='arcane']) .hyvui-btn-secondary:focus-visible {
307
+ box-shadow: 0 0 14px rgba(184, 69, 201, 0.28);
308
+ border-color: rgba(184, 69, 201, 0.5);
309
+ }
310
+ </style>
@@ -1,4 +1,12 @@
1
1
  import type { Snippet } from 'svelte';
2
+ /**
3
+ * @see echo — add `echo` prop (or `use:echo` directly) for a gold click-pulse ripple.
4
+ * @example
5
+ * <Button variant="primary" onclick={handleSubmit}>submit</Button>
6
+ * <Button variant="ghost" href="/back">go back</Button>
7
+ * <Button variant="destructive" loading>deleting...</Button>
8
+ * <Button variant="primary" echo onclick={confirm}>confirm</Button>
9
+ */
2
10
  interface Props {
3
11
  /** Button visual style. */
4
12
  variant?: 'primary' | 'secondary' | 'ghost' | 'destructive';