@dorsk/tsumikit 0.40.1 → 0.41.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
CHANGED
|
@@ -167,7 +167,8 @@ Dropzone, CodeBlock, Callout, EmptyState, ConfirmModal, Pagination, Toaster,
|
|
|
167
167
|
ThemePicker (popover grid of 2×2 palette swatches: bg · surface · text · accent per theme), FontScalePicker (popover with a stepped slider across the five text sizes), SectionHeader, KeyValue, LoadMore,
|
|
168
168
|
GitRef (branch chip + PR link tinted by state + `+N −N` diff; `collapse`
|
|
169
169
|
auto/never/glyph degrades to icons inside a narrow `.cq` container),
|
|
170
|
-
CapBar (consumption track with a draggable, keyboard-steppable cap handle
|
|
170
|
+
CapBar (consumption track with a draggable, keyboard-steppable cap handle that
|
|
171
|
+
shows a `N%` bubble while it is moved; `oninput` live, `onchange` on commit),
|
|
171
172
|
Drawer (side-panel `<dialog>`: `side`, `width` clamped to the viewport, full-screen
|
|
172
173
|
under 48rem; `nav` page column that turns into a horizontal strip on narrow
|
|
173
174
|
screens, or `navMobile`; sticky `footer`; Escape / scrim / close button all close),
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
|
|
64
64
|
let trackEl = $state<HTMLDivElement | null>(null);
|
|
65
65
|
let dragging = $state(false);
|
|
66
|
+
let keying = $state(false);
|
|
66
67
|
let committed = cap;
|
|
67
68
|
|
|
68
69
|
function setCap(next: number) {
|
|
@@ -98,6 +99,7 @@
|
|
|
98
99
|
const next = capKeyStep(e.key, e.shiftKey, snapCap(cap, step, min, max), step, min, max);
|
|
99
100
|
if (next === null) return;
|
|
100
101
|
e.preventDefault();
|
|
102
|
+
keying = true;
|
|
101
103
|
setCap(next);
|
|
102
104
|
}
|
|
103
105
|
function keyUp(e: KeyboardEvent) {
|
|
@@ -111,6 +113,7 @@
|
|
|
111
113
|
class="cap-bar size-{size} tone-{tone} {klass}"
|
|
112
114
|
class:readonly
|
|
113
115
|
class:dragging
|
|
116
|
+
class:keying
|
|
114
117
|
style="--label-w: {labelWidth}; --readout-w: {readoutWidth}; --pct: {pct}%; --cap: {capPct}%; {styleProp}"
|
|
115
118
|
>
|
|
116
119
|
{#if label}
|
|
@@ -141,7 +144,9 @@
|
|
|
141
144
|
aria-disabled={readonly ? 'true' : undefined}
|
|
142
145
|
onkeydown={keyDown}
|
|
143
146
|
onkeyup={keyUp}
|
|
147
|
+
onblur={() => (keying = false)}
|
|
144
148
|
></div>
|
|
149
|
+
<div class="bubble" aria-hidden="true">{cap}%</div>
|
|
145
150
|
</div>
|
|
146
151
|
<div class="readout" title={readoutTitle}>
|
|
147
152
|
{#if readout === undefined}{readoutText}{:else if typeof readout === 'string'}{readout}{:else}{@render readout()}{/if}
|
|
@@ -225,6 +230,34 @@
|
|
|
225
230
|
outline: 2px solid var(--accent);
|
|
226
231
|
outline-offset: 2px;
|
|
227
232
|
}
|
|
233
|
+
.bubble {
|
|
234
|
+
position: absolute;
|
|
235
|
+
bottom: calc(100% + 8px);
|
|
236
|
+
left: var(--cap);
|
|
237
|
+
transform: translateX(-50%);
|
|
238
|
+
padding: 1px var(--sp-1);
|
|
239
|
+
border: 1px solid var(--border-strong);
|
|
240
|
+
border-radius: var(--r-sm);
|
|
241
|
+
background: var(--bg-elevated-2);
|
|
242
|
+
box-shadow: var(--shadow-sm);
|
|
243
|
+
color: var(--text);
|
|
244
|
+
font-size: var(--fs-xs);
|
|
245
|
+
line-height: 1.4;
|
|
246
|
+
font-variant-numeric: tabular-nums;
|
|
247
|
+
white-space: nowrap;
|
|
248
|
+
pointer-events: none;
|
|
249
|
+
opacity: 0;
|
|
250
|
+
visibility: hidden;
|
|
251
|
+
transition:
|
|
252
|
+
opacity 0.12s var(--ease),
|
|
253
|
+
visibility 0.12s;
|
|
254
|
+
z-index: 3;
|
|
255
|
+
}
|
|
256
|
+
.dragging .bubble,
|
|
257
|
+
.keying .bubble {
|
|
258
|
+
opacity: 1;
|
|
259
|
+
visibility: visible;
|
|
260
|
+
}
|
|
228
261
|
.readonly .track,
|
|
229
262
|
.readonly .handle {
|
|
230
263
|
cursor: default;
|
|
@@ -251,7 +284,8 @@
|
|
|
251
284
|
grid-column: 1 / 3;
|
|
252
285
|
}
|
|
253
286
|
@media (prefers-reduced-motion: reduce) {
|
|
254
|
-
.fill
|
|
287
|
+
.fill,
|
|
288
|
+
.bubble {
|
|
255
289
|
transition: none;
|
|
256
290
|
}
|
|
257
291
|
}
|
|
@@ -174,10 +174,17 @@
|
|
|
174
174
|
/* The trigger owns its look (a ghost icon-button) from tokens — it no longer
|
|
175
175
|
borrows global .btn classes, so a consumer can restyle it via `triggerClass`
|
|
176
176
|
(+ `bare`) from their own scoped CSS instead of fighting globals. */
|
|
177
|
-
|
|
177
|
+
/* Default trigger chrome. Zero specificity (`:where`) so any consumer class
|
|
178
|
+
(triggerClass) overrides it; `:not(.bare)` keeps it off bare triggers such
|
|
179
|
+
as the Timestamp <time>, which stay plain inline text. */
|
|
180
|
+
:where(.pop-trigger:not(.bare)) {
|
|
178
181
|
display: inline-flex;
|
|
179
182
|
align-items: center;
|
|
180
183
|
justify-content: center;
|
|
184
|
+
min-height: var(--box-md);
|
|
185
|
+
min-width: var(--box-md);
|
|
186
|
+
padding: var(--sp-2);
|
|
187
|
+
border: 1px solid transparent;
|
|
181
188
|
border-radius: var(--r-md);
|
|
182
189
|
background: transparent;
|
|
183
190
|
color: var(--text);
|
|
@@ -185,15 +192,7 @@
|
|
|
185
192
|
background 0.12s var(--ease),
|
|
186
193
|
border-color 0.12s var(--ease);
|
|
187
194
|
}
|
|
188
|
-
|
|
189
|
-
Timestamp <time>) keeps its text's line box. */
|
|
190
|
-
.pop-trigger:not(.bare) {
|
|
191
|
-
min-height: var(--box-md);
|
|
192
|
-
min-width: var(--box-md);
|
|
193
|
-
padding: var(--sp-2);
|
|
194
|
-
border: 1px solid transparent;
|
|
195
|
-
}
|
|
196
|
-
.pop-trigger:hover:not(:disabled) {
|
|
195
|
+
:where(.pop-trigger:not(.bare):hover:not(:disabled)) {
|
|
197
196
|
background: var(--bg-elevated-2);
|
|
198
197
|
}
|
|
199
198
|
/* Supplying canonical chrome props opts into the same dimensions, variants
|
|
@@ -328,19 +327,15 @@
|
|
|
328
327
|
/* `bare`: strip the chrome down to a plain button the consumer styles. */
|
|
329
328
|
:where(.pop-trigger.bare) {
|
|
330
329
|
display: inline;
|
|
331
|
-
height: auto;
|
|
332
|
-
min-height: 0;
|
|
333
|
-
min-width: 0;
|
|
334
|
-
width: auto;
|
|
335
330
|
padding: 0;
|
|
336
331
|
border: 0;
|
|
332
|
+
border-radius: 0;
|
|
337
333
|
background: none;
|
|
334
|
+
color: inherit;
|
|
338
335
|
font: inherit;
|
|
339
336
|
line-height: inherit;
|
|
340
337
|
vertical-align: baseline;
|
|
341
|
-
|
|
342
|
-
:where(.pop-trigger.bare:hover:not(:disabled)) {
|
|
343
|
-
background: none;
|
|
338
|
+
cursor: pointer;
|
|
344
339
|
}
|
|
345
340
|
.pop-panel {
|
|
346
341
|
position: fixed;
|
package/package.json
CHANGED