@ponchia/ui 0.5.0 → 0.6.3
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/CHANGELOG.md +386 -4
- package/MIGRATIONS.json +14 -0
- package/README.md +29 -6
- package/annotations/index.d.ts +398 -276
- package/annotations/index.d.ts.map +1 -0
- package/annotations/index.js +350 -77
- package/behaviors/carousel.d.ts +28 -0
- package/behaviors/carousel.d.ts.map +1 -0
- package/behaviors/carousel.js +20 -16
- package/behaviors/combobox.d.ts +40 -0
- package/behaviors/combobox.d.ts.map +1 -0
- package/behaviors/combobox.js +111 -29
- package/behaviors/command.d.ts +41 -0
- package/behaviors/command.d.ts.map +1 -0
- package/behaviors/command.js +27 -15
- package/behaviors/connectors.d.ts +17 -0
- package/behaviors/connectors.d.ts.map +1 -0
- package/behaviors/connectors.js +7 -5
- package/behaviors/crosshair.d.ts +42 -0
- package/behaviors/crosshair.d.ts.map +1 -0
- package/behaviors/crosshair.js +23 -6
- package/behaviors/dialog.d.ts +20 -0
- package/behaviors/dialog.d.ts.map +1 -0
- package/behaviors/dialog.js +6 -2
- package/behaviors/disclosure.d.ts +10 -0
- package/behaviors/disclosure.d.ts.map +1 -0
- package/behaviors/disclosure.js +6 -2
- package/behaviors/dismissible.d.ts +10 -0
- package/behaviors/dismissible.d.ts.map +1 -0
- package/behaviors/dismissible.js +6 -2
- package/behaviors/forms.d.ts +27 -0
- package/behaviors/forms.d.ts.map +1 -0
- package/behaviors/forms.js +54 -13
- package/behaviors/glyph.d.ts +14 -0
- package/behaviors/glyph.d.ts.map +1 -0
- package/behaviors/glyph.js +28 -5
- package/behaviors/index.d.ts +31 -237
- package/behaviors/index.d.ts.map +1 -0
- package/behaviors/index.js +17 -0
- package/behaviors/inert.d.ts +20 -0
- package/behaviors/inert.d.ts.map +1 -0
- package/behaviors/inert.js +46 -0
- package/behaviors/internal.d.ts +25 -0
- package/behaviors/internal.d.ts.map +1 -0
- package/behaviors/internal.js +77 -1
- package/behaviors/legend.d.ts +35 -0
- package/behaviors/legend.d.ts.map +1 -0
- package/behaviors/legend.js +32 -2
- package/behaviors/menu.d.ts +16 -0
- package/behaviors/menu.d.ts.map +1 -0
- package/behaviors/menu.js +6 -2
- package/behaviors/modal.d.ts +41 -0
- package/behaviors/modal.d.ts.map +1 -0
- package/behaviors/modal.js +124 -0
- package/behaviors/popover.d.ts +28 -0
- package/behaviors/popover.d.ts.map +1 -0
- package/behaviors/popover.js +78 -7
- package/behaviors/spotlight.d.ts +17 -0
- package/behaviors/spotlight.d.ts.map +1 -0
- package/behaviors/spotlight.js +7 -5
- package/behaviors/table.d.ts +36 -0
- package/behaviors/table.d.ts.map +1 -0
- package/behaviors/table.js +84 -17
- package/behaviors/tabs.d.ts +20 -0
- package/behaviors/tabs.d.ts.map +1 -0
- package/behaviors/tabs.js +17 -14
- package/behaviors/theme.d.ts +54 -0
- package/behaviors/theme.d.ts.map +1 -0
- package/behaviors/theme.js +22 -3
- package/behaviors/toast.d.ts +49 -0
- package/behaviors/toast.d.ts.map +1 -0
- package/behaviors/toast.js +47 -3
- package/classes/classes.json +2527 -0
- package/classes/index.d.ts +134 -15
- package/classes/index.js +280 -80
- package/classes/vscode.css-custom-data.json +12 -0
- package/connectors/index.d.ts +201 -69
- package/connectors/index.d.ts.map +1 -0
- package/connectors/index.js +142 -25
- package/css/app.css +69 -13
- package/css/base.css +15 -10
- package/css/bullet.css +108 -0
- package/css/code.css +98 -0
- package/css/connectors.css +17 -0
- package/css/content.css +22 -3
- package/css/crosshair.css +7 -7
- package/css/dataviz.css +5 -1
- package/css/diff.css +153 -0
- package/css/disclosure.css +53 -7
- package/css/dots.css +94 -7
- package/css/feedback.css +97 -7
- package/css/forms.css +113 -4
- package/css/legend.css +16 -9
- package/css/marks.css +38 -8
- package/css/motion.css +98 -53
- package/css/navigation.css +7 -0
- package/css/overlay.css +90 -3
- package/css/primitives.css +158 -13
- package/css/report.css +73 -56
- package/css/sidenote.css +67 -0
- package/css/site.css +16 -2
- package/css/sources.css +43 -1
- package/css/spark.css +62 -0
- package/css/spotlight.css +1 -1
- package/css/table.css +9 -2
- package/css/term.css +110 -0
- package/css/textref.css +63 -0
- package/css/toc.css +91 -0
- package/css/tokens.css +49 -1
- package/css/tree.css +134 -0
- package/css/workbench.css +1 -1
- package/dist/bronto.css +1 -1
- package/dist/css/analytical.css +1 -1
- package/dist/css/app.css +1 -1
- package/dist/css/base.css +1 -1
- package/dist/css/bullet.css +1 -0
- package/dist/css/code.css +1 -0
- package/dist/css/connectors.css +1 -1
- package/dist/css/content.css +1 -1
- package/dist/css/crosshair.css +1 -1
- package/dist/css/diff.css +1 -0
- package/dist/css/disclosure.css +1 -1
- package/dist/css/dots.css +1 -1
- package/dist/css/feedback.css +1 -1
- package/dist/css/forms.css +1 -1
- package/dist/css/legend.css +1 -1
- package/dist/css/marks.css +1 -1
- package/dist/css/motion.css +1 -1
- package/dist/css/navigation.css +1 -1
- package/dist/css/overlay.css +1 -1
- package/dist/css/primitives.css +1 -1
- package/dist/css/report.css +1 -1
- package/dist/css/sidenote.css +1 -0
- package/dist/css/site.css +1 -1
- package/dist/css/sources.css +1 -1
- package/dist/css/spark.css +1 -0
- package/dist/css/spotlight.css +1 -1
- package/dist/css/table.css +1 -1
- package/dist/css/term.css +1 -0
- package/dist/css/textref.css +1 -0
- package/dist/css/toc.css +1 -0
- package/dist/css/tokens.css +1 -1
- package/dist/css/tree.css +1 -0
- package/dist/css/workbench.css +1 -1
- package/docs/adr/0003-theme-model.md +1 -1
- package/docs/annotations.md +133 -14
- package/docs/architecture.md +49 -6
- package/docs/bullet.md +78 -0
- package/docs/code.md +76 -0
- package/docs/contrast.md +116 -92
- package/docs/d2.md +196 -0
- package/docs/diff.md +146 -0
- package/docs/legends.md +23 -3
- package/docs/marks.md +9 -2
- package/docs/mermaid.md +169 -0
- package/docs/reference.md +201 -26
- package/docs/reporting.md +416 -57
- package/docs/sidenote.md +64 -0
- package/docs/sources.md +27 -0
- package/docs/spark.md +78 -0
- package/docs/stability.md +10 -2
- package/docs/term.md +81 -0
- package/docs/textref.md +78 -0
- package/docs/theming.md +44 -5
- package/docs/toc.md +83 -0
- package/docs/tree.md +74 -0
- package/docs/usage.md +354 -16
- package/docs/vega.md +244 -0
- package/docs/workbench.md +7 -1
- package/glyphs/glyphs.js +13 -5
- package/llms.txt +285 -14
- package/package.json +95 -17
- package/qwik/index.d.ts +44 -59
- package/qwik/index.d.ts.map +1 -0
- package/qwik/index.js +65 -3
- package/react/index.d.ts +41 -61
- package/react/index.d.ts.map +1 -0
- package/react/index.js +63 -3
- package/solid/index.d.ts +68 -61
- package/solid/index.d.ts.map +1 -0
- package/solid/index.js +66 -3
- package/tokens/d2.d.ts +38 -0
- package/tokens/d2.js +71 -0
- package/tokens/d2.json +43 -0
- package/tokens/index.d.ts +5 -5
- package/tokens/index.js +15 -1
- package/tokens/index.json +9 -0
- package/tokens/mermaid.d.ts +23 -0
- package/tokens/mermaid.js +181 -0
- package/tokens/mermaid.json +163 -0
- package/tokens/resolved.json +45 -1
- package/tokens/skins.js +3 -2
- package/tokens/tokens.dtcg.json +26 -0
- package/tokens/vega.d.ts +34 -0
- package/tokens/vega.js +155 -0
- package/tokens/vega.json +179 -0
package/css/primitives.css
CHANGED
|
@@ -71,12 +71,15 @@
|
|
|
71
71
|
padding-inline: var(--center-gutter, var(--space-md));
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
/* Intrinsic aspect-ratio box; the media child fills it.
|
|
74
|
+
/* Intrinsic aspect-ratio box; the media child fills it. The contract is ONE
|
|
75
|
+
child (a single <img>/<video>/<iframe>). Scope the fill to :first-child rather
|
|
76
|
+
than every child: a second child would otherwise be forced to 100%/100% +
|
|
77
|
+
object-fit and stack on top, silently breaking the ratio. (audit C34.) */
|
|
75
78
|
.ui-ratio {
|
|
76
79
|
aspect-ratio: var(--ratio, 16 / 9);
|
|
77
80
|
}
|
|
78
81
|
|
|
79
|
-
.ui-ratio >
|
|
82
|
+
.ui-ratio > :first-child {
|
|
80
83
|
block-size: 100%;
|
|
81
84
|
inline-size: 100%;
|
|
82
85
|
object-fit: cover;
|
|
@@ -87,10 +90,18 @@
|
|
|
87
90
|
(island-safe). Inert until applied, so existing layouts/baselines
|
|
88
91
|
are unaffected. */
|
|
89
92
|
.ui-cq {
|
|
90
|
-
container
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
93
|
+
/* The container-name is fixed: the `@container bronto (…)` collapse queries
|
|
94
|
+
below hardcode `bronto`. There is no `--cq-name` knob — the name is not
|
|
95
|
+
author-tunable, and an author-set `--cq-name` is simply ignored (nothing
|
|
96
|
+
reads it). Name a different container yourself if you need a custom scope. */
|
|
97
|
+
container: bronto / inline-size;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* Logical `max-inline-size`, not physical `max-width`: the container is typed
|
|
101
|
+
`inline-size`, so the inline axis is the one actually tracked — the logical
|
|
102
|
+
query matches it in any writing mode (a physical `width` query silently
|
|
103
|
+
misses in a vertical WM). (component audit C34.) */
|
|
104
|
+
@container bronto (max-inline-size: 34rem) {
|
|
94
105
|
.ui-grid {
|
|
95
106
|
--grid-min: 100%;
|
|
96
107
|
}
|
|
@@ -164,7 +175,7 @@
|
|
|
164
175
|
/* Inside an opt-in .ui-cq container, collapse to one column when the
|
|
165
176
|
container (not the viewport) is narrow — keeps tiles usable in a slim
|
|
166
177
|
panel. Inert without .ui-cq, so baselines are unaffected. */
|
|
167
|
-
@container bronto (max-
|
|
178
|
+
@container bronto (max-inline-size: 30rem) {
|
|
168
179
|
.ui-statgrid,
|
|
169
180
|
.ui-app-metrics {
|
|
170
181
|
grid-template-columns: 1fr;
|
|
@@ -178,6 +189,12 @@
|
|
|
178
189
|
border-radius: var(--radius-md);
|
|
179
190
|
display: grid;
|
|
180
191
|
gap: 0.4rem;
|
|
192
|
+
|
|
193
|
+
/* These tiles hold IDs / hashes / big numbers — the unbreakable-token case is
|
|
194
|
+
the common one. A grid item defaults to min-inline-size:auto, so a long
|
|
195
|
+
value pushes the whole statgrid track wider; allow the tile to shrink so the
|
|
196
|
+
value can wrap instead (paired with overflow-wrap on __value). (audit C5.) */
|
|
197
|
+
min-inline-size: 0;
|
|
181
198
|
padding: var(--space-md);
|
|
182
199
|
}
|
|
183
200
|
|
|
@@ -196,8 +213,10 @@
|
|
|
196
213
|
font-family: var(--display);
|
|
197
214
|
font-size: 1.9rem;
|
|
198
215
|
font-variant-numeric: tabular-nums;
|
|
199
|
-
|
|
200
|
-
|
|
216
|
+
font-weight: var(--display-weight-strong);
|
|
217
|
+
letter-spacing: 0.02em;
|
|
218
|
+
line-height: 1.05;
|
|
219
|
+
overflow-wrap: anywhere; /* break an unspaced ID/hash rather than overflow (audit C5) */
|
|
201
220
|
}
|
|
202
221
|
|
|
203
222
|
.ui-stat__delta,
|
|
@@ -216,12 +235,32 @@
|
|
|
216
235
|
color: var(--danger);
|
|
217
236
|
}
|
|
218
237
|
|
|
238
|
+
/* A direction arrow is the non-colour channel — colour alone (success/danger)
|
|
239
|
+
fails WCAG 1.4.1, so the tile carries the same ▲/▼ glyph as `.ui-delta`
|
|
240
|
+
(C13). Marked aria-hidden-equivalent by being generated content; the sign is
|
|
241
|
+
still in the author's text ("+12%"). */
|
|
242
|
+
.ui-stat__delta.is-pos::before,
|
|
243
|
+
.ui-app-metric__delta.is-pos::before {
|
|
244
|
+
content: '▲ ';
|
|
245
|
+
font-size: 0.85em;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.ui-stat__delta.is-neg::before,
|
|
249
|
+
.ui-app-metric__delta.is-neg::before {
|
|
250
|
+
content: '▼ ';
|
|
251
|
+
font-size: 0.85em;
|
|
252
|
+
}
|
|
253
|
+
|
|
219
254
|
/* --- Numeric value vocabulary ---
|
|
220
255
|
The same tabular/aligned/tone intent the table has shipped since
|
|
221
256
|
0.1.0, but freed from `.ui-table` so cards, stats and inline figures
|
|
222
257
|
share one P&L vocabulary. Token-identical to the table's is-num/
|
|
223
258
|
is-pos/is-neg (which stay table-local). */
|
|
224
259
|
.ui-num {
|
|
260
|
+
/* inline-block so `text-align: end` actually applies: on a bare inline element
|
|
261
|
+
it computes but never paints (the box is shrink-wrapped), so an author who
|
|
262
|
+
followed the docs to right-align an inline figure saw no effect. (audit C17.) */
|
|
263
|
+
display: inline-block;
|
|
225
264
|
font-variant-numeric: tabular-nums;
|
|
226
265
|
text-align: end;
|
|
227
266
|
}
|
|
@@ -238,6 +277,58 @@
|
|
|
238
277
|
color: var(--text-dim);
|
|
239
278
|
}
|
|
240
279
|
|
|
280
|
+
/* --- Trend delta ---
|
|
281
|
+
A standalone change indicator: a direction arrow (the non-colour channel,
|
|
282
|
+
WCAG 1.4.1) plus the figure, tabular so a column of deltas aligns.
|
|
283
|
+
Direction sets the glyph AND the conventional tone (up = positive,
|
|
284
|
+
down = negative). When "up" is the bad direction (latency, error rate,
|
|
285
|
+
cost, churn), add `ui-delta--invert` to swap only the tone — the arrow
|
|
286
|
+
still reports real direction. Pair with words; the arrow is visual, not a
|
|
287
|
+
substitute for stating the change. */
|
|
288
|
+
.ui-delta {
|
|
289
|
+
align-items: baseline;
|
|
290
|
+
color: var(--text-soft);
|
|
291
|
+
display: inline-flex;
|
|
292
|
+
font-variant-numeric: tabular-nums;
|
|
293
|
+
gap: 0.2em;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.ui-delta::before {
|
|
297
|
+
font-size: 0.85em;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.ui-delta--up {
|
|
301
|
+
color: var(--success);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.ui-delta--up::before {
|
|
305
|
+
content: '▲';
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.ui-delta--down {
|
|
309
|
+
color: var(--danger);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.ui-delta--down::before {
|
|
313
|
+
content: '▼';
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.ui-delta--flat {
|
|
317
|
+
color: var(--text-dim);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.ui-delta--flat::before {
|
|
321
|
+
content: '—';
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.ui-delta--invert.ui-delta--up {
|
|
325
|
+
color: var(--danger);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.ui-delta--invert.ui-delta--down {
|
|
329
|
+
color: var(--success);
|
|
330
|
+
}
|
|
331
|
+
|
|
241
332
|
/* --- Eyebrow / section label — dot-matrix face --- */
|
|
242
333
|
|
|
243
334
|
.ui-eyebrow {
|
|
@@ -338,6 +429,28 @@
|
|
|
338
429
|
opacity: 0.45;
|
|
339
430
|
}
|
|
340
431
|
|
|
432
|
+
/* aria-disabled keeps the element in the a11y tree but the browser does NOT
|
|
433
|
+
block activation (a real <a class="ui-button" aria-disabled> still navigates,
|
|
434
|
+
a <button> still fires). `pointer-events: none` kills POINTER activation only
|
|
435
|
+
— a focused control still fires on Enter/Space, which CSS cannot intercept. So
|
|
436
|
+
this looks-dead state is NOT keyboard-inert: for that, prefer native
|
|
437
|
+
`<button disabled>`, run `initDisabledGuard()` (it intercepts Enter/Space on
|
|
438
|
+
aria-disabled controls), or add `tabindex="-1"` (and drop `href` on a link).
|
|
439
|
+
See docs/usage.md "Disabled vs aria-disabled". (a11y review C3 / audit C4;
|
|
440
|
+
native :disabled already inert.) */
|
|
441
|
+
.ui-button[aria-disabled='true'],
|
|
442
|
+
.ui-link[aria-disabled='true'] {
|
|
443
|
+
pointer-events: none;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/* The button family dims + shows not-allowed via its `:disabled` rule above, but
|
|
447
|
+
a disabled LINK got only pointer-events:none — it looked fully live. Give it
|
|
448
|
+
the same visual disabled cue. (component audit C30.) */
|
|
449
|
+
.ui-link[aria-disabled='true'] {
|
|
450
|
+
cursor: not-allowed;
|
|
451
|
+
opacity: 0.45;
|
|
452
|
+
}
|
|
453
|
+
|
|
341
454
|
.ui-button:active {
|
|
342
455
|
transform: translateY(1px);
|
|
343
456
|
}
|
|
@@ -363,8 +476,13 @@
|
|
|
363
476
|
}
|
|
364
477
|
|
|
365
478
|
@media (prefers-reduced-motion: reduce) {
|
|
479
|
+
/* The global reduced-motion reset freezes the spin on a single frame with an
|
|
480
|
+
!important `animation-duration`, so the old non-important `1.4s` slow-spin
|
|
481
|
+
here was dead code AND left a broken, transparent-topped ring looking like a
|
|
482
|
+
rendering bug. Drop the dead rule; show a STATIC complete ring instead — a
|
|
483
|
+
still busy cue with no implied motion. (component audit C15.) */
|
|
366
484
|
.ui-button[aria-busy='true']::before {
|
|
367
|
-
|
|
485
|
+
border-block-start-color: currentcolor;
|
|
368
486
|
}
|
|
369
487
|
}
|
|
370
488
|
|
|
@@ -401,8 +519,8 @@
|
|
|
401
519
|
|
|
402
520
|
.ui-link--arrow::after,
|
|
403
521
|
.ui-link--cta::after {
|
|
404
|
-
border-inline-end: 1px solid
|
|
405
|
-
border-block-start: 1px solid
|
|
522
|
+
border-inline-end: 1px solid currentcolor;
|
|
523
|
+
border-block-start: 1px solid currentcolor;
|
|
406
524
|
content: '';
|
|
407
525
|
block-size: 0.42rem;
|
|
408
526
|
transform: rotate(45deg);
|
|
@@ -410,6 +528,27 @@
|
|
|
410
528
|
inline-size: 0.42rem;
|
|
411
529
|
}
|
|
412
530
|
|
|
531
|
+
/* RTL: the logical borders flip sides, but a fixed `rotate(45deg)` then points
|
|
532
|
+
the chevron UP rather than toward the inline-end (the reading-forward way).
|
|
533
|
+
Mirror the rotation so the resting affordance points forward in RTL too.
|
|
534
|
+
(component audit C14.) */
|
|
535
|
+
[dir='rtl'] .ui-link--arrow::after,
|
|
536
|
+
[dir='rtl'] .ui-link--cta::after {
|
|
537
|
+
transform: rotate(-45deg);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/* Standalone CTA links are tap targets, not inline prose links: on a coarse
|
|
541
|
+
pointer float them to the WCAG 2.5.8 AA 24px floor (the 2.5.8 inline-link
|
|
542
|
+
exception doesn't cover a block-level call-to-action, which is what these
|
|
543
|
+
are). Buttons already auto-grow to ~44px on coarse pointers. (component
|
|
544
|
+
audit C14.) */
|
|
545
|
+
@media (pointer: coarse) {
|
|
546
|
+
.ui-link--arrow,
|
|
547
|
+
.ui-link--cta {
|
|
548
|
+
min-block-size: 1.5rem;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
413
552
|
/* --- Chip / tag --- */
|
|
414
553
|
|
|
415
554
|
.ui-chip {
|
|
@@ -459,6 +598,10 @@
|
|
|
459
598
|
(the soft tint can't carry 4.5:1 small-bold tone-on-tone — WCAG). */
|
|
460
599
|
.ui-badge--accent {
|
|
461
600
|
background: var(--accent-soft);
|
|
601
|
+
|
|
602
|
+
/* Accent mixes 45% (vs 40% for the status tones below) on purpose: the brand
|
|
603
|
+
hue is lower-chroma here than the status hues, so it needs a touch more to
|
|
604
|
+
read at the same border weight. Intentional, not a copy-paste slip. (Q15.) */
|
|
462
605
|
border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
|
|
463
606
|
}
|
|
464
607
|
|
|
@@ -551,6 +694,8 @@
|
|
|
551
694
|
color: var(--text);
|
|
552
695
|
font-family: var(--mono);
|
|
553
696
|
margin: 0;
|
|
697
|
+
min-inline-size: 0;
|
|
698
|
+
overflow-wrap: anywhere; /* IDs/hashes/paths are the common value — break, don't overflow (audit C5) */
|
|
554
699
|
}
|
|
555
700
|
|
|
556
701
|
/* --- Hover (pointer only) --- */
|
|
@@ -593,7 +738,7 @@
|
|
|
593
738
|
|
|
594
739
|
[dir='rtl'] .ui-link--arrow:hover::after,
|
|
595
740
|
[dir='rtl'] .ui-link--cta:hover::after {
|
|
596
|
-
transform: translateX(-0.14rem) rotate(45deg);
|
|
741
|
+
transform: translateX(-0.14rem) rotate(-45deg);
|
|
597
742
|
}
|
|
598
743
|
|
|
599
744
|
.ui-chip--accent:hover {
|
package/css/report.css
CHANGED
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
========================================================================== */
|
|
8
8
|
|
|
9
9
|
.ui-report {
|
|
10
|
+
/* Declare override-surface tokens first so authors can set them. */
|
|
11
|
+
--report-width: 72rem;
|
|
12
|
+
--report-padding-block: var(--space-2xl);
|
|
10
13
|
--report-gap: var(--space-lg);
|
|
11
14
|
--report-measure: 74ch;
|
|
12
15
|
--report-page-margin: 18mm;
|
|
@@ -14,9 +17,9 @@
|
|
|
14
17
|
color: var(--text-soft);
|
|
15
18
|
display: grid;
|
|
16
19
|
gap: var(--report-gap);
|
|
17
|
-
inline-size: min(100%, var(--report-width
|
|
20
|
+
inline-size: min(100%, var(--report-width));
|
|
18
21
|
margin-inline: auto;
|
|
19
|
-
padding: var(--report-padding-block
|
|
22
|
+
padding: var(--report-padding-block) var(--space-md);
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
.ui-report--compact {
|
|
@@ -42,7 +45,7 @@
|
|
|
42
45
|
padding-block: var(--space-xl) var(--space-lg);
|
|
43
46
|
}
|
|
44
47
|
|
|
45
|
-
.ui-
|
|
48
|
+
.ui-report__head {
|
|
46
49
|
align-items: end;
|
|
47
50
|
border-block-end: 1px solid var(--line);
|
|
48
51
|
display: flex;
|
|
@@ -56,6 +59,7 @@
|
|
|
56
59
|
color: var(--text);
|
|
57
60
|
font-family: var(--display);
|
|
58
61
|
font-size: calc(var(--text-xl) * 1.35);
|
|
62
|
+
font-weight: var(--display-weight-strong);
|
|
59
63
|
letter-spacing: 0;
|
|
60
64
|
line-height: 1.05;
|
|
61
65
|
margin: 0;
|
|
@@ -171,6 +175,7 @@
|
|
|
171
175
|
color: var(--text);
|
|
172
176
|
font-family: var(--display);
|
|
173
177
|
font-size: var(--text-xl);
|
|
178
|
+
font-weight: var(--display-weight);
|
|
174
179
|
letter-spacing: 0;
|
|
175
180
|
line-height: 1.1;
|
|
176
181
|
margin: 0;
|
|
@@ -195,8 +200,7 @@
|
|
|
195
200
|
margin: 0;
|
|
196
201
|
}
|
|
197
202
|
|
|
198
|
-
.ui-report__caption
|
|
199
|
-
.ui-chart__caption {
|
|
203
|
+
.ui-report__caption {
|
|
200
204
|
color: var(--text-dim);
|
|
201
205
|
font-family: var(--mono);
|
|
202
206
|
font-size: var(--text-2xs);
|
|
@@ -216,65 +220,88 @@
|
|
|
216
220
|
padding-block-start: var(--space-md);
|
|
217
221
|
}
|
|
218
222
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
223
|
+
/* --- Comparison layout ---
|
|
224
|
+
The report layer's "A vs B" / before-after grid — the side-by-side layout
|
|
225
|
+
reports lean on that the grammar was missing. Fluid-first: columns wrap to
|
|
226
|
+
a single stack on a narrow screen via auto-fit, so two panels never
|
|
227
|
+
overflow. `ui-compare__col` is one side, `ui-compare__head` labels it.
|
|
228
|
+
`ui-compare--2up` pins exactly two equal columns for a hard before/after
|
|
229
|
+
pairing (still collapsing to one column on a phone). */
|
|
230
|
+
.ui-compare {
|
|
222
231
|
display: grid;
|
|
223
|
-
gap: var(--space-
|
|
224
|
-
|
|
232
|
+
gap: var(--space-md);
|
|
233
|
+
grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
|
|
225
234
|
}
|
|
226
235
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
a legend. The chart owns only its plot + bars + fallback below. */
|
|
230
|
-
.ui-chart__plot {
|
|
231
|
-
display: grid;
|
|
232
|
-
gap: var(--space-xs);
|
|
236
|
+
.ui-compare--2up {
|
|
237
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
233
238
|
}
|
|
234
239
|
|
|
235
|
-
|
|
236
|
-
--
|
|
240
|
+
@media (max-width: 33rem) {
|
|
241
|
+
.ui-compare--2up {
|
|
242
|
+
grid-template-columns: 1fr;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
237
245
|
|
|
246
|
+
.ui-compare__col {
|
|
247
|
+
align-content: start;
|
|
238
248
|
display: grid;
|
|
239
|
-
gap:
|
|
249
|
+
gap: var(--space-sm);
|
|
240
250
|
}
|
|
241
251
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
252
|
+
.ui-compare__head {
|
|
253
|
+
color: var(--text-dim);
|
|
254
|
+
font-family: var(--mono);
|
|
255
|
+
font-size: var(--text-2xs);
|
|
256
|
+
letter-spacing: var(--tracking-wide);
|
|
257
|
+
text-transform: uppercase;
|
|
247
258
|
}
|
|
248
259
|
|
|
249
|
-
|
|
260
|
+
/* --- Labelled meter row ---
|
|
261
|
+
A multi-meter block (SLO burn, error budgets, capacity) lays out as
|
|
262
|
+
label | bar | value. The bare `ui-meter` base lives in feedback.css; this is
|
|
263
|
+
the report-document grammar around it so authors stop hand-rolling the grid.
|
|
264
|
+
The bar NEVER carries the reading alone (WCAG 1.4.1) — `ui-meter__value` is
|
|
265
|
+
the data of record, and the bar clamps at 100 so an over-target figure still
|
|
266
|
+
reads correctly in the value text. Collapses to a stack on a narrow screen. */
|
|
267
|
+
.ui-meter__row {
|
|
250
268
|
align-items: center;
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
gap: var(--space-sm);
|
|
256
|
-
justify-content: space-between;
|
|
269
|
+
display: grid;
|
|
270
|
+
gap: var(--space-2xs) var(--space-md);
|
|
271
|
+
grid-template-columns: minmax(9rem, 14rem) 1fr auto;
|
|
272
|
+
margin-block: var(--space-2xs);
|
|
257
273
|
}
|
|
258
274
|
|
|
259
|
-
.ui-
|
|
260
|
-
|
|
261
|
-
border: 1px solid var(--line);
|
|
262
|
-
block-size: 0.8rem;
|
|
263
|
-
min-inline-size: 0;
|
|
275
|
+
.ui-meter__row .ui-meter {
|
|
276
|
+
min-inline-size: 8rem;
|
|
264
277
|
}
|
|
265
278
|
|
|
266
|
-
.ui-
|
|
267
|
-
|
|
268
|
-
background-image: var(--chart-pattern, var(--chart-pattern-1, none));
|
|
269
|
-
background-size: var(--chart-pattern-size, 8px);
|
|
270
|
-
block-size: 100%;
|
|
271
|
-
inline-size: clamp(0%, var(--chart-value), 100%);
|
|
279
|
+
.ui-meter__label {
|
|
280
|
+
color: var(--text-soft);
|
|
272
281
|
}
|
|
273
282
|
|
|
274
|
-
.ui-
|
|
275
|
-
|
|
283
|
+
.ui-meter__value {
|
|
284
|
+
color: var(--text);
|
|
285
|
+
font-family: var(--mono);
|
|
286
|
+
font-variant-numeric: tabular-nums;
|
|
287
|
+
text-align: end;
|
|
276
288
|
}
|
|
277
289
|
|
|
290
|
+
@media (max-width: 32rem) {
|
|
291
|
+
.ui-meter__row {
|
|
292
|
+
grid-template-columns: 1fr;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.ui-meter__value {
|
|
296
|
+
text-align: start;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/* A chart is NOT a bronto component — it needs scales + data binding, which the
|
|
301
|
+
analytical layer refuses to own. Theme Vega-Lite with `@ponchia/ui/vega`
|
|
302
|
+
(docs/vega.md), or hand-author a token-themed inline `<svg>`, and drop it in a
|
|
303
|
+
`.ui-report__figure` with a `.ui-report__caption` + a `.ui-legend` key. */
|
|
304
|
+
|
|
278
305
|
.ui-print-only {
|
|
279
306
|
display: none !important;
|
|
280
307
|
}
|
|
@@ -313,27 +340,17 @@
|
|
|
313
340
|
padding: 0;
|
|
314
341
|
}
|
|
315
342
|
|
|
316
|
-
/* Meaning-carrying chart fills must survive the print "economy" default
|
|
317
|
-
(which drops backgrounds) without relying on a `.ui-print-exact`
|
|
318
|
-
ancestor. The accent on `.ui-report__summary` is a border, so it already
|
|
319
|
-
prints. (Legend swatches print-protect themselves in css/legend.css.) */
|
|
320
|
-
.ui-chart__fill {
|
|
321
|
-
-webkit-print-color-adjust: exact;
|
|
322
|
-
print-color-adjust: exact;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
343
|
.ui-report__cover {
|
|
326
344
|
min-block-size: auto;
|
|
327
345
|
}
|
|
328
346
|
|
|
329
347
|
.ui-report__cover,
|
|
330
|
-
.ui-
|
|
348
|
+
.ui-report__head,
|
|
331
349
|
.ui-report__section,
|
|
332
350
|
.ui-report__summary,
|
|
333
351
|
.ui-report__finding,
|
|
334
352
|
.ui-report__evidence,
|
|
335
|
-
.ui-report__figure
|
|
336
|
-
.ui-chart {
|
|
353
|
+
.ui-report__figure {
|
|
337
354
|
break-inside: avoid;
|
|
338
355
|
}
|
|
339
356
|
|
package/css/sidenote.css
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
sidenote — opt-in Tufte-style margin notes.
|
|
3
|
+
|
|
4
|
+
A numbered `ui-sidenote` and an unnumbered `ui-marginnote` for evidence,
|
|
5
|
+
caveats, and provenance asides that belong beside the text, not in it. Wide
|
|
6
|
+
viewports float the note into the inline-end margin; narrow viewports collapse
|
|
7
|
+
it to an indented inline block. CSS counters number the sidenotes. Not
|
|
8
|
+
imported by core.css.
|
|
9
|
+
|
|
10
|
+
Boundary / wiring: the HOST owns where numbering restarts — set
|
|
11
|
+
`counter-reset: ui-sidenote` on the article (or a section) — and reserves the
|
|
12
|
+
margin gutter by giving that container
|
|
13
|
+
`padding-inline-end: calc(var(--sidenote-width) + var(--sidenote-gap))` at the
|
|
14
|
+
same breakpoint. Place each note in the DOM right after its `.ui-sidenote__ref`.
|
|
15
|
+
========================================================================== */
|
|
16
|
+
|
|
17
|
+
.ui-sidenote,
|
|
18
|
+
.ui-marginnote {
|
|
19
|
+
--sidenote-width: 12rem;
|
|
20
|
+
--sidenote-gap: 2rem;
|
|
21
|
+
|
|
22
|
+
border-inline-start: 2px solid var(--line);
|
|
23
|
+
color: var(--text-dim);
|
|
24
|
+
display: block;
|
|
25
|
+
font-size: var(--text-2xs);
|
|
26
|
+
line-height: 1.5;
|
|
27
|
+
margin-block: var(--space-2xs);
|
|
28
|
+
padding-inline-start: var(--space-md);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* The inline superscript that anchors a numbered sidenote. Use --accent-text,
|
|
32
|
+
not raw --accent: this is readable text and must clear WCAG AA 4.5:1 even
|
|
33
|
+
after a one-knob re-brand to a paler --accent (raw --accent drops to ~1.5:1).
|
|
34
|
+
Same accent-as-text contract as .ui-eyebrow / .ui-link--cta. (audit C6.) */
|
|
35
|
+
.ui-sidenote__ref {
|
|
36
|
+
color: var(--accent-text);
|
|
37
|
+
counter-increment: ui-sidenote;
|
|
38
|
+
font-size: 0.75em;
|
|
39
|
+
vertical-align: super;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.ui-sidenote__ref::after {
|
|
43
|
+
content: counter(ui-sidenote);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* The note repeats its number (display only — the ref already incremented).
|
|
47
|
+
--accent-text for the same WCAG-AA reason as the ref above. (audit C6.) */
|
|
48
|
+
.ui-sidenote::before {
|
|
49
|
+
color: var(--accent-text);
|
|
50
|
+
content: counter(ui-sidenote) '. ';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* Wide viewports: float the note into the inline-end margin. The container must
|
|
54
|
+
reserve the gutter (see header). */
|
|
55
|
+
@media (min-width: 60rem) {
|
|
56
|
+
.ui-sidenote,
|
|
57
|
+
.ui-marginnote {
|
|
58
|
+
border-inline-start: 0;
|
|
59
|
+
clear: inline-end;
|
|
60
|
+
float: inline-end;
|
|
61
|
+
inline-size: var(--sidenote-width);
|
|
62
|
+
margin-block: 0;
|
|
63
|
+
margin-inline-end: calc(-1 * (var(--sidenote-width) + var(--sidenote-gap)));
|
|
64
|
+
padding-inline-start: 0;
|
|
65
|
+
text-align: start;
|
|
66
|
+
}
|
|
67
|
+
}
|
package/css/site.css
CHANGED
|
@@ -162,11 +162,11 @@
|
|
|
162
162
|
transform var(--duration-fast) var(--ease-spring);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
.ui-sitenav a[aria-current] {
|
|
165
|
+
.ui-sitenav a[aria-current]:not([aria-current='false']) {
|
|
166
166
|
color: var(--accent-text);
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
.ui-sitenav a[aria-current]::before {
|
|
169
|
+
.ui-sitenav a[aria-current]:not([aria-current='false'])::before {
|
|
170
170
|
opacity: 1;
|
|
171
171
|
transform: scale(1);
|
|
172
172
|
}
|
|
@@ -182,6 +182,13 @@
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
+
@media (pointer: coarse) {
|
|
186
|
+
.ui-sitenav a {
|
|
187
|
+
min-block-size: 2.9rem;
|
|
188
|
+
padding-inline: 0.9rem;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
185
192
|
/* --- Mobile menu — native <details>, no JS required --- */
|
|
186
193
|
|
|
187
194
|
.ui-sitemenu {
|
|
@@ -247,6 +254,13 @@
|
|
|
247
254
|
}
|
|
248
255
|
}
|
|
249
256
|
|
|
257
|
+
@media (pointer: coarse) {
|
|
258
|
+
.ui-sitemenu > summary {
|
|
259
|
+
min-block-size: 2.9rem;
|
|
260
|
+
padding-inline: 0.9rem;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
250
264
|
/* --- Footer --- */
|
|
251
265
|
|
|
252
266
|
.ui-sitefooter {
|
package/css/sources.css
CHANGED
|
@@ -19,6 +19,37 @@
|
|
|
19
19
|
--src-tone: var(--text-dim);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/* Standalone trust pill — wears a `.ui-src--*` tone on its own, for a bare
|
|
23
|
+
"verified" / "stale" label outside a citation or source card (the tone setters
|
|
24
|
+
below only paint a `--src-tone` custom property, so without this host a lone
|
|
25
|
+
`.ui-src--verified` validates against classes.json yet renders nothing). Tone
|
|
26
|
+
is a leading dot + a tinted border AND the author's written label, never colour
|
|
27
|
+
alone (WCAG 1.4.1). Declared before the `--*` setters so their tone wins. */
|
|
28
|
+
.ui-src {
|
|
29
|
+
--src-tone: var(--text-dim);
|
|
30
|
+
|
|
31
|
+
align-items: center;
|
|
32
|
+
background: var(--panel-soft);
|
|
33
|
+
border: 1px solid color-mix(in srgb, var(--src-tone) 45%, var(--line));
|
|
34
|
+
border-radius: var(--radius-pill);
|
|
35
|
+
color: var(--text-soft);
|
|
36
|
+
display: inline-flex;
|
|
37
|
+
font-size: var(--text-2xs);
|
|
38
|
+
gap: 0.35rem;
|
|
39
|
+
padding: 0.08rem 0.55rem;
|
|
40
|
+
vertical-align: baseline;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.ui-src::before {
|
|
44
|
+
background: var(--src-tone);
|
|
45
|
+
border-radius: 50%;
|
|
46
|
+
block-size: 0.45rem;
|
|
47
|
+
content: '';
|
|
48
|
+
flex: none;
|
|
49
|
+
inline-size: 0.45rem;
|
|
50
|
+
print-color-adjust: exact;
|
|
51
|
+
}
|
|
52
|
+
|
|
22
53
|
.ui-src--verified {
|
|
23
54
|
--src-tone: var(--success);
|
|
24
55
|
}
|
|
@@ -169,7 +200,8 @@
|
|
|
169
200
|
1.4.1). Keep the marks visible as CanvasText rather than letting them vanish. */
|
|
170
201
|
@media (forced-colors: active) {
|
|
171
202
|
.ui-citation--chip::before,
|
|
172
|
-
.ui-provenance__item::before
|
|
203
|
+
.ui-provenance__item::before,
|
|
204
|
+
.ui-src::before {
|
|
173
205
|
background: CanvasText;
|
|
174
206
|
}
|
|
175
207
|
|
|
@@ -177,3 +209,13 @@
|
|
|
177
209
|
border-inline-start-color: CanvasText;
|
|
178
210
|
}
|
|
179
211
|
}
|
|
212
|
+
|
|
213
|
+
/* Print: an inline citation marker points into the references list, so never
|
|
214
|
+
expand its href inline. base.css expands `.ui-prose a[href^="http"]` with a
|
|
215
|
+
trailing "(url)"; on a superscript marker that dumps a full URL mid-sentence.
|
|
216
|
+
!important + print-scoped because base's rule is more specific. */
|
|
217
|
+
@media print {
|
|
218
|
+
.ui-citation[href]::after {
|
|
219
|
+
content: none !important;
|
|
220
|
+
}
|
|
221
|
+
}
|