@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
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// JS to open the dialog. Emits the chosen files via `onfiles`. Dependency-free.
|
|
6
6
|
import Icon from '../atoms/Icon.svelte';
|
|
7
7
|
import type { IconName } from '../atoms/Icon.svelte';
|
|
8
|
+
import { playSound } from '../../sound';
|
|
8
9
|
|
|
9
10
|
let {
|
|
10
11
|
onfiles,
|
|
@@ -20,6 +21,7 @@
|
|
|
20
21
|
control = false,
|
|
21
22
|
box,
|
|
22
23
|
hitArea = 'auto',
|
|
24
|
+
sound = true,
|
|
23
25
|
class: klass = ''
|
|
24
26
|
}: {
|
|
25
27
|
onfiles: (files: File[]) => void;
|
|
@@ -47,6 +49,8 @@
|
|
|
47
49
|
box?: 'xs' | 'sm' | 'md' | 'lg';
|
|
48
50
|
/** Icon-only buttons grow a touch hit slab on coarse pointers; `compact` opts out. */
|
|
49
51
|
hitArea?: 'auto' | 'compact';
|
|
52
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
53
|
+
sound?: boolean;
|
|
50
54
|
class?: string;
|
|
51
55
|
} = $props();
|
|
52
56
|
|
|
@@ -81,6 +85,7 @@
|
|
|
81
85
|
{accept}
|
|
82
86
|
{multiple}
|
|
83
87
|
{disabled}
|
|
88
|
+
onclick={() => playSound('click', sound)}
|
|
84
89
|
onchange={onchange}
|
|
85
90
|
/>
|
|
86
91
|
{#if icon}
|
|
@@ -100,41 +105,52 @@
|
|
|
100
105
|
align-items: center;
|
|
101
106
|
justify-content: center;
|
|
102
107
|
gap: var(--sp-2);
|
|
103
|
-
padding: var(--sp-2) var(--
|
|
104
|
-
min-height:
|
|
108
|
+
padding: var(--sp-2) var(--btn-px-md);
|
|
109
|
+
min-height: var(--control-height-default);
|
|
105
110
|
border: 1px solid var(--border-strong);
|
|
106
111
|
border-radius: var(--r-md);
|
|
107
112
|
background: var(--surface);
|
|
108
113
|
color: var(--text);
|
|
109
114
|
font-weight: var(--fw-medium);
|
|
110
|
-
font-size: var(--fs-
|
|
111
|
-
line-height:
|
|
115
|
+
font-size: var(--control-fs-md);
|
|
116
|
+
line-height: var(--lh-none);
|
|
112
117
|
white-space: nowrap;
|
|
113
118
|
cursor: pointer;
|
|
114
119
|
user-select: none;
|
|
120
|
+
--icon-size: var(--control-icon-md);
|
|
121
|
+
--file-scale-dur: var(--dur-fast);
|
|
115
122
|
transition:
|
|
116
|
-
background
|
|
117
|
-
border-color
|
|
118
|
-
|
|
123
|
+
background var(--dur-fast) ease,
|
|
124
|
+
border-color var(--dur-fast) ease,
|
|
125
|
+
color var(--dur-fast) ease,
|
|
126
|
+
opacity var(--dur-fast) ease,
|
|
127
|
+
scale var(--file-scale-dur) var(--ease-out);
|
|
119
128
|
}
|
|
120
|
-
.file-btn:
|
|
121
|
-
|
|
129
|
+
.file-btn:active:not(.disabled) {
|
|
130
|
+
--file-scale-dur: var(--dur-press);
|
|
131
|
+
scale: var(--press-scale);
|
|
132
|
+
}
|
|
133
|
+
.file-btn.icon-only:active:not(.disabled),
|
|
134
|
+
.file-btn.box:active:not(.disabled) {
|
|
135
|
+
scale: var(--press-scale-sm);
|
|
122
136
|
}
|
|
123
|
-
/* Size variants mirror the Button atom
|
|
137
|
+
/* Size variants mirror the Button atom. */
|
|
124
138
|
.file-btn.sm {
|
|
125
|
-
min-height:
|
|
126
|
-
padding: var(--sp-1) var(--
|
|
127
|
-
font-size: var(--fs-
|
|
139
|
+
min-height: var(--control-height-compact);
|
|
140
|
+
padding: var(--sp-1) var(--btn-px-sm);
|
|
141
|
+
font-size: var(--control-fs-sm);
|
|
142
|
+
--icon-size: var(--control-icon-sm);
|
|
128
143
|
}
|
|
129
144
|
.file-btn.lg {
|
|
130
|
-
min-height:
|
|
131
|
-
padding: var(--sp-3) var(--
|
|
132
|
-
font-size: var(--fs-
|
|
145
|
+
min-height: var(--control-height-large);
|
|
146
|
+
padding: var(--sp-3) var(--btn-px-lg);
|
|
147
|
+
font-size: var(--control-fs-lg);
|
|
148
|
+
--icon-size: var(--control-icon-lg);
|
|
133
149
|
}
|
|
134
150
|
.file-btn.control {
|
|
135
151
|
height: var(--control-height);
|
|
136
152
|
min-height: var(--control-height);
|
|
137
|
-
padding: 0 var(--
|
|
153
|
+
padding: 0 var(--control-px-md);
|
|
138
154
|
}
|
|
139
155
|
/* icon-only: square it up and drop the label gap. */
|
|
140
156
|
.file-btn.icon-only {
|
|
@@ -162,12 +178,17 @@
|
|
|
162
178
|
inset-inline-end: 0;
|
|
163
179
|
}
|
|
164
180
|
}
|
|
165
|
-
/*
|
|
166
|
-
read, so render it a touch larger for legibility. */
|
|
181
|
+
/* An emoji reads small next to an SVG glyph of the same size: one icon tier up. */
|
|
167
182
|
.emoji {
|
|
168
183
|
display: inline-flex;
|
|
169
|
-
font-size:
|
|
170
|
-
line-height:
|
|
184
|
+
font-size: var(--icon-lg);
|
|
185
|
+
line-height: var(--lh-none);
|
|
186
|
+
}
|
|
187
|
+
.file-btn.sm .emoji {
|
|
188
|
+
font-size: var(--icon-md);
|
|
189
|
+
}
|
|
190
|
+
.file-btn.lg .emoji {
|
|
191
|
+
font-size: var(--icon-xl);
|
|
171
192
|
}
|
|
172
193
|
.file-btn.primary {
|
|
173
194
|
background: var(--accent);
|
|
@@ -175,25 +196,30 @@
|
|
|
175
196
|
color: var(--text-on-accent);
|
|
176
197
|
font-weight: var(--fw-semibold);
|
|
177
198
|
}
|
|
178
|
-
.file-btn.primary:hover:not(.disabled) {
|
|
179
|
-
filter: brightness(1.08);
|
|
180
|
-
}
|
|
181
199
|
.file-btn.ghost {
|
|
182
200
|
background: transparent;
|
|
183
201
|
border-color: transparent;
|
|
184
202
|
}
|
|
185
|
-
.file-btn.ghost:hover:not(.disabled) {
|
|
186
|
-
background: var(--bg-elevated-2);
|
|
187
|
-
border-color: transparent;
|
|
188
|
-
}
|
|
189
203
|
/* The hidden input keeps focusability (sr-only, not display:none), so mirror
|
|
190
204
|
its focus onto the label for a visible ring. */
|
|
191
205
|
.file-btn:focus-within {
|
|
192
|
-
outline:
|
|
193
|
-
outline-offset:
|
|
206
|
+
outline: var(--focus-ring);
|
|
207
|
+
outline-offset: var(--focus-ring-offset);
|
|
194
208
|
}
|
|
195
209
|
.file-btn.disabled {
|
|
196
|
-
opacity:
|
|
210
|
+
opacity: var(--disabled-opacity);
|
|
197
211
|
cursor: not-allowed;
|
|
198
212
|
}
|
|
213
|
+
@media (hover: hover) and (pointer: fine) {
|
|
214
|
+
.file-btn:hover:not(.disabled) {
|
|
215
|
+
border-color: var(--accent);
|
|
216
|
+
}
|
|
217
|
+
.file-btn.primary:hover:not(.disabled) {
|
|
218
|
+
filter: brightness(1.08);
|
|
219
|
+
}
|
|
220
|
+
.file-btn.ghost:hover:not(.disabled) {
|
|
221
|
+
background: var(--bg-elevated-2);
|
|
222
|
+
border-color: transparent;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
199
225
|
</style>
|
|
@@ -26,6 +26,8 @@ type $$ComponentProps = {
|
|
|
26
26
|
box?: 'xs' | 'sm' | 'md' | 'lg';
|
|
27
27
|
/** Icon-only buttons grow a touch hit slab on coarse pointers; `compact` opts out. */
|
|
28
28
|
hitArea?: 'auto' | 'compact';
|
|
29
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
30
|
+
sound?: boolean;
|
|
29
31
|
class?: string;
|
|
30
32
|
};
|
|
31
33
|
declare const FileButton: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
@@ -465,20 +465,26 @@
|
|
|
465
465
|
min-width: 0;
|
|
466
466
|
}
|
|
467
467
|
.fi__bar {
|
|
468
|
+
--fi-icon: var(--control-icon-md);
|
|
468
469
|
display: flex;
|
|
469
470
|
align-items: center;
|
|
470
471
|
gap: var(--sp-2);
|
|
471
|
-
padding: 0 var(--
|
|
472
|
+
padding: 0 var(--control-px-md);
|
|
472
473
|
min-height: var(--control-height-default);
|
|
473
474
|
background: var(--bg-elevated);
|
|
474
475
|
border: 1px solid var(--border-strong);
|
|
475
476
|
border-radius: var(--r-md);
|
|
477
|
+
transition:
|
|
478
|
+
border-color var(--dur-fast) ease,
|
|
479
|
+
box-shadow var(--dur-fast) ease;
|
|
476
480
|
}
|
|
477
481
|
.fi--sm .fi__bar {
|
|
478
482
|
min-height: var(--control-height-compact);
|
|
483
|
+
padding: 0 var(--control-px-sm);
|
|
484
|
+
--fi-icon: var(--control-icon-sm);
|
|
479
485
|
}
|
|
480
486
|
.fi--sm .fi__input {
|
|
481
|
-
font-size: var(--fs-sm);
|
|
487
|
+
font-size: var(--control-fs-sm);
|
|
482
488
|
}
|
|
483
489
|
.fi--pill .fi__bar {
|
|
484
490
|
border-radius: var(--r-pill);
|
|
@@ -493,11 +499,11 @@
|
|
|
493
499
|
.fi__kbd {
|
|
494
500
|
font-family: var(--font-mono);
|
|
495
501
|
font-size: var(--fs-xs);
|
|
496
|
-
line-height:
|
|
502
|
+
line-height: var(--lh-none);
|
|
497
503
|
color: var(--text-faint);
|
|
498
504
|
border: 1px solid var(--border);
|
|
499
505
|
border-radius: var(--r-sm);
|
|
500
|
-
padding:
|
|
506
|
+
padding: var(--sp-0-5) var(--sp-1);
|
|
501
507
|
}
|
|
502
508
|
.fi__bar:focus-within {
|
|
503
509
|
border-color: var(--accent);
|
|
@@ -509,6 +515,7 @@
|
|
|
509
515
|
}
|
|
510
516
|
.fi__icon {
|
|
511
517
|
display: flex;
|
|
518
|
+
font-size: var(--fi-icon);
|
|
512
519
|
color: var(--text-faint);
|
|
513
520
|
}
|
|
514
521
|
.fi__field {
|
|
@@ -533,16 +540,16 @@
|
|
|
533
540
|
background: transparent;
|
|
534
541
|
color: var(--text);
|
|
535
542
|
font-family: var(--font-mono);
|
|
536
|
-
font-size: var(--fs-md);
|
|
543
|
+
font-size: var(--control-fs-md);
|
|
537
544
|
outline: none;
|
|
538
545
|
min-width: 0;
|
|
539
546
|
}
|
|
540
547
|
@media (pointer: coarse) {
|
|
541
548
|
.fi__input {
|
|
542
|
-
font-size: max(16px, var(--fs-md));
|
|
549
|
+
font-size: max(16px, var(--control-fs-md));
|
|
543
550
|
}
|
|
544
551
|
.fi--sm .fi__input {
|
|
545
|
-
font-size: max(16px, var(--fs-sm));
|
|
552
|
+
font-size: max(16px, var(--control-fs-sm));
|
|
546
553
|
}
|
|
547
554
|
}
|
|
548
555
|
.fi--sans .fi__input {
|
|
@@ -555,22 +562,40 @@
|
|
|
555
562
|
color: transparent;
|
|
556
563
|
}
|
|
557
564
|
.fi__clear {
|
|
565
|
+
--clear-scale-dur: var(--dur-fast);
|
|
558
566
|
display: flex;
|
|
559
567
|
border: 0;
|
|
560
568
|
background: transparent;
|
|
569
|
+
font-size: var(--fi-icon);
|
|
561
570
|
color: var(--text-faint);
|
|
562
571
|
cursor: pointer;
|
|
563
572
|
padding: var(--sp-1);
|
|
564
573
|
border-radius: var(--r-sm);
|
|
574
|
+
transition:
|
|
575
|
+
color var(--dur-fast) ease,
|
|
576
|
+
background-color var(--dur-fast) ease,
|
|
577
|
+
opacity var(--dur-fast) ease,
|
|
578
|
+
scale var(--clear-scale-dur) var(--ease-out);
|
|
579
|
+
}
|
|
580
|
+
@starting-style {
|
|
581
|
+
.fi__clear {
|
|
582
|
+
opacity: 0;
|
|
583
|
+
}
|
|
565
584
|
}
|
|
566
|
-
.fi__clear:
|
|
567
|
-
|
|
568
|
-
|
|
585
|
+
.fi__clear:active {
|
|
586
|
+
--clear-scale-dur: var(--dur-press);
|
|
587
|
+
scale: var(--press-scale-sm);
|
|
588
|
+
}
|
|
589
|
+
@media (hover: hover) and (pointer: fine) {
|
|
590
|
+
.fi__clear:hover {
|
|
591
|
+
color: var(--text);
|
|
592
|
+
background: var(--bg-elevated-2);
|
|
593
|
+
}
|
|
569
594
|
}
|
|
570
595
|
|
|
571
596
|
.fi__menu {
|
|
572
597
|
position: absolute;
|
|
573
|
-
top: calc(100% +
|
|
598
|
+
top: calc(100% + var(--sp-1));
|
|
574
599
|
left: 0;
|
|
575
600
|
right: 0;
|
|
576
601
|
z-index: var(--z-drawer);
|
|
@@ -581,6 +606,18 @@
|
|
|
581
606
|
padding: var(--sp-1);
|
|
582
607
|
max-height: 320px;
|
|
583
608
|
overflow-y: auto;
|
|
609
|
+
transform-origin: top left;
|
|
610
|
+
transition:
|
|
611
|
+
opacity var(--dur-fast) var(--ease-out),
|
|
612
|
+
scale var(--dur-fast) var(--ease-out),
|
|
613
|
+
translate var(--dur-fast) var(--ease-out);
|
|
614
|
+
}
|
|
615
|
+
@starting-style {
|
|
616
|
+
.fi__menu {
|
|
617
|
+
opacity: 0;
|
|
618
|
+
scale: var(--enter-scale);
|
|
619
|
+
translate: 0 calc(-1 * var(--shift-sm));
|
|
620
|
+
}
|
|
584
621
|
}
|
|
585
622
|
.fi__menu-head {
|
|
586
623
|
font-size: var(--fs-xs);
|
|
@@ -602,9 +639,12 @@
|
|
|
602
639
|
border-radius: var(--r-sm);
|
|
603
640
|
cursor: pointer;
|
|
604
641
|
font-size: var(--fs-sm);
|
|
642
|
+
transition: background-color var(--dur-fast) ease;
|
|
605
643
|
}
|
|
644
|
+
/* Highlight lands instantly and fades out: list navigation is high frequency. */
|
|
606
645
|
.fi__opt.is-active {
|
|
607
646
|
background: var(--accent-dim);
|
|
647
|
+
transition-duration: var(--dur-instant);
|
|
608
648
|
}
|
|
609
649
|
.fi__opt-label {
|
|
610
650
|
font-weight: var(--fw-medium);
|
|
@@ -75,14 +75,14 @@
|
|
|
75
75
|
.glyph {
|
|
76
76
|
font-weight: var(--fw-bold);
|
|
77
77
|
font-size: 1rem;
|
|
78
|
-
line-height:
|
|
78
|
+
line-height: var(--lh-none);
|
|
79
79
|
}
|
|
80
80
|
.panel {
|
|
81
81
|
width: min(15rem, calc(100vw - var(--sp-6)));
|
|
82
82
|
box-sizing: border-box;
|
|
83
83
|
overflow: hidden;
|
|
84
84
|
font-size: 0.875rem;
|
|
85
|
-
line-height:
|
|
85
|
+
line-height: var(--lh-snug);
|
|
86
86
|
padding: var(--sp-2) var(--sp-3);
|
|
87
87
|
}
|
|
88
88
|
.row {
|
|
@@ -106,16 +106,27 @@
|
|
|
106
106
|
color: var(--text-muted);
|
|
107
107
|
font-family: inherit;
|
|
108
108
|
font-weight: var(--fw-bold);
|
|
109
|
-
line-height:
|
|
109
|
+
line-height: var(--lh-none);
|
|
110
110
|
cursor: pointer;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
--end-scale-dur: var(--dur-fast);
|
|
112
|
+
transition:
|
|
113
|
+
background-color var(--dur-fast) ease,
|
|
114
|
+
color var(--dur-fast) ease,
|
|
115
|
+
scale var(--end-scale-dur) var(--ease-out);
|
|
115
116
|
}
|
|
116
117
|
.end:focus-visible {
|
|
117
|
-
outline:
|
|
118
|
-
outline-offset:
|
|
118
|
+
outline: var(--focus-ring);
|
|
119
|
+
outline-offset: var(--focus-ring-offset-inset);
|
|
120
|
+
}
|
|
121
|
+
.end:active {
|
|
122
|
+
--end-scale-dur: var(--dur-press);
|
|
123
|
+
scale: var(--press-scale-sm);
|
|
124
|
+
}
|
|
125
|
+
@media (hover: hover) and (pointer: fine) {
|
|
126
|
+
.end:hover {
|
|
127
|
+
background: var(--bg-elevated-2);
|
|
128
|
+
color: var(--text);
|
|
129
|
+
}
|
|
119
130
|
}
|
|
120
131
|
.small {
|
|
121
132
|
font-size: 0.75rem;
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
min-width: 0;
|
|
116
116
|
font-family: var(--font-mono);
|
|
117
117
|
font-size: var(--fs-xs);
|
|
118
|
-
line-height:
|
|
118
|
+
line-height: var(--lh-snug);
|
|
119
119
|
white-space: nowrap;
|
|
120
120
|
}
|
|
121
121
|
.chip {
|
|
@@ -123,7 +123,7 @@
|
|
|
123
123
|
align-items: center;
|
|
124
124
|
gap: 0.25em;
|
|
125
125
|
min-width: 0;
|
|
126
|
-
padding: 0
|
|
126
|
+
padding: var(--sp-0-5) var(--sp-2);
|
|
127
127
|
border-radius: var(--r-pill);
|
|
128
128
|
background: var(--bg-elevated-2);
|
|
129
129
|
color: var(--text-muted);
|
|
@@ -137,14 +137,16 @@
|
|
|
137
137
|
color: var(--git-ref-tone);
|
|
138
138
|
border-color: color-mix(in srgb, var(--git-ref-tone) 40%, transparent);
|
|
139
139
|
background: color-mix(in srgb, var(--git-ref-tone) 12%, transparent);
|
|
140
|
-
transition: border-color
|
|
140
|
+
transition: border-color var(--dur-fast) var(--ease);
|
|
141
141
|
}
|
|
142
|
-
|
|
143
|
-
|
|
142
|
+
@media (hover: hover) and (pointer: fine) {
|
|
143
|
+
.pr:hover {
|
|
144
|
+
border-color: var(--git-ref-tone);
|
|
145
|
+
}
|
|
144
146
|
}
|
|
145
147
|
.pr:focus-visible {
|
|
146
|
-
outline:
|
|
147
|
-
outline-offset:
|
|
148
|
+
outline: var(--focus-ring-width) solid var(--git-ref-tone);
|
|
149
|
+
outline-offset: var(--focus-ring-offset);
|
|
148
150
|
}
|
|
149
151
|
.text {
|
|
150
152
|
min-width: 0;
|
|
@@ -55,6 +55,10 @@
|
|
|
55
55
|
}: Omit<HTMLAttributes<HTMLSpanElement>, keyof Own> & Own = $props();
|
|
56
56
|
|
|
57
57
|
let root = $state<HTMLElement>();
|
|
58
|
+
// Coarse pointers cannot hit 1rem cells, so a folded stack with items opens
|
|
59
|
+
// its tiles on tap unless the caller chose an expand mode.
|
|
60
|
+
let coarse = $state(false);
|
|
61
|
+
const mode = $derived(expand !== 'none' ? expand : coarse ? 'tap' : 'none');
|
|
58
62
|
let width = $state(Number.POSITIVE_INFINITY);
|
|
59
63
|
let limit = $state(0);
|
|
60
64
|
const stacked = $derived(stack === 'always' || (stack === 'auto' && width < limit));
|
|
@@ -82,7 +86,7 @@
|
|
|
82
86
|
const CONTROL = 'button, a[href], input, select, textarea, [role="button"], [tabindex]:not([tabindex="-1"])';
|
|
83
87
|
|
|
84
88
|
const tiles = $derived(items?.slice(0, 4) ?? []);
|
|
85
|
-
const expandable = $derived(
|
|
89
|
+
const expandable = $derived(mode !== 'none' && stacked && tiles.length > 0);
|
|
86
90
|
let panel = $state<HTMLDivElement>();
|
|
87
91
|
let open = $state(false);
|
|
88
92
|
let armed = $state(-1);
|
|
@@ -151,7 +155,7 @@
|
|
|
151
155
|
}
|
|
152
156
|
|
|
153
157
|
function onPointerDown(e: PointerEvent) {
|
|
154
|
-
if (!expandable ||
|
|
158
|
+
if (!expandable || mode !== 'slide' || e.button !== 0) return;
|
|
155
159
|
e.preventDefault();
|
|
156
160
|
e.stopPropagation();
|
|
157
161
|
slide.down(e, root);
|
|
@@ -177,12 +181,21 @@
|
|
|
177
181
|
if (!expandable || e.detail === 0) return;
|
|
178
182
|
e.preventDefault();
|
|
179
183
|
e.stopPropagation();
|
|
180
|
-
if (
|
|
184
|
+
if (mode === 'tap') {
|
|
181
185
|
if (open) hide();
|
|
182
186
|
else show();
|
|
183
187
|
}
|
|
184
188
|
}
|
|
185
189
|
|
|
190
|
+
$effect(() => {
|
|
191
|
+
if (!browser || typeof matchMedia !== 'function') return;
|
|
192
|
+
const mq = matchMedia('(pointer: coarse)');
|
|
193
|
+
const sync = () => (coarse = mq.matches);
|
|
194
|
+
sync();
|
|
195
|
+
mq.addEventListener?.('change', sync);
|
|
196
|
+
return () => mq.removeEventListener?.('change', sync);
|
|
197
|
+
});
|
|
198
|
+
|
|
186
199
|
$effect(() => {
|
|
187
200
|
if (!expandable && open) hide();
|
|
188
201
|
});
|
|
@@ -229,7 +242,7 @@
|
|
|
229
242
|
class:stacked
|
|
230
243
|
data-stack={stack}
|
|
231
244
|
data-stacked={stacked || undefined}
|
|
232
|
-
data-expand={expandable ?
|
|
245
|
+
data-expand={expandable ? mode : undefined}
|
|
233
246
|
{...rest}
|
|
234
247
|
onpointerdown={onPointerDown}
|
|
235
248
|
onpointermove={onPointerMove}
|
|
@@ -249,13 +262,13 @@
|
|
|
249
262
|
{/if}
|
|
250
263
|
</span>
|
|
251
264
|
|
|
252
|
-
{#if
|
|
265
|
+
{#if mode !== 'none' && items}
|
|
253
266
|
<!-- `manual`: an `auto` popover would light-dismiss on the captured slide release. -->
|
|
254
267
|
<div
|
|
255
268
|
bind:this={panel}
|
|
256
269
|
popover="manual"
|
|
257
270
|
class="expand-panel"
|
|
258
|
-
data-expand-panel={
|
|
271
|
+
data-expand-panel={mode}
|
|
259
272
|
role="group"
|
|
260
273
|
aria-label={expandLabel}
|
|
261
274
|
ontoggle={onToggle}
|
|
@@ -291,10 +304,12 @@
|
|
|
291
304
|
display: inline-grid;
|
|
292
305
|
grid-template-columns: repeat(2, 1rem);
|
|
293
306
|
grid-auto-rows: 1rem;
|
|
294
|
-
gap:
|
|
307
|
+
gap: var(--sp-px);
|
|
295
308
|
place-items: center;
|
|
296
309
|
}
|
|
310
|
+
/* Cells clip, so any focus ring inside draws inset. */
|
|
297
311
|
.stacked > :global(*) {
|
|
312
|
+
--focus-ring-offset: var(--focus-ring-offset-inset);
|
|
298
313
|
width: 1rem;
|
|
299
314
|
height: 1rem;
|
|
300
315
|
max-width: 1rem;
|
|
@@ -304,7 +319,7 @@
|
|
|
304
319
|
justify-content: center;
|
|
305
320
|
overflow: hidden;
|
|
306
321
|
font-size: var(--fs-xs);
|
|
307
|
-
line-height:
|
|
322
|
+
line-height: var(--lh-none);
|
|
308
323
|
}
|
|
309
324
|
.glyph-stack[data-expand] {
|
|
310
325
|
cursor: pointer;
|
|
@@ -325,18 +340,24 @@
|
|
|
325
340
|
border: 1px solid var(--border-strong);
|
|
326
341
|
border-radius: var(--r-md);
|
|
327
342
|
box-shadow: var(--shadow-md);
|
|
343
|
+
opacity: 0;
|
|
344
|
+
scale: var(--enter-scale);
|
|
345
|
+
transition:
|
|
346
|
+
opacity var(--dur-base) var(--ease-out),
|
|
347
|
+
scale var(--dur-base) var(--ease-out);
|
|
328
348
|
}
|
|
329
349
|
.expand-panel:popover-open {
|
|
330
350
|
display: grid;
|
|
331
351
|
grid-template-columns: repeat(2, minmax(var(--glyph-stack-tile, 3rem), 1fr));
|
|
332
352
|
grid-auto-rows: minmax(var(--glyph-stack-tile, 3rem), 1fr);
|
|
333
353
|
gap: var(--sp-1);
|
|
334
|
-
|
|
354
|
+
opacity: 1;
|
|
355
|
+
scale: 1;
|
|
335
356
|
}
|
|
336
|
-
@
|
|
337
|
-
|
|
357
|
+
@starting-style {
|
|
358
|
+
.expand-panel:popover-open {
|
|
338
359
|
opacity: 0;
|
|
339
|
-
|
|
360
|
+
scale: var(--enter-scale);
|
|
340
361
|
}
|
|
341
362
|
}
|
|
342
363
|
.tile {
|
|
@@ -344,13 +365,16 @@
|
|
|
344
365
|
align-items: center;
|
|
345
366
|
justify-content: center;
|
|
346
367
|
padding: var(--sp-1);
|
|
347
|
-
border-radius: var(--r-
|
|
368
|
+
border-radius: calc(var(--r-md) - var(--sp-1) - 1px);
|
|
348
369
|
background: var(--surface);
|
|
349
|
-
transition:
|
|
370
|
+
transition:
|
|
371
|
+
background var(--dur-fast) var(--ease),
|
|
372
|
+
box-shadow var(--dur-fast) var(--ease);
|
|
350
373
|
}
|
|
351
374
|
.tile.armed {
|
|
352
375
|
background: color-mix(in srgb, var(--accent) 18%, var(--surface));
|
|
353
376
|
box-shadow: inset 0 0 0 2px var(--accent);
|
|
377
|
+
transition-duration: var(--dur-instant);
|
|
354
378
|
}
|
|
355
379
|
.tile-body {
|
|
356
380
|
display: inline-flex;
|
|
@@ -26,8 +26,7 @@
|
|
|
26
26
|
tone?: Tone | 'none';
|
|
27
27
|
// Outlined `--box-lg` square icon-chip (header/toolbar actions).
|
|
28
28
|
chip?: boolean;
|
|
29
|
-
// Shared square box scale (`--box-xs/sm/md/lg`)
|
|
30
|
-
// 2.25rem box. Forwarded to Button.
|
|
29
|
+
// Shared square box scale (`--box-xs/sm/md/lg`). Forwarded to Button.
|
|
31
30
|
box?: 'xs' | 'sm' | 'md' | 'lg';
|
|
32
31
|
// SVG glyph px. Emoji text glyphs render at ×1.35 of it.
|
|
33
32
|
size?: number;
|
|
@@ -63,6 +62,8 @@
|
|
|
63
62
|
* in the accessible name. */
|
|
64
63
|
count?: number;
|
|
65
64
|
countMax?: number;
|
|
65
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
66
|
+
sound?: boolean;
|
|
66
67
|
class?: string;
|
|
67
68
|
};
|
|
68
69
|
|
|
@@ -90,6 +91,7 @@
|
|
|
90
91
|
loading = false,
|
|
91
92
|
count,
|
|
92
93
|
countMax,
|
|
94
|
+
sound = true,
|
|
93
95
|
disabled = false,
|
|
94
96
|
onclick,
|
|
95
97
|
class: klass = '',
|
|
@@ -118,6 +120,7 @@
|
|
|
118
120
|
{loading}
|
|
119
121
|
{count}
|
|
120
122
|
{countMax}
|
|
123
|
+
{sound}
|
|
121
124
|
{title}
|
|
122
125
|
{onclick}
|
|
123
126
|
icon={!inline && !chip && !showLabel}
|
|
@@ -166,6 +169,6 @@
|
|
|
166
169
|
display: inline-flex;
|
|
167
170
|
align-items: center;
|
|
168
171
|
justify-content: center;
|
|
169
|
-
line-height:
|
|
172
|
+
line-height: var(--lh-none);
|
|
170
173
|
}
|
|
171
174
|
</style>
|
|
@@ -40,6 +40,8 @@ type IconButtonProps = HTMLButtonAttributes & {
|
|
|
40
40
|
* in the accessible name. */
|
|
41
41
|
count?: number;
|
|
42
42
|
countMax?: number;
|
|
43
|
+
/** Play UI sounds when enabled globally; false silences this instance. */
|
|
44
|
+
sound?: boolean;
|
|
43
45
|
class?: string;
|
|
44
46
|
};
|
|
45
47
|
declare const IconButton: import("svelte").Component<IconButtonProps, {}, "">;
|
|
@@ -113,9 +113,9 @@
|
|
|
113
113
|
full width and the scrollbar ends above the controls. */
|
|
114
114
|
.ig {
|
|
115
115
|
--ig-h: var(--control-height-default);
|
|
116
|
-
--ig-pad-x: var(--
|
|
116
|
+
--ig-pad-x: var(--control-px-md);
|
|
117
117
|
--ig-gap: var(--sp-2);
|
|
118
|
-
--ig-inset:
|
|
118
|
+
--ig-inset: var(--sp-0-5);
|
|
119
119
|
--ig-radius: var(--r-md);
|
|
120
120
|
position: relative;
|
|
121
121
|
display: flex;
|
|
@@ -123,12 +123,12 @@
|
|
|
123
123
|
}
|
|
124
124
|
.ig-sm {
|
|
125
125
|
--ig-h: var(--control-height-compact);
|
|
126
|
-
--ig-pad-x: var(--
|
|
126
|
+
--ig-pad-x: var(--control-px-sm);
|
|
127
127
|
--ig-gap: var(--sp-1);
|
|
128
128
|
}
|
|
129
129
|
.ig-lg {
|
|
130
130
|
--ig-h: var(--control-height-large);
|
|
131
|
-
--ig-pad-x: var(--
|
|
131
|
+
--ig-pad-x: var(--control-px-lg);
|
|
132
132
|
}
|
|
133
133
|
.ig-field {
|
|
134
134
|
width: 100%;
|
|
@@ -138,10 +138,10 @@
|
|
|
138
138
|
following the field's; inner corners go square. In the bar they hug the
|
|
139
139
|
bottom and side borders, so only the bottom-outer corner is rounded. */
|
|
140
140
|
.ig-adorn {
|
|
141
|
-
--ig-fuse-r: calc(var(--ig-radius) -
|
|
141
|
+
--ig-fuse-r: calc(var(--ig-radius) - var(--sp-px));
|
|
142
142
|
position: absolute;
|
|
143
|
-
top:
|
|
144
|
-
bottom:
|
|
143
|
+
top: var(--sp-px);
|
|
144
|
+
bottom: var(--sp-px);
|
|
145
145
|
z-index: 1;
|
|
146
146
|
display: flex;
|
|
147
147
|
align-items: center;
|
|
@@ -149,10 +149,10 @@
|
|
|
149
149
|
pointer-events: none;
|
|
150
150
|
}
|
|
151
151
|
.ig-leading {
|
|
152
|
-
inset-inline-start:
|
|
152
|
+
inset-inline-start: var(--sp-px);
|
|
153
153
|
}
|
|
154
154
|
.ig-trailing {
|
|
155
|
-
inset-inline-end:
|
|
155
|
+
inset-inline-end: var(--sp-px);
|
|
156
156
|
}
|
|
157
157
|
.ig-adorn > :global(*) {
|
|
158
158
|
pointer-events: auto;
|
|
@@ -197,7 +197,7 @@
|
|
|
197
197
|
}
|
|
198
198
|
.ig-bar .ig-adorn {
|
|
199
199
|
top: auto;
|
|
200
|
-
height: calc(var(--ig-h) -
|
|
200
|
+
height: calc(var(--ig-h) - var(--sp-px));
|
|
201
201
|
}
|
|
202
202
|
.ig-bar .ig-leading > :global(:first-child) {
|
|
203
203
|
--btn-radius: 0 0 0 var(--ig-fuse-r);
|
|
@@ -225,7 +225,7 @@
|
|
|
225
225
|
border: 1px solid var(--textarea-border, var(--border-strong));
|
|
226
226
|
border-top: 0;
|
|
227
227
|
border-radius: 0 0 var(--ig-radius) var(--ig-radius);
|
|
228
|
-
transition: border-color
|
|
228
|
+
transition: border-color var(--dur-fast) ease;
|
|
229
229
|
pointer-events: none;
|
|
230
230
|
}
|
|
231
231
|
.ig-bar:has(.ig-field :global(:focus))::before {
|
|
@@ -244,7 +244,8 @@
|
|
|
244
244
|
pointer-events: none;
|
|
245
245
|
}
|
|
246
246
|
.ig.disabled {
|
|
247
|
-
opacity:
|
|
247
|
+
opacity: var(--disabled-opacity);
|
|
248
|
+
cursor: not-allowed;
|
|
248
249
|
}
|
|
249
250
|
.ig.disabled .ig-adorn > :global(:disabled) {
|
|
250
251
|
opacity: 1;
|