@dorsk/tsumikit 0.74.0 → 0.75.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.
- package/README.md +38 -1
- package/dist/autoresize.d.ts +2 -0
- package/dist/autoresize.js +8 -1
- package/dist/components/atoms/Artwork.svelte +12 -5
- package/dist/components/atoms/Avatar.svelte +1 -1
- package/dist/components/atoms/Badge.svelte +59 -23
- package/dist/components/atoms/Button.svelte +130 -96
- package/dist/components/atoms/Button.svelte.d.ts +2 -0
- package/dist/components/atoms/Card.svelte +10 -4
- package/dist/components/atoms/Checkbox.svelte +36 -9
- package/dist/components/atoms/Checkbox.svelte.d.ts +2 -0
- package/dist/components/atoms/Gauge.svelte +20 -14
- package/dist/components/atoms/Heading.svelte +1 -1
- package/dist/components/atoms/Icon.svelte +1 -0
- package/dist/components/atoms/Input.svelte +67 -13
- package/dist/components/atoms/Kbd.svelte +3 -3
- package/dist/components/atoms/Link.svelte +7 -2
- package/dist/components/atoms/Progress.svelte +4 -2
- package/dist/components/atoms/Scrim.svelte +3 -8
- package/dist/components/atoms/SegmentedProgress.svelte +5 -4
- package/dist/components/atoms/Select.svelte +58 -27
- package/dist/components/atoms/Slider.svelte +79 -22
- package/dist/components/atoms/Slider.svelte.d.ts +2 -0
- package/dist/components/atoms/Swatch.svelte +19 -8
- package/dist/components/atoms/Switch.svelte +34 -21
- package/dist/components/atoms/Switch.svelte.d.ts +2 -0
- package/dist/components/atoms/Text.svelte +1 -1
- package/dist/components/atoms/Textarea.svelte +34 -12
- package/dist/components/atoms/TimeDisplay.svelte +4 -2
- package/dist/components/layouts/AppShell.svelte +26 -15
- package/dist/components/layouts/MasterDetail.svelte +23 -21
- package/dist/components/layouts/NavBar.svelte +11 -8
- package/dist/components/layouts/NavItem.svelte +15 -7
- package/dist/components/layouts/NavSection.svelte +1 -1
- package/dist/components/layouts/ResizablePanel.svelte +37 -16
- package/dist/components/layouts/TabBar.svelte +24 -14
- package/dist/components/layouts/TabBar.svelte.d.ts +2 -0
- package/dist/components/molecules/Accordion.svelte +4 -0
- package/dist/components/molecules/Accordion.svelte.d.ts +2 -0
- package/dist/components/molecules/AttachmentList.svelte +14 -11
- package/dist/components/molecules/Breadcrumb.svelte +13 -9
- package/dist/components/molecules/Callout.svelte +3 -3
- package/dist/components/molecules/CapBar.svelte +23 -22
- package/dist/components/molecules/Carousel.svelte +27 -17
- package/dist/components/molecules/ChatBubble.svelte +2 -2
- package/dist/components/molecules/CodeBlock.svelte +2 -2
- package/dist/components/molecules/Combobox.svelte +30 -1
- package/dist/components/molecules/Combobox.svelte.d.ts +4 -0
- package/dist/components/molecules/Composer.svelte +2 -2
- package/dist/components/molecules/ConfirmModal.svelte +4 -0
- package/dist/components/molecules/ConfirmModal.svelte.d.ts +2 -0
- package/dist/components/molecules/CopyButton.svelte +46 -2
- package/dist/components/molecules/CopyButton.svelte.d.ts +2 -0
- package/dist/components/molecules/Disclosure.svelte +23 -12
- package/dist/components/molecules/Disclosure.svelte.d.ts +2 -0
- package/dist/components/molecules/Drawer.svelte +43 -23
- package/dist/components/molecules/Drawer.svelte.d.ts +2 -0
- package/dist/components/molecules/Dropzone.svelte +24 -8
- package/dist/components/molecules/EmojiPicker.svelte +27 -8
- package/dist/components/molecules/EmojiPicker.svelte.d.ts +2 -0
- package/dist/components/molecules/EmptyState.svelte +5 -5
- package/dist/components/molecules/Fieldset.svelte +8 -13
- package/dist/components/molecules/FileButton.svelte +57 -31
- package/dist/components/molecules/FileButton.svelte.d.ts +2 -0
- package/dist/components/molecules/FilterInput.svelte +51 -11
- package/dist/components/molecules/FontScalePicker.svelte +20 -9
- package/dist/components/molecules/GitRef.svelte +9 -7
- package/dist/components/molecules/GlyphStack.svelte +38 -14
- package/dist/components/molecules/IconButton.svelte +6 -3
- package/dist/components/molecules/IconButton.svelte.d.ts +2 -0
- package/dist/components/molecules/InputGroup.svelte +13 -12
- package/dist/components/molecules/LoadMore.svelte +6 -1
- package/dist/components/molecules/LoadMore.svelte.d.ts +2 -0
- package/dist/components/molecules/Menu.svelte +33 -7
- package/dist/components/molecules/Menu.svelte.d.ts +2 -0
- package/dist/components/molecules/Metric.svelte +11 -9
- package/dist/components/molecules/Modal.svelte +76 -26
- package/dist/components/molecules/Modal.svelte.d.ts +2 -0
- package/dist/components/molecules/OptionButton.svelte +28 -10
- package/dist/components/molecules/OptionButton.svelte.d.ts +2 -0
- package/dist/components/molecules/Pagination.svelte +26 -9
- package/dist/components/molecules/Pagination.svelte.d.ts +2 -0
- package/dist/components/molecules/Popover.svelte +107 -51
- package/dist/components/molecules/Popover.svelte.d.ts +2 -0
- package/dist/components/molecules/Prose.svelte +1 -1
- package/dist/components/molecules/PullToRefresh.svelte +14 -10
- package/dist/components/molecules/PullToRefresh.svelte.d.ts +2 -0
- package/dist/components/molecules/RadialMenu.svelte +52 -19
- package/dist/components/molecules/RadialMenu.svelte.d.ts +2 -0
- package/dist/components/molecules/RadioGroup.svelte +38 -23
- package/dist/components/molecules/RadioGroup.svelte.d.ts +2 -0
- package/dist/components/molecules/SectionHeader.svelte +13 -8
- package/dist/components/molecules/SeekSlider.svelte +38 -27
- package/dist/components/molecules/SeekSlider.svelte.d.ts +2 -0
- package/dist/components/molecules/SegmentedControl.svelte +139 -86
- package/dist/components/molecules/SegmentedControl.svelte.d.ts +2 -0
- package/dist/components/molecules/SelectButton.svelte +21 -6
- package/dist/components/molecules/SelectButton.svelte.d.ts +2 -0
- package/dist/components/molecules/SortableList.svelte +10 -11
- package/dist/components/molecules/SoundSettings.svelte +161 -0
- package/dist/components/molecules/SoundSettings.svelte.d.ts +17 -0
- package/dist/components/molecules/SplitButton.svelte +30 -3
- package/dist/components/molecules/SplitButton.svelte.d.ts +2 -0
- package/dist/components/molecules/SwipeRow.svelte +18 -15
- package/dist/components/molecules/SwipeRow.svelte.d.ts +2 -0
- package/dist/components/molecules/Tabs.svelte +92 -10
- package/dist/components/molecules/Tabs.svelte.d.ts +2 -0
- package/dist/components/molecules/ThemePicker.svelte +25 -10
- package/dist/components/molecules/Timestamp.svelte +12 -7
- package/dist/components/molecules/Toaster.svelte +65 -14
- package/dist/components/molecules/Toaster.svelte.d.ts +2 -0
- package/dist/components/molecules/Toggle.svelte +36 -13
- package/dist/components/molecules/Toggle.svelte.d.ts +2 -0
- package/dist/components/molecules/Tooltip.svelte +41 -10
- package/dist/components/molecules/Tooltip.svelte.d.ts +1 -1
- package/dist/components/molecules/VolumeSlider.svelte +34 -14
- package/dist/components/molecules/VolumeSlider.svelte.d.ts +2 -0
- package/dist/components/molecules/WorkingDir.svelte +1 -0
- package/dist/components/organisms/ConversationFeed.svelte +4 -0
- package/dist/components/organisms/DataTable.svelte +37 -14
- package/dist/floating.js +26 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/sound-synth.js +17 -12
- package/dist/stores/toast.svelte.d.ts +9 -0
- package/dist/stores/toast.svelte.js +45 -9
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import Icon, { isIconName } from './Icon.svelte';
|
|
3
3
|
import { formatCount, hasCount } from '../../count';
|
|
4
|
+
import { playSound } from '../../sound';
|
|
4
5
|
import type { ControlSize } from '../../size';
|
|
5
6
|
import { canonicalTone, type Tone } from '../../tone';
|
|
6
7
|
import type { Snippet } from 'svelte';
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
href?: string;
|
|
33
34
|
target?: string;
|
|
34
35
|
rel?: string;
|
|
35
|
-
// Square icon-only tap target (IconButton), `--box-md`
|
|
36
|
+
// Square icon-only tap target (IconButton), `--box-md` unless
|
|
36
37
|
// `box` says otherwise. `iconInline` is the borderless, compact variant
|
|
37
38
|
// (chip-remove ✕, inline edit ✎); pair with `hoverDanger` to tint it red on
|
|
38
39
|
// hover (delete affordances).
|
|
@@ -73,6 +74,8 @@
|
|
|
73
74
|
shortcut?: string;
|
|
74
75
|
// Two-state toggle: sets `aria-pressed`.
|
|
75
76
|
pressed?: boolean;
|
|
77
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
78
|
+
sound?: boolean;
|
|
76
79
|
class?: string;
|
|
77
80
|
children?: Snippet;
|
|
78
81
|
};
|
|
@@ -103,6 +106,7 @@
|
|
|
103
106
|
glyph,
|
|
104
107
|
shortcut,
|
|
105
108
|
pressed,
|
|
109
|
+
sound = true,
|
|
106
110
|
type = 'button',
|
|
107
111
|
disabled = false,
|
|
108
112
|
title,
|
|
@@ -129,6 +133,7 @@
|
|
|
129
133
|
e.preventDefault();
|
|
130
134
|
return;
|
|
131
135
|
}
|
|
136
|
+
playSound('click', sound);
|
|
132
137
|
onclick?.(e);
|
|
133
138
|
};
|
|
134
139
|
|
|
@@ -234,64 +239,68 @@
|
|
|
234
239
|
align-items: center;
|
|
235
240
|
justify-content: center;
|
|
236
241
|
gap: var(--sp-2);
|
|
237
|
-
padding: var(--sp-2) var(--
|
|
242
|
+
padding: var(--sp-2) var(--btn-px-md);
|
|
238
243
|
min-height: var(--btn-size, var(--control-height-default));
|
|
244
|
+
max-width: 100%;
|
|
239
245
|
border: 1px solid var(--btn-border, var(--border-strong));
|
|
240
246
|
border-radius: var(--btn-radius, var(--r-md));
|
|
241
247
|
background: var(--btn-bg, var(--surface));
|
|
242
248
|
color: var(--btn-fg, var(--text));
|
|
243
249
|
font-weight: var(--fw-medium);
|
|
244
|
-
font-size: var(--fs-
|
|
245
|
-
line-height:
|
|
250
|
+
font-size: var(--control-fs-md);
|
|
251
|
+
line-height: var(--lh-none);
|
|
252
|
+
--icon-size: var(--control-icon-md);
|
|
253
|
+
--btn-scale-dur: var(--dur-fast);
|
|
246
254
|
transition:
|
|
247
|
-
background
|
|
248
|
-
border-color
|
|
249
|
-
|
|
255
|
+
background var(--dur-fast) ease,
|
|
256
|
+
border-color var(--dur-fast) ease,
|
|
257
|
+
color var(--dur-fast) ease,
|
|
258
|
+
opacity var(--dur-fast) ease,
|
|
259
|
+
scale var(--btn-scale-dur) var(--ease-out);
|
|
250
260
|
user-select: none;
|
|
251
|
-
white-space:
|
|
252
|
-
|
|
253
|
-
.btn:hover:not(:disabled) {
|
|
254
|
-
border-color: var(--accent);
|
|
261
|
+
white-space: normal;
|
|
262
|
+
overflow-wrap: break-word;
|
|
255
263
|
}
|
|
256
264
|
.btn:disabled {
|
|
257
|
-
opacity:
|
|
265
|
+
opacity: var(--disabled-opacity);
|
|
258
266
|
cursor: not-allowed;
|
|
259
267
|
}
|
|
268
|
+
/* Press: scale in over --dur-press, release over --dur-fast. */
|
|
269
|
+
.btn:active:not(:disabled, [aria-disabled='true'], .loading, .btn-link) {
|
|
270
|
+
--btn-scale-dur: var(--dur-press);
|
|
271
|
+
scale: var(--press-scale);
|
|
272
|
+
}
|
|
273
|
+
.btn-icon:active:not(:disabled, [aria-disabled='true'], .loading),
|
|
274
|
+
.btn-box:active:not(:disabled, [aria-disabled='true'], .loading),
|
|
275
|
+
.btn-square:active:not(:disabled, [aria-disabled='true'], .loading),
|
|
276
|
+
.btn-icon-inline:active:not(:disabled, [aria-disabled='true'], .loading) {
|
|
277
|
+
scale: var(--press-scale-sm);
|
|
278
|
+
}
|
|
260
279
|
.btn-primary {
|
|
261
280
|
background: var(--btn-bg, var(--accent));
|
|
262
281
|
border-color: var(--btn-border, var(--accent));
|
|
263
282
|
color: var(--btn-fg, var(--text-on-accent));
|
|
264
283
|
font-weight: var(--fw-semibold);
|
|
265
284
|
}
|
|
266
|
-
.btn-primary:hover:not(:disabled) {
|
|
267
|
-
filter: brightness(1.08);
|
|
268
|
-
}
|
|
269
285
|
.btn-danger {
|
|
270
286
|
color: var(--danger);
|
|
271
287
|
border-color: color-mix(in srgb, var(--danger) 50%, var(--border));
|
|
272
288
|
}
|
|
273
|
-
.btn-danger:hover:not(:disabled) {
|
|
274
|
-
background: color-mix(in srgb, var(--danger) 14%, transparent);
|
|
275
|
-
border-color: var(--danger);
|
|
276
|
-
}
|
|
277
289
|
.btn-ghost {
|
|
278
290
|
background: var(--btn-bg, transparent);
|
|
279
291
|
border-color: var(--btn-border, transparent);
|
|
280
292
|
}
|
|
281
|
-
.btn-ghost:hover:not(:disabled) {
|
|
282
|
-
background: var(--bg-elevated-2);
|
|
283
|
-
border-color: transparent;
|
|
284
|
-
}
|
|
285
293
|
.btn-sm {
|
|
286
|
-
height: var(--btn-size, var(--control-height-compact));
|
|
287
294
|
min-height: var(--btn-size, var(--control-height-compact));
|
|
288
|
-
padding: var(--sp-1) var(--
|
|
289
|
-
font-size: var(--fs-
|
|
295
|
+
padding: var(--sp-1) var(--btn-px-sm);
|
|
296
|
+
font-size: var(--control-fs-sm);
|
|
297
|
+
--icon-size: var(--control-icon-sm);
|
|
290
298
|
}
|
|
291
299
|
.btn-lg {
|
|
292
300
|
min-height: var(--btn-size, var(--control-height-large));
|
|
293
|
-
padding: var(--sp-3) var(--
|
|
294
|
-
font-size: var(--fs-
|
|
301
|
+
padding: var(--sp-3) var(--btn-px-lg);
|
|
302
|
+
font-size: var(--control-fs-lg);
|
|
303
|
+
--icon-size: var(--control-icon-lg);
|
|
295
304
|
}
|
|
296
305
|
.btn-block {
|
|
297
306
|
width: 100%;
|
|
@@ -305,7 +314,7 @@
|
|
|
305
314
|
text-decoration: none;
|
|
306
315
|
}
|
|
307
316
|
a.btn[aria-disabled='true'] {
|
|
308
|
-
opacity:
|
|
317
|
+
opacity: var(--disabled-opacity);
|
|
309
318
|
pointer-events: none;
|
|
310
319
|
cursor: not-allowed;
|
|
311
320
|
}
|
|
@@ -335,14 +344,6 @@
|
|
|
335
344
|
color: var(--btn-tone);
|
|
336
345
|
border-color: color-mix(in srgb, var(--btn-tone) 50%, var(--border));
|
|
337
346
|
}
|
|
338
|
-
.btn-tone-accent:hover:not(:disabled),
|
|
339
|
-
.btn-tone-success:hover:not(:disabled),
|
|
340
|
-
.btn-tone-info:hover:not(:disabled),
|
|
341
|
-
.btn-tone-warn:hover:not(:disabled),
|
|
342
|
-
.btn-tone-danger:hover:not(:disabled) {
|
|
343
|
-
background: color-mix(in srgb, var(--btn-tone) 14%, transparent);
|
|
344
|
-
border-color: var(--btn-tone);
|
|
345
|
-
}
|
|
346
347
|
|
|
347
348
|
/* Icon-chip: larger square outlined tap target for header/toolbar actions.
|
|
348
349
|
Combines with a tone for tinted severity chips. */
|
|
@@ -370,26 +371,19 @@
|
|
|
370
371
|
gap: var(--sp-2);
|
|
371
372
|
height: var(--btn-size, var(--control-height));
|
|
372
373
|
min-height: var(--btn-size, var(--control-height));
|
|
373
|
-
padding: 0 var(--
|
|
374
|
+
padding: 0 var(--control-px-md);
|
|
374
375
|
border: 1px solid var(--btn-border, var(--border-strong));
|
|
375
376
|
border-radius: var(--btn-radius, var(--r-md));
|
|
376
377
|
background: var(--btn-bg, var(--surface));
|
|
377
378
|
color: var(--btn-fg, var(--text));
|
|
378
379
|
font-weight: var(--fw-medium);
|
|
379
|
-
font-size: var(--fs-
|
|
380
|
-
line-height:
|
|
381
|
-
white-space:
|
|
382
|
-
transition:
|
|
383
|
-
background 0.12s var(--ease),
|
|
384
|
-
border-color 0.12s var(--ease),
|
|
385
|
-
opacity 0.12s var(--ease);
|
|
380
|
+
font-size: var(--control-fs-md);
|
|
381
|
+
line-height: var(--lh-none);
|
|
382
|
+
white-space: normal;
|
|
386
383
|
user-select: none;
|
|
387
384
|
}
|
|
388
|
-
.btn-control:hover:not(:disabled) {
|
|
389
|
-
border-color: var(--accent);
|
|
390
|
-
}
|
|
391
385
|
.btn-control:disabled {
|
|
392
|
-
opacity:
|
|
386
|
+
opacity: var(--disabled-opacity);
|
|
393
387
|
cursor: not-allowed;
|
|
394
388
|
}
|
|
395
389
|
/* .btn-control follows .btn-primary in source order and would otherwise paint
|
|
@@ -400,28 +394,15 @@
|
|
|
400
394
|
border-color: var(--btn-border, var(--accent));
|
|
401
395
|
color: var(--btn-fg, var(--text-on-accent));
|
|
402
396
|
}
|
|
403
|
-
.btn-control.btn-primary:hover:not(:disabled) {
|
|
404
|
-
border-color: var(--accent);
|
|
405
|
-
filter: brightness(1.08);
|
|
406
|
-
}
|
|
407
397
|
.btn-control.btn-tone-success {
|
|
408
398
|
color: var(--ok);
|
|
409
399
|
border-color: color-mix(in srgb, var(--ok) 50%, var(--border));
|
|
410
400
|
}
|
|
411
|
-
.btn-control.btn-tone-success:hover:not(:disabled) {
|
|
412
|
-
background: color-mix(in srgb, var(--ok) 14%, transparent);
|
|
413
|
-
border-color: var(--ok);
|
|
414
|
-
}
|
|
415
401
|
.btn-control.btn-danger,
|
|
416
402
|
.btn-control.btn-tone-danger {
|
|
417
403
|
color: var(--danger);
|
|
418
404
|
border-color: color-mix(in srgb, var(--danger) 50%, var(--border));
|
|
419
405
|
}
|
|
420
|
-
.btn-control.btn-danger:hover:not(:disabled),
|
|
421
|
-
.btn-control.btn-tone-danger:hover:not(:disabled) {
|
|
422
|
-
background: color-mix(in srgb, var(--danger) 14%, transparent);
|
|
423
|
-
border-color: var(--danger);
|
|
424
|
-
}
|
|
425
406
|
/* A positive primary action uses success as its fill, not merely as the
|
|
426
407
|
neutral tint. This follows the control override so both heights match. */
|
|
427
408
|
.btn-primary.btn-tone-success {
|
|
@@ -429,11 +410,6 @@
|
|
|
429
410
|
border-color: var(--ok);
|
|
430
411
|
color: var(--text-on-success);
|
|
431
412
|
}
|
|
432
|
-
.btn-primary.btn-tone-success:hover:not(:disabled) {
|
|
433
|
-
background: var(--ok);
|
|
434
|
-
border-color: var(--ok);
|
|
435
|
-
filter: brightness(1.08);
|
|
436
|
-
}
|
|
437
413
|
/* Other tones on a primary action tint the accent fill rather than repaint the
|
|
438
414
|
text, so the on-accent foreground stays readable (bare tone-as-text would be
|
|
439
415
|
accent-on-accent). success keeps its own filled guard above. */
|
|
@@ -445,14 +421,6 @@
|
|
|
445
421
|
border-color: color-mix(in srgb, var(--btn-tone) 35%, var(--accent));
|
|
446
422
|
color: var(--text-on-accent);
|
|
447
423
|
}
|
|
448
|
-
.btn-primary.btn-tone-accent:hover:not(:disabled),
|
|
449
|
-
.btn-primary.btn-tone-info:hover:not(:disabled),
|
|
450
|
-
.btn-primary.btn-tone-warn:hover:not(:disabled),
|
|
451
|
-
.btn-primary.btn-tone-danger:hover:not(:disabled) {
|
|
452
|
-
background: color-mix(in srgb, var(--btn-tone) 35%, var(--accent));
|
|
453
|
-
border-color: color-mix(in srgb, var(--btn-tone) 35%, var(--accent));
|
|
454
|
-
filter: brightness(1.08);
|
|
455
|
-
}
|
|
456
424
|
|
|
457
425
|
.no-shrink {
|
|
458
426
|
flex: none;
|
|
@@ -472,10 +440,9 @@
|
|
|
472
440
|
box-shadow: none;
|
|
473
441
|
border-radius: 0;
|
|
474
442
|
font-size: inherit;
|
|
475
|
-
line-height:
|
|
443
|
+
line-height: var(--lh-none);
|
|
476
444
|
color: var(--btn-tone, var(--link));
|
|
477
445
|
}
|
|
478
|
-
.btn-link:hover:not(:disabled),
|
|
479
446
|
.btn-link:focus-visible {
|
|
480
447
|
background: none;
|
|
481
448
|
border: none;
|
|
@@ -524,14 +491,6 @@
|
|
|
524
491
|
background: none;
|
|
525
492
|
color: var(--text-muted);
|
|
526
493
|
}
|
|
527
|
-
.btn-icon-inline:hover:not(:disabled) {
|
|
528
|
-
border: none;
|
|
529
|
-
background: none;
|
|
530
|
-
color: var(--text);
|
|
531
|
-
}
|
|
532
|
-
.btn-icon-inline.hover-danger:hover:not(:disabled) {
|
|
533
|
-
color: var(--danger);
|
|
534
|
-
}
|
|
535
494
|
|
|
536
495
|
/* Label collapse: `[data-label]` children disappear below the threshold and
|
|
537
496
|
the button falls back to icon-only padding. */
|
|
@@ -629,14 +588,14 @@
|
|
|
629
588
|
}
|
|
630
589
|
.btn-stacked.btn-sm {
|
|
631
590
|
min-height: var(--btn-size, var(--control-height-default));
|
|
632
|
-
min-width: var(--btn-size, calc(var(--control-height-default) + var(--sp-1) + 0
|
|
633
|
-
gap: 0
|
|
591
|
+
min-width: var(--btn-size, calc(var(--control-height-default) + var(--sp-1) + var(--sp-0-5)));
|
|
592
|
+
gap: var(--sp-0-5);
|
|
634
593
|
padding: var(--sp-1);
|
|
635
594
|
font-size: calc(var(--fs-xs) * 0.85);
|
|
636
595
|
}
|
|
637
596
|
.btn-stacked.btn-lg {
|
|
638
|
-
min-height: var(--btn-size, calc(var(--control-height-large) + var(--sp-2) + 0
|
|
639
|
-
min-width: var(--btn-size, calc(var(--control-height-large) + var(--sp-2) + 0
|
|
597
|
+
min-height: var(--btn-size, calc(var(--control-height-large) + var(--sp-2) + var(--sp-0-5)));
|
|
598
|
+
min-width: var(--btn-size, calc(var(--control-height-large) + var(--sp-2) + var(--sp-0-5)));
|
|
640
599
|
padding: var(--sp-2) var(--sp-3);
|
|
641
600
|
font-size: var(--fs-sm);
|
|
642
601
|
}
|
|
@@ -645,7 +604,8 @@
|
|
|
645
604
|
align-items: center;
|
|
646
605
|
justify-content: center;
|
|
647
606
|
flex: none;
|
|
648
|
-
line-height:
|
|
607
|
+
line-height: var(--lh-none);
|
|
608
|
+
font-size: var(--icon-size);
|
|
649
609
|
}
|
|
650
610
|
.btn-stacked .btn-glyph {
|
|
651
611
|
font-size: var(--fs-lg);
|
|
@@ -677,13 +637,13 @@
|
|
|
677
637
|
}
|
|
678
638
|
.btn-shortcut {
|
|
679
639
|
position: absolute;
|
|
680
|
-
top: 0
|
|
681
|
-
left:
|
|
640
|
+
top: var(--sp-0-5);
|
|
641
|
+
left: var(--sp-1);
|
|
682
642
|
font-family: var(--font-mono);
|
|
683
643
|
font-size: calc(var(--fs-xs) * 0.75);
|
|
684
644
|
font-weight: var(--fw-medium);
|
|
685
645
|
color: var(--text-faint);
|
|
686
|
-
line-height:
|
|
646
|
+
line-height: var(--lh-none);
|
|
687
647
|
pointer-events: none;
|
|
688
648
|
}
|
|
689
649
|
|
|
@@ -701,8 +661,14 @@
|
|
|
701
661
|
flex: none;
|
|
702
662
|
border: 2px solid currentColor;
|
|
703
663
|
border-top-color: transparent;
|
|
704
|
-
border-radius:
|
|
664
|
+
border-radius: var(--r-pill);
|
|
705
665
|
animation: btn-spin 0.6s linear infinite;
|
|
666
|
+
transition: opacity var(--dur-fast) ease;
|
|
667
|
+
}
|
|
668
|
+
@starting-style {
|
|
669
|
+
.btn-spinner {
|
|
670
|
+
opacity: 0;
|
|
671
|
+
}
|
|
706
672
|
}
|
|
707
673
|
@keyframes btn-spin {
|
|
708
674
|
to {
|
|
@@ -733,7 +699,7 @@
|
|
|
733
699
|
font-size: var(--fs-xs);
|
|
734
700
|
font-weight: var(--fw-semibold);
|
|
735
701
|
font-variant-numeric: tabular-nums;
|
|
736
|
-
line-height:
|
|
702
|
+
line-height: var(--lh-none);
|
|
737
703
|
white-space: nowrap;
|
|
738
704
|
pointer-events: none;
|
|
739
705
|
}
|
|
@@ -741,7 +707,7 @@
|
|
|
741
707
|
.btn-link .btn-count,
|
|
742
708
|
.btn-icon-inline .btn-count {
|
|
743
709
|
--btn-count-size: 1rem;
|
|
744
|
-
padding: 0 0
|
|
710
|
+
padding: 0 var(--sp-0-5);
|
|
745
711
|
font-size: var(--fs-xs);
|
|
746
712
|
}
|
|
747
713
|
/* The accent fill would swallow an accent pill: invert on primary. */
|
|
@@ -759,4 +725,72 @@
|
|
|
759
725
|
clip-path: inset(50%);
|
|
760
726
|
white-space: nowrap;
|
|
761
727
|
}
|
|
728
|
+
|
|
729
|
+
/* Hover only on devices that have it: taps leave sticky hovers on touch. */
|
|
730
|
+
@media (hover: hover) and (pointer: fine) {
|
|
731
|
+
.btn:hover:not(:disabled) {
|
|
732
|
+
border-color: var(--accent);
|
|
733
|
+
}
|
|
734
|
+
.btn-primary:hover:not(:disabled) {
|
|
735
|
+
filter: brightness(1.08);
|
|
736
|
+
}
|
|
737
|
+
.btn-danger:hover:not(:disabled) {
|
|
738
|
+
background: color-mix(in srgb, var(--danger) 14%, transparent);
|
|
739
|
+
border-color: var(--danger);
|
|
740
|
+
}
|
|
741
|
+
.btn-ghost:hover:not(:disabled) {
|
|
742
|
+
background: var(--bg-elevated-2);
|
|
743
|
+
border-color: transparent;
|
|
744
|
+
}
|
|
745
|
+
.btn-tone-accent:hover:not(:disabled),
|
|
746
|
+
.btn-tone-success:hover:not(:disabled),
|
|
747
|
+
.btn-tone-info:hover:not(:disabled),
|
|
748
|
+
.btn-tone-warn:hover:not(:disabled),
|
|
749
|
+
.btn-tone-danger:hover:not(:disabled) {
|
|
750
|
+
background: color-mix(in srgb, var(--btn-tone) 14%, transparent);
|
|
751
|
+
border-color: var(--btn-tone);
|
|
752
|
+
}
|
|
753
|
+
.btn-control:hover:not(:disabled) {
|
|
754
|
+
border-color: var(--accent);
|
|
755
|
+
}
|
|
756
|
+
.btn-control.btn-primary:hover:not(:disabled) {
|
|
757
|
+
border-color: var(--accent);
|
|
758
|
+
filter: brightness(1.08);
|
|
759
|
+
}
|
|
760
|
+
.btn-control.btn-tone-success:hover:not(:disabled) {
|
|
761
|
+
background: color-mix(in srgb, var(--ok) 14%, transparent);
|
|
762
|
+
border-color: var(--ok);
|
|
763
|
+
}
|
|
764
|
+
.btn-control.btn-danger:hover:not(:disabled),
|
|
765
|
+
.btn-control.btn-tone-danger:hover:not(:disabled) {
|
|
766
|
+
background: color-mix(in srgb, var(--danger) 14%, transparent);
|
|
767
|
+
border-color: var(--danger);
|
|
768
|
+
}
|
|
769
|
+
.btn-primary.btn-tone-success:hover:not(:disabled) {
|
|
770
|
+
background: var(--ok);
|
|
771
|
+
border-color: var(--ok);
|
|
772
|
+
filter: brightness(1.08);
|
|
773
|
+
}
|
|
774
|
+
.btn-primary.btn-tone-accent:hover:not(:disabled),
|
|
775
|
+
.btn-primary.btn-tone-info:hover:not(:disabled),
|
|
776
|
+
.btn-primary.btn-tone-warn:hover:not(:disabled),
|
|
777
|
+
.btn-primary.btn-tone-danger:hover:not(:disabled) {
|
|
778
|
+
background: color-mix(in srgb, var(--btn-tone) 35%, var(--accent));
|
|
779
|
+
border-color: color-mix(in srgb, var(--btn-tone) 35%, var(--accent));
|
|
780
|
+
filter: brightness(1.08);
|
|
781
|
+
}
|
|
782
|
+
.btn-link:hover:not(:disabled) {
|
|
783
|
+
background: none;
|
|
784
|
+
border: none;
|
|
785
|
+
text-decoration: underline;
|
|
786
|
+
}
|
|
787
|
+
.btn-icon-inline:hover:not(:disabled) {
|
|
788
|
+
border: none;
|
|
789
|
+
background: none;
|
|
790
|
+
color: var(--text);
|
|
791
|
+
}
|
|
792
|
+
.btn-icon-inline.hover-danger:hover:not(:disabled) {
|
|
793
|
+
color: var(--danger);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
762
796
|
</style>
|
|
@@ -30,6 +30,8 @@ type ButtonProps = HTMLButtonAttributes & {
|
|
|
30
30
|
glyph?: Snippet | string;
|
|
31
31
|
shortcut?: string;
|
|
32
32
|
pressed?: boolean;
|
|
33
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
34
|
+
sound?: boolean;
|
|
33
35
|
class?: string;
|
|
34
36
|
children?: Snippet;
|
|
35
37
|
};
|
|
@@ -234,14 +234,20 @@
|
|
|
234
234
|
.card-tap {
|
|
235
235
|
cursor: pointer;
|
|
236
236
|
transition:
|
|
237
|
-
border-color
|
|
238
|
-
background
|
|
237
|
+
border-color var(--dur-fast) var(--ease),
|
|
238
|
+
background var(--dur-fast) var(--ease),
|
|
239
|
+
box-shadow var(--dur-fast) var(--ease),
|
|
240
|
+
scale var(--dur-fast) var(--ease-out);
|
|
239
241
|
}
|
|
240
242
|
.card-tap:active {
|
|
241
243
|
background: var(--bg-elevated-2);
|
|
244
|
+
scale: var(--press-scale-lg);
|
|
245
|
+
transition-duration: var(--dur-press);
|
|
242
246
|
}
|
|
243
|
-
|
|
244
|
-
|
|
247
|
+
@media (hover: hover) and (pointer: fine) {
|
|
248
|
+
.card-tap:hover {
|
|
249
|
+
border-color: var(--border-strong);
|
|
250
|
+
}
|
|
245
251
|
}
|
|
246
252
|
.card-max {
|
|
247
253
|
width: 100%;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
7
7
|
import { getFieldContext } from '../../field-context';
|
|
8
8
|
import type { ControlSize } from '../../size';
|
|
9
|
+
import { playSound } from '../../sound';
|
|
9
10
|
|
|
10
11
|
let {
|
|
11
12
|
checked = $bindable(false),
|
|
@@ -14,11 +15,13 @@
|
|
|
14
15
|
label,
|
|
15
16
|
labelHidden = false,
|
|
16
17
|
size = 'md',
|
|
18
|
+
sound = true,
|
|
17
19
|
id,
|
|
18
20
|
'aria-describedby': ariaDescribedby,
|
|
19
21
|
'aria-invalid': ariaInvalid,
|
|
20
22
|
class: klass = '',
|
|
21
23
|
el = $bindable(null),
|
|
24
|
+
onchange,
|
|
22
25
|
...rest
|
|
23
26
|
}: Omit<HTMLInputAttributes, 'size'> & {
|
|
24
27
|
checked?: boolean;
|
|
@@ -31,6 +34,8 @@
|
|
|
31
34
|
/** Box + label scale, as on `Switch`. Override the box alone with
|
|
32
35
|
* `style="--cb-box: 1rem"`. */
|
|
33
36
|
size?: ControlSize;
|
|
37
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
38
|
+
sound?: boolean;
|
|
34
39
|
id?: string;
|
|
35
40
|
'aria-describedby'?: string | null;
|
|
36
41
|
'aria-invalid'?: HTMLInputAttributes['aria-invalid'];
|
|
@@ -40,6 +45,11 @@
|
|
|
40
45
|
const field = getFieldContext();
|
|
41
46
|
const isInvalid = $derived(invalid || !!field?.invalid);
|
|
42
47
|
|
|
48
|
+
function change(e: Event & { currentTarget: EventTarget & HTMLInputElement }) {
|
|
49
|
+
onchange?.(e);
|
|
50
|
+
playSound(e.currentTarget.checked ? 'toggle-on' : 'toggle-off', sound);
|
|
51
|
+
}
|
|
52
|
+
|
|
43
53
|
// `indeterminate` is a property, not an attribute — sync it imperatively.
|
|
44
54
|
$effect(() => {
|
|
45
55
|
if (el) el.indeterminate = indeterminate;
|
|
@@ -57,6 +67,7 @@
|
|
|
57
67
|
type="checkbox"
|
|
58
68
|
bind:checked
|
|
59
69
|
{...rest}
|
|
70
|
+
onchange={change}
|
|
60
71
|
id={id ?? field?.id}
|
|
61
72
|
aria-describedby={ariaDescribedby ?? field?.describedBy}
|
|
62
73
|
aria-invalid={ariaInvalid ?? (isInvalid ? 'true' : undefined)}
|
|
@@ -83,24 +94,29 @@
|
|
|
83
94
|
margin: 0;
|
|
84
95
|
}
|
|
85
96
|
.checkbox-sm {
|
|
86
|
-
--cb-box:
|
|
97
|
+
--cb-box: var(--chip-xs);
|
|
87
98
|
font-size: var(--fs-xs);
|
|
88
99
|
}
|
|
89
100
|
.checkbox-lg {
|
|
90
|
-
--cb-box:
|
|
101
|
+
--cb-box: var(--chip-md);
|
|
91
102
|
font-size: var(--fs-base);
|
|
92
103
|
}
|
|
93
104
|
.box {
|
|
94
105
|
position: relative;
|
|
95
106
|
flex: none;
|
|
96
|
-
width: var(--cb-box,
|
|
97
|
-
height: var(--cb-box,
|
|
107
|
+
width: var(--cb-box, var(--chip-sm));
|
|
108
|
+
height: var(--cb-box, var(--chip-sm));
|
|
98
109
|
border: 1px solid var(--border-strong);
|
|
99
110
|
border-radius: var(--r-sm);
|
|
100
111
|
background: var(--bg);
|
|
101
112
|
transition:
|
|
102
|
-
background
|
|
103
|
-
border-color
|
|
113
|
+
background var(--dur-fast) var(--ease),
|
|
114
|
+
border-color var(--dur-fast) var(--ease),
|
|
115
|
+
scale var(--dur-fast) var(--ease-out);
|
|
116
|
+
}
|
|
117
|
+
.checkbox:active:not(:has(input:disabled)) .box {
|
|
118
|
+
scale: var(--press-scale-sm);
|
|
119
|
+
transition-duration: var(--dur-press);
|
|
104
120
|
}
|
|
105
121
|
/* check mark */
|
|
106
122
|
.box::after {
|
|
@@ -110,7 +126,10 @@
|
|
|
110
126
|
background: var(--text-on-accent);
|
|
111
127
|
clip-path: polygon(41% 67%, 79% 26%, 87% 35%, 41% 84%, 15% 56%, 24% 47%);
|
|
112
128
|
opacity: 0;
|
|
113
|
-
|
|
129
|
+
scale: 0.6;
|
|
130
|
+
transition:
|
|
131
|
+
opacity var(--dur-exit-fast) var(--ease-out),
|
|
132
|
+
scale var(--dur-exit-fast) var(--ease-out);
|
|
114
133
|
}
|
|
115
134
|
input:checked + .box {
|
|
116
135
|
background: var(--accent);
|
|
@@ -118,6 +137,10 @@
|
|
|
118
137
|
}
|
|
119
138
|
input:checked + .box::after {
|
|
120
139
|
opacity: 1;
|
|
140
|
+
scale: 1;
|
|
141
|
+
transition:
|
|
142
|
+
opacity var(--dur-spring) var(--ease-spring),
|
|
143
|
+
scale var(--dur-spring) var(--ease-spring);
|
|
121
144
|
}
|
|
122
145
|
/* indeterminate dash */
|
|
123
146
|
input:indeterminate + .box {
|
|
@@ -126,17 +149,21 @@
|
|
|
126
149
|
}
|
|
127
150
|
input:indeterminate + .box::after {
|
|
128
151
|
opacity: 1;
|
|
152
|
+
scale: 1;
|
|
129
153
|
clip-path: polygon(22% 42%, 78% 42%, 78% 58%, 22% 58%);
|
|
154
|
+
transition:
|
|
155
|
+
opacity var(--dur-spring) var(--ease-spring),
|
|
156
|
+
scale var(--dur-spring) var(--ease-spring);
|
|
130
157
|
}
|
|
131
158
|
input:focus-visible + .box {
|
|
132
159
|
outline: var(--focus-ring);
|
|
133
|
-
outline-offset:
|
|
160
|
+
outline-offset: var(--focus-ring-offset);
|
|
134
161
|
}
|
|
135
162
|
input[aria-invalid='true']:not(:checked):not(:indeterminate) + .box {
|
|
136
163
|
border-color: var(--danger);
|
|
137
164
|
}
|
|
138
165
|
input:disabled ~ * {
|
|
139
|
-
opacity:
|
|
166
|
+
opacity: var(--disabled-opacity);
|
|
140
167
|
}
|
|
141
168
|
.checkbox:has(input:disabled) {
|
|
142
169
|
cursor: not-allowed;
|
|
@@ -11,6 +11,8 @@ type $$ComponentProps = Omit<HTMLInputAttributes, 'size'> & {
|
|
|
11
11
|
/** Box + label scale, as on `Switch`. Override the box alone with
|
|
12
12
|
* `style="--cb-box: 1rem"`. */
|
|
13
13
|
size?: ControlSize;
|
|
14
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
15
|
+
sound?: boolean;
|
|
14
16
|
id?: string;
|
|
15
17
|
'aria-describedby'?: string | null;
|
|
16
18
|
'aria-invalid'?: HTMLInputAttributes['aria-invalid'];
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
{/each}
|
|
92
92
|
</span>
|
|
93
93
|
{:else}
|
|
94
|
-
<span class="fill" style
|
|
94
|
+
<span class="fill" style:--p={pct / 100}></span>
|
|
95
95
|
{/if}
|
|
96
96
|
{#if corner}
|
|
97
97
|
<span class="corner">{@render corner()}</span>
|
|
@@ -120,12 +120,14 @@
|
|
|
120
120
|
.interactive {
|
|
121
121
|
cursor: pointer;
|
|
122
122
|
}
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
@media (hover: hover) and (pointer: fine) {
|
|
124
|
+
.interactive:hover {
|
|
125
|
+
border-color: var(--gauge-fill);
|
|
126
|
+
}
|
|
125
127
|
}
|
|
126
128
|
.interactive:focus-visible {
|
|
127
|
-
outline:
|
|
128
|
-
outline-offset:
|
|
129
|
+
outline: var(--focus-ring);
|
|
130
|
+
outline-offset: var(--focus-ring-offset);
|
|
129
131
|
}
|
|
130
132
|
.tone-ok {
|
|
131
133
|
--gauge-fill: var(--ok);
|
|
@@ -138,23 +140,27 @@
|
|
|
138
140
|
}
|
|
139
141
|
.fill {
|
|
140
142
|
position: absolute;
|
|
141
|
-
inset:
|
|
142
|
-
border-radius: calc(var(--r-sm) -
|
|
143
|
+
inset: 0;
|
|
144
|
+
border-radius: calc(var(--r-sm) - var(--sp-px));
|
|
143
145
|
background: var(--gauge-fill);
|
|
144
|
-
|
|
146
|
+
transform-origin: bottom;
|
|
147
|
+
scale: 1 var(--p, 0);
|
|
148
|
+
transition:
|
|
149
|
+
scale var(--dur-base) var(--ease-out),
|
|
150
|
+
background var(--dur-fast) var(--ease);
|
|
145
151
|
}
|
|
146
152
|
.segments {
|
|
147
153
|
position: absolute;
|
|
148
|
-
inset:
|
|
154
|
+
inset: var(--sp-0-5);
|
|
149
155
|
display: flex;
|
|
150
156
|
flex-direction: column-reverse;
|
|
151
|
-
gap:
|
|
157
|
+
gap: var(--sp-0-5);
|
|
152
158
|
}
|
|
153
159
|
.segment {
|
|
154
160
|
flex: 1 1 0%;
|
|
155
|
-
border-radius:
|
|
161
|
+
border-radius: var(--r-xs);
|
|
156
162
|
background: var(--bg-elevated);
|
|
157
|
-
transition: background
|
|
163
|
+
transition: background var(--dur-fast) var(--ease);
|
|
158
164
|
}
|
|
159
165
|
.segment.lit {
|
|
160
166
|
background: var(--gauge-fill);
|
|
@@ -164,8 +170,8 @@
|
|
|
164
170
|
right: -0.35em;
|
|
165
171
|
bottom: -0.35em;
|
|
166
172
|
display: inline-flex;
|
|
167
|
-
font-size:
|
|
168
|
-
line-height:
|
|
173
|
+
font-size: var(--fs-xs);
|
|
174
|
+
line-height: var(--lh-none);
|
|
169
175
|
pointer-events: none;
|
|
170
176
|
}
|
|
171
177
|
</style>
|