@ponchia/ui 0.4.1 → 0.6.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/CHANGELOG.md +552 -8
- package/MIGRATIONS.json +106 -0
- package/README.md +34 -8
- package/annotations/index.d.ts +402 -0
- package/annotations/index.d.ts.map +1 -0
- package/annotations/index.js +792 -0
- package/behaviors/carousel.js +198 -0
- package/behaviors/combobox.js +226 -0
- package/behaviors/command.js +190 -0
- package/behaviors/connectors.js +95 -0
- package/behaviors/crosshair.js +57 -0
- package/behaviors/dialog.js +74 -0
- package/behaviors/disclosure.js +26 -0
- package/behaviors/dismissible.js +25 -0
- package/behaviors/forms.js +186 -0
- package/behaviors/glyph.js +108 -0
- package/behaviors/index.d.ts +79 -0
- package/behaviors/index.js +18 -1409
- package/behaviors/internal.js +97 -0
- package/behaviors/legend.js +67 -0
- package/behaviors/menu.js +47 -0
- package/behaviors/popover.js +179 -0
- package/behaviors/spotlight.js +52 -0
- package/behaviors/table.js +136 -0
- package/behaviors/tabs.js +103 -0
- package/behaviors/theme.js +84 -0
- package/behaviors/toast.js +164 -0
- package/classes/classes.json +1857 -0
- package/classes/index.d.ts +306 -13
- package/classes/index.js +339 -12
- package/classes/vscode.css-custom-data.json +12 -0
- package/connectors/index.d.ts +191 -0
- package/connectors/index.d.ts.map +1 -0
- package/connectors/index.js +275 -0
- package/css/analytical.css +21 -0
- package/css/annotations.css +292 -0
- package/css/app.css +43 -13
- package/css/base.css +15 -10
- package/css/command.css +97 -0
- package/css/connectors.css +110 -0
- package/css/content.css +7 -1
- package/css/crosshair.css +100 -0
- package/css/dataviz.css +5 -1
- package/css/disclosure.css +38 -6
- package/css/dots.css +57 -0
- package/css/feedback.css +111 -2
- package/css/fonts.css +11 -7
- package/css/forms.css +42 -1
- package/css/generated.css +117 -0
- package/css/legend.css +272 -0
- package/css/marks.css +174 -0
- package/css/motion.css +24 -44
- package/css/navigation.css +7 -0
- package/css/overlay.css +31 -1
- package/css/primitives.css +109 -5
- package/css/report.css +39 -81
- package/css/selection.css +46 -0
- package/css/site.css +16 -2
- package/css/sources.css +221 -0
- package/css/spotlight.css +104 -0
- package/css/state.css +121 -0
- package/css/tokens.css +60 -37
- package/css/workbench.css +83 -0
- package/dist/bronto.css +1 -1
- package/dist/css/analytical.css +1 -0
- package/dist/css/annotations.css +1 -0
- package/dist/css/app.css +1 -1
- package/dist/css/base.css +1 -1
- package/dist/css/command.css +1 -0
- package/dist/css/connectors.css +1 -0
- package/dist/css/content.css +1 -1
- package/dist/css/crosshair.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/fonts.css +1 -1
- package/dist/css/forms.css +1 -1
- package/dist/css/generated.css +1 -0
- package/dist/css/legend.css +1 -0
- package/dist/css/marks.css +1 -0
- 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/selection.css +1 -0
- package/dist/css/site.css +1 -1
- package/dist/css/sources.css +1 -0
- package/dist/css/spotlight.css +1 -0
- package/dist/css/state.css +1 -0
- package/dist/css/tokens.css +1 -1
- package/dist/css/workbench.css +1 -0
- package/docs/adr/0003-theme-model.md +7 -4
- package/docs/annotations.md +425 -0
- package/docs/architecture.md +246 -0
- package/docs/command.md +95 -0
- package/docs/connectors.md +91 -0
- package/docs/contrast.md +116 -92
- package/docs/crosshair.md +63 -0
- package/docs/d2.md +195 -0
- package/docs/generated.md +91 -0
- package/docs/legends.md +184 -0
- package/docs/marks.md +93 -0
- package/docs/mermaid.md +152 -0
- package/docs/reference.md +385 -23
- package/docs/reporting.md +436 -63
- package/docs/selection.md +40 -0
- package/docs/sources.md +137 -0
- package/docs/spotlight.md +78 -0
- package/docs/stability.md +24 -2
- package/docs/state.md +85 -0
- package/docs/usage.md +123 -4
- package/docs/vega.md +225 -0
- package/docs/workbench.md +78 -0
- package/fonts/doto-400.woff2 +0 -0
- package/fonts/doto-500.woff2 +0 -0
- package/fonts/doto-600.woff2 +0 -0
- package/fonts/doto-700.woff2 +0 -0
- package/fonts/doto-800.woff2 +0 -0
- package/fonts/doto-900.woff2 +0 -0
- package/glyphs/glyphs.js +6 -4
- package/llms.txt +362 -14
- package/package.json +115 -12
- package/qwik/index.d.ts +42 -54
- package/qwik/index.d.ts.map +1 -0
- package/qwik/index.js +75 -3
- package/react/index.d.ts +39 -56
- package/react/index.d.ts.map +1 -0
- package/react/index.js +67 -3
- package/solid/index.d.ts +64 -56
- package/solid/index.d.ts.map +1 -0
- package/solid/index.js +70 -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 +23 -5
- 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/fonts/doto-400.ttf +0 -0
- package/fonts/doto-500.ttf +0 -0
- package/fonts/doto-600.ttf +0 -0
- package/fonts/doto-700.ttf +0 -0
- package/fonts/doto-800.ttf +0 -0
- package/fonts/doto-900.ttf +0 -0
package/css/marks.css
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
marks — opt-in evidence/emphasis marks for running text.
|
|
3
|
+
|
|
4
|
+
The prose counterpart to the SVG annotations layer: annotations call out a
|
|
5
|
+
figure, marks call out a sentence. Sober, report-grade highlights for docs,
|
|
6
|
+
audits, and generated (LLM) reports — not a hand-drawn Rough-Notation look.
|
|
7
|
+
Not imported by core.css.
|
|
8
|
+
|
|
9
|
+
`.ui-mark` is an inline highlight (put it on a `<mark>`); `.ui-bracket-note`
|
|
10
|
+
brackets a whole passage. Monochrome by default — the rationed accent is
|
|
11
|
+
opt-in via `--accent`; status tones are only for status-bearing emphasis.
|
|
12
|
+
========================================================================== */
|
|
13
|
+
|
|
14
|
+
.ui-mark {
|
|
15
|
+
/* No base `--mark-color`: each draw style supplies its own fallback default
|
|
16
|
+
(highlight/box keep the subtle `--line-strong`; the full-opacity
|
|
17
|
+
`--underline`/`--strike` decorations default to the darker `--text-dim` so
|
|
18
|
+
they read on a light surface — C33). A tone modifier SETS `--mark-color`,
|
|
19
|
+
so it still wins everywhere the fallback would otherwise apply. */
|
|
20
|
+
|
|
21
|
+
/* A bare `<mark>` carries the UA `background-color: yellow`; the translucent
|
|
22
|
+
highlight gradient sits on top of it, so without this reset the UA yellow
|
|
23
|
+
bleeds through (an author declaration always beats the UA origin). */
|
|
24
|
+
background-color: transparent;
|
|
25
|
+
background-image: linear-gradient(
|
|
26
|
+
90deg,
|
|
27
|
+
color-mix(in srgb, var(--mark-color, var(--line-strong)) 30%, transparent),
|
|
28
|
+
color-mix(in srgb, var(--mark-color, var(--line-strong)) 30%, transparent)
|
|
29
|
+
);
|
|
30
|
+
background-repeat: no-repeat;
|
|
31
|
+
background-size: 100% 100%;
|
|
32
|
+
border-radius: 0.12em;
|
|
33
|
+
box-decoration-break: clone;
|
|
34
|
+
color: inherit;
|
|
35
|
+
padding-block: 0.05em;
|
|
36
|
+
padding-inline: 0.18em;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* Tones set the mark colour. Default is neutral ink; `--accent` is the
|
|
40
|
+
rationed accent; status tones only for status-bearing emphasis. */
|
|
41
|
+
.ui-mark--accent {
|
|
42
|
+
--mark-color: var(--accent);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.ui-mark--success {
|
|
46
|
+
--mark-color: var(--success);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.ui-mark--warning {
|
|
50
|
+
--mark-color: var(--warning);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.ui-mark--danger {
|
|
54
|
+
--mark-color: var(--danger);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.ui-mark--info {
|
|
58
|
+
--mark-color: var(--info);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.ui-mark--muted {
|
|
62
|
+
--mark-color: var(--text-dim);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* Styles change how the mark is drawn (no highlight fill). They wrap across
|
|
66
|
+
lines natively (text-decoration) or with the cloned box (border). */
|
|
67
|
+
.ui-mark--underline {
|
|
68
|
+
background: none;
|
|
69
|
+
padding: 0;
|
|
70
|
+
text-decoration-color: var(--mark-color, var(--text-dim));
|
|
71
|
+
text-decoration-line: underline;
|
|
72
|
+
text-decoration-thickness: 0.12em;
|
|
73
|
+
text-underline-offset: 0.18em;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.ui-mark--box {
|
|
77
|
+
background: none;
|
|
78
|
+
border: 1px solid var(--mark-color, var(--line-strong));
|
|
79
|
+
border-radius: var(--radius-sm);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.ui-mark--strike {
|
|
83
|
+
background: none;
|
|
84
|
+
padding: 0;
|
|
85
|
+
text-decoration-color: var(--mark-color, var(--text-dim));
|
|
86
|
+
text-decoration-line: line-through;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* Draw-on highlight sweep. Only the highlight fill animates, and only when
|
|
90
|
+
motion is welcome — reduced-motion keeps the resting full highlight. */
|
|
91
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
92
|
+
/* The sweep animates `background-size`, i.e. the highlight FILL — so it is
|
|
93
|
+
inert on the no-fill styles (underline/box/strike). Scope it out rather
|
|
94
|
+
than let `--draw` look applied but do nothing. (content review C14.) */
|
|
95
|
+
.ui-mark--draw:not(.ui-mark--underline, .ui-mark--box, .ui-mark--strike) {
|
|
96
|
+
animation: ui-mark-draw 0.6s var(--ease, ease) both;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@keyframes ui-mark-draw {
|
|
101
|
+
from {
|
|
102
|
+
background-size: 0% 100%;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
to {
|
|
106
|
+
background-size: 100% 100%;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* A passage bracket: a tick down the inline-start with an optional label.
|
|
111
|
+
The prose analogue of `ui-annotation--bracket`. */
|
|
112
|
+
.ui-bracket-note {
|
|
113
|
+
--mark-color: var(--line-strong);
|
|
114
|
+
|
|
115
|
+
border-inline-start: 2px solid var(--mark-color);
|
|
116
|
+
display: block;
|
|
117
|
+
padding-inline-start: var(--space-md);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.ui-bracket-note__label {
|
|
121
|
+
color: var(--mark-color);
|
|
122
|
+
display: block;
|
|
123
|
+
font-family: var(--mono);
|
|
124
|
+
font-size: var(--text-2xs);
|
|
125
|
+
letter-spacing: 0;
|
|
126
|
+
margin-block-end: var(--space-2xs);
|
|
127
|
+
text-transform: uppercase;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.ui-bracket-note--accent {
|
|
131
|
+
--mark-color: var(--accent);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.ui-bracket-note--success {
|
|
135
|
+
--mark-color: var(--success);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.ui-bracket-note--warning {
|
|
139
|
+
--mark-color: var(--warning);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.ui-bracket-note--danger {
|
|
143
|
+
--mark-color: var(--danger);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.ui-bracket-note--info {
|
|
147
|
+
--mark-color: var(--info);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/* Forced colours: only the highlight `background` is dropped, so add an
|
|
151
|
+
underline to the plain highlight mark to keep it visible. The styled marks
|
|
152
|
+
already carry a surviving channel — `--underline`/`--strike` use
|
|
153
|
+
text-decoration and `--box` a border — so they're excluded (otherwise the
|
|
154
|
+
underline would overwrite `--strike`'s line-through and lose its meaning). */
|
|
155
|
+
@media (forced-colors: active) {
|
|
156
|
+
.ui-mark:not(.ui-mark--underline, .ui-mark--box, .ui-mark--strike) {
|
|
157
|
+
text-decoration-line: underline;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/* Print: the highlight is a painted background, so force it through the print
|
|
162
|
+
"economy" default that would otherwise drop it. Settle the draw sweep to its
|
|
163
|
+
resting full highlight in case it is mid-animation when the page is printed. */
|
|
164
|
+
@media print {
|
|
165
|
+
.ui-mark {
|
|
166
|
+
-webkit-print-color-adjust: exact;
|
|
167
|
+
background-size: 100% 100%;
|
|
168
|
+
print-color-adjust: exact;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.ui-mark--draw {
|
|
172
|
+
animation: none;
|
|
173
|
+
}
|
|
174
|
+
}
|
package/css/motion.css
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/* ==========================================================================
|
|
2
2
|
motion — keyframes + animation utilities
|
|
3
3
|
Restrained, dot-flavoured. Everything collapses under reduced-motion.
|
|
4
|
-
Keyframes from the legacy responsive layer live here so consumers that
|
|
5
|
-
import only core.css keep their existing animations.
|
|
6
4
|
========================================================================== */
|
|
7
5
|
|
|
8
6
|
@keyframes pulseDot {
|
|
@@ -18,45 +16,6 @@
|
|
|
18
16
|
}
|
|
19
17
|
}
|
|
20
18
|
|
|
21
|
-
@keyframes scan {
|
|
22
|
-
0% {
|
|
23
|
-
transform: translateY(-120%);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
100% {
|
|
27
|
-
transform: translateY(320%);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
@keyframes growBar {
|
|
32
|
-
to {
|
|
33
|
-
transform: scaleX(1);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
@keyframes drawLine {
|
|
38
|
-
from {
|
|
39
|
-
opacity: 0;
|
|
40
|
-
stroke-dasharray: 0 999;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
to {
|
|
44
|
-
opacity: 1;
|
|
45
|
-
stroke-dasharray: 999 0;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
@keyframes pulseNode {
|
|
50
|
-
0%,
|
|
51
|
-
100% {
|
|
52
|
-
transform: scale(1);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
50% {
|
|
56
|
-
transform: scale(1.08);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
19
|
@keyframes pulseRing {
|
|
61
20
|
0% {
|
|
62
21
|
opacity: 0.7;
|
|
@@ -233,9 +192,13 @@
|
|
|
233
192
|
animation-delay: 360ms;
|
|
234
193
|
}
|
|
235
194
|
|
|
236
|
-
/* Reveal-on-scroll: add .ui-reveal, toggle .is-visible
|
|
237
|
-
|
|
238
|
-
|
|
195
|
+
/* Reveal-on-scroll: add .ui-reveal, then toggle .is-visible (e.g. from an
|
|
196
|
+
IntersectionObserver you own) to play it in. For a ZERO-JS reveal, use
|
|
197
|
+
`.ui-scroll-reveal` (scroll-driven, CSS-only) instead — that is the path for
|
|
198
|
+
an LLM-authored or no-build report. The hidden initial state below is gated
|
|
199
|
+
on `scripting: enabled`, so with scripting OFF the content is fully visible
|
|
200
|
+
and never silently hidden behind a script that will never run. */
|
|
201
|
+
@media (prefers-reduced-motion: no-preference) and (scripting: enabled) {
|
|
239
202
|
.ui-reveal {
|
|
240
203
|
opacity: 0;
|
|
241
204
|
transform: translateY(14px);
|
|
@@ -365,14 +328,31 @@
|
|
|
365
328
|
scroll-behavior: auto;
|
|
366
329
|
}
|
|
367
330
|
|
|
331
|
+
/* !important is required: inside @layer bronto, layered rules lose to
|
|
332
|
+
unlayered author rules at equal specificity — only a layered !important
|
|
333
|
+
stays authoritative over unlayered declarations (CSS cascade §6.2). */
|
|
368
334
|
*,
|
|
369
335
|
*::before,
|
|
370
336
|
*::after {
|
|
371
337
|
animation-duration: 0.01ms !important;
|
|
372
338
|
animation-iteration-count: 1 !important;
|
|
339
|
+
|
|
340
|
+
/* Zero the delay too: `.ui-stagger` children animate `uiRise` with
|
|
341
|
+
`fill-mode: both`, so a non-zero `animation-delay` holds them at the
|
|
342
|
+
`opacity: 0` from-state for the full delay and then pops them in — the
|
|
343
|
+
exact late flash a reduced-motion user asked to avoid (C4). */
|
|
344
|
+
animation-delay: 0s !important;
|
|
373
345
|
transition-duration: 0.01ms !important;
|
|
374
346
|
}
|
|
375
347
|
|
|
348
|
+
/* Freeze the shimmer gradient mid-sweep would expose a diagonal band.
|
|
349
|
+
Flatten the skeleton to its base panel colour instead. */
|
|
350
|
+
.ui-skeleton {
|
|
351
|
+
animation: none;
|
|
352
|
+
background: var(--panel-soft);
|
|
353
|
+
background-size: auto;
|
|
354
|
+
}
|
|
355
|
+
|
|
376
356
|
.ui-reveal {
|
|
377
357
|
opacity: 1 !important;
|
|
378
358
|
transform: none !important;
|
package/css/navigation.css
CHANGED
package/css/overlay.css
CHANGED
|
@@ -249,7 +249,7 @@ dialog.ui-modal[open]::backdrop {
|
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
.ui-menu__item::before {
|
|
252
|
-
background:
|
|
252
|
+
background: currentcolor;
|
|
253
253
|
border-radius: 50%;
|
|
254
254
|
content: '';
|
|
255
255
|
block-size: 0.3rem;
|
|
@@ -275,6 +275,15 @@ dialog.ui-modal[open]::backdrop {
|
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
+
.ui-menu__item:focus-visible {
|
|
279
|
+
background: var(--bg-accent);
|
|
280
|
+
color: var(--text);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.ui-menu__item:focus-visible::before {
|
|
284
|
+
opacity: 1;
|
|
285
|
+
}
|
|
286
|
+
|
|
278
287
|
/* --- Combobox: an input with a filtered listbox popup (APG pattern,
|
|
279
288
|
wired by initCombobox). Reuses the menu surface tokens. --- */
|
|
280
289
|
.ui-combobox {
|
|
@@ -363,6 +372,14 @@ dialog.ui-modal[open]::backdrop {
|
|
|
363
372
|
inset-inline: 0;
|
|
364
373
|
min-inline-size: 0;
|
|
365
374
|
}
|
|
375
|
+
|
|
376
|
+
/* Let the combobox shed its 14rem floor and span the viewport so the input
|
|
377
|
+
(and its full-width listbox) can't overflow a narrow screen. */
|
|
378
|
+
.ui-combobox {
|
|
379
|
+
display: block;
|
|
380
|
+
inline-size: 100%;
|
|
381
|
+
min-inline-size: 0;
|
|
382
|
+
}
|
|
366
383
|
}
|
|
367
384
|
|
|
368
385
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -376,3 +393,16 @@ dialog.ui-modal[open]::backdrop {
|
|
|
376
393
|
transition: none;
|
|
377
394
|
}
|
|
378
395
|
}
|
|
396
|
+
|
|
397
|
+
/* Forced-colors drops both `backdrop-filter: blur()` and the `color-mix()`
|
|
398
|
+
scrim, so the dialog/lightbox would float over an undimmed page with no
|
|
399
|
+
separation. Re-assert a translucent scrim with `forced-color-adjust: none`
|
|
400
|
+
so the layering reads in High Contrast, matching the meter/dot precedent
|
|
401
|
+
(C28). */
|
|
402
|
+
@media (forced-colors: active) {
|
|
403
|
+
.ui-modal::backdrop,
|
|
404
|
+
.ui-lightbox::backdrop {
|
|
405
|
+
background: color-mix(in srgb, #000 50%, transparent);
|
|
406
|
+
forced-color-adjust: none;
|
|
407
|
+
}
|
|
408
|
+
}
|
package/css/primitives.css
CHANGED
|
@@ -87,7 +87,11 @@
|
|
|
87
87
|
(island-safe). Inert until applied, so existing layouts/baselines
|
|
88
88
|
are unaffected. */
|
|
89
89
|
.ui-cq {
|
|
90
|
-
container
|
|
90
|
+
/* The container-name is fixed: the `@container bronto (…)` collapse queries
|
|
91
|
+
below hardcode `bronto`. There is no `--cq-name` knob — the name is not
|
|
92
|
+
author-tunable, and an author-set `--cq-name` is simply ignored (nothing
|
|
93
|
+
reads it). Name a different container yourself if you need a custom scope. */
|
|
94
|
+
container: bronto / inline-size;
|
|
91
95
|
}
|
|
92
96
|
|
|
93
97
|
@container bronto (max-width: 34rem) {
|
|
@@ -196,8 +200,9 @@
|
|
|
196
200
|
font-family: var(--display);
|
|
197
201
|
font-size: 1.9rem;
|
|
198
202
|
font-variant-numeric: tabular-nums;
|
|
199
|
-
|
|
200
|
-
|
|
203
|
+
font-weight: var(--display-weight-strong);
|
|
204
|
+
letter-spacing: 0.02em;
|
|
205
|
+
line-height: 1.05;
|
|
201
206
|
}
|
|
202
207
|
|
|
203
208
|
.ui-stat__delta,
|
|
@@ -216,6 +221,22 @@
|
|
|
216
221
|
color: var(--danger);
|
|
217
222
|
}
|
|
218
223
|
|
|
224
|
+
/* A direction arrow is the non-colour channel — colour alone (success/danger)
|
|
225
|
+
fails WCAG 1.4.1, so the tile carries the same ▲/▼ glyph as `.ui-delta`
|
|
226
|
+
(C13). Marked aria-hidden-equivalent by being generated content; the sign is
|
|
227
|
+
still in the author's text ("+12%"). */
|
|
228
|
+
.ui-stat__delta.is-pos::before,
|
|
229
|
+
.ui-app-metric__delta.is-pos::before {
|
|
230
|
+
content: '▲ ';
|
|
231
|
+
font-size: 0.85em;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.ui-stat__delta.is-neg::before,
|
|
235
|
+
.ui-app-metric__delta.is-neg::before {
|
|
236
|
+
content: '▼ ';
|
|
237
|
+
font-size: 0.85em;
|
|
238
|
+
}
|
|
239
|
+
|
|
219
240
|
/* --- Numeric value vocabulary ---
|
|
220
241
|
The same tabular/aligned/tone intent the table has shipped since
|
|
221
242
|
0.1.0, but freed from `.ui-table` so cards, stats and inline figures
|
|
@@ -238,6 +259,58 @@
|
|
|
238
259
|
color: var(--text-dim);
|
|
239
260
|
}
|
|
240
261
|
|
|
262
|
+
/* --- Trend delta ---
|
|
263
|
+
A standalone change indicator: a direction arrow (the non-colour channel,
|
|
264
|
+
WCAG 1.4.1) plus the figure, tabular so a column of deltas aligns.
|
|
265
|
+
Direction sets the glyph AND the conventional tone (up = positive,
|
|
266
|
+
down = negative). When "up" is the bad direction (latency, error rate,
|
|
267
|
+
cost, churn), add `ui-delta--invert` to swap only the tone — the arrow
|
|
268
|
+
still reports real direction. Pair with words; the arrow is visual, not a
|
|
269
|
+
substitute for stating the change. */
|
|
270
|
+
.ui-delta {
|
|
271
|
+
align-items: baseline;
|
|
272
|
+
color: var(--text-soft);
|
|
273
|
+
display: inline-flex;
|
|
274
|
+
font-variant-numeric: tabular-nums;
|
|
275
|
+
gap: 0.2em;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.ui-delta::before {
|
|
279
|
+
font-size: 0.85em;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.ui-delta--up {
|
|
283
|
+
color: var(--success);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.ui-delta--up::before {
|
|
287
|
+
content: '▲';
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.ui-delta--down {
|
|
291
|
+
color: var(--danger);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.ui-delta--down::before {
|
|
295
|
+
content: '▼';
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.ui-delta--flat {
|
|
299
|
+
color: var(--text-dim);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.ui-delta--flat::before {
|
|
303
|
+
content: '—';
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.ui-delta--invert.ui-delta--up {
|
|
307
|
+
color: var(--danger);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.ui-delta--invert.ui-delta--down {
|
|
311
|
+
color: var(--success);
|
|
312
|
+
}
|
|
313
|
+
|
|
241
314
|
/* --- Eyebrow / section label — dot-matrix face --- */
|
|
242
315
|
|
|
243
316
|
.ui-eyebrow {
|
|
@@ -338,6 +411,15 @@
|
|
|
338
411
|
opacity: 0.45;
|
|
339
412
|
}
|
|
340
413
|
|
|
414
|
+
/* aria-disabled keeps the element in the a11y tree but the browser does NOT
|
|
415
|
+
block activation (a real <a class="ui-button" aria-disabled> still navigates,
|
|
416
|
+
a <button> still fires). Looking dead while staying live is the defect — kill
|
|
417
|
+
pointer activation. (a11y review C3; native :disabled already inert.) */
|
|
418
|
+
.ui-button[aria-disabled='true'],
|
|
419
|
+
.ui-link[aria-disabled='true'] {
|
|
420
|
+
pointer-events: none;
|
|
421
|
+
}
|
|
422
|
+
|
|
341
423
|
.ui-button:active {
|
|
342
424
|
transform: translateY(1px);
|
|
343
425
|
}
|
|
@@ -401,8 +483,8 @@
|
|
|
401
483
|
|
|
402
484
|
.ui-link--arrow::after,
|
|
403
485
|
.ui-link--cta::after {
|
|
404
|
-
border-inline-end: 1px solid
|
|
405
|
-
border-block-start: 1px solid
|
|
486
|
+
border-inline-end: 1px solid currentcolor;
|
|
487
|
+
border-block-start: 1px solid currentcolor;
|
|
406
488
|
content: '';
|
|
407
489
|
block-size: 0.42rem;
|
|
408
490
|
transform: rotate(45deg);
|
|
@@ -459,6 +541,10 @@
|
|
|
459
541
|
(the soft tint can't carry 4.5:1 small-bold tone-on-tone — WCAG). */
|
|
460
542
|
.ui-badge--accent {
|
|
461
543
|
background: var(--accent-soft);
|
|
544
|
+
|
|
545
|
+
/* Accent mixes 45% (vs 40% for the status tones below) on purpose: the brand
|
|
546
|
+
hue is lower-chroma here than the status hues, so it needs a touch more to
|
|
547
|
+
read at the same border weight. Intentional, not a copy-paste slip. (Q15.) */
|
|
462
548
|
border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
|
|
463
549
|
}
|
|
464
550
|
|
|
@@ -649,6 +735,24 @@
|
|
|
649
735
|
padding: 0.18rem 0.4rem;
|
|
650
736
|
}
|
|
651
737
|
|
|
738
|
+
/* --- Shortcut hint — one or more .ui-kbd keys as a chord or sequence, with a
|
|
739
|
+
connective __sep ("+" for a chord, "then" for a sequence). The reusable
|
|
740
|
+
keyboard-hint primitive (menu items, buttons, tooltips, command lists). --- */
|
|
741
|
+
|
|
742
|
+
.ui-shortcut {
|
|
743
|
+
align-items: center;
|
|
744
|
+
display: inline-flex;
|
|
745
|
+
gap: 0.25rem;
|
|
746
|
+
vertical-align: middle;
|
|
747
|
+
white-space: nowrap;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
.ui-shortcut__sep {
|
|
751
|
+
color: var(--text-dim);
|
|
752
|
+
font-family: var(--mono);
|
|
753
|
+
font-size: var(--text-2xs);
|
|
754
|
+
}
|
|
755
|
+
|
|
652
756
|
/* --- Timeline — vertical event list on a hairline spine. Use an <ol>;
|
|
653
757
|
each <li> is a __item with an optional __time label. aria-current marks
|
|
654
758
|
the live/most-recent event (accent marker). --- */
|
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,82 +220,47 @@
|
|
|
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
|
-
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
.ui-chart__legend {
|
|
228
|
-
display: flex;
|
|
229
|
-
flex-wrap: wrap;
|
|
230
|
-
gap: var(--space-xs);
|
|
231
|
-
list-style: none;
|
|
232
|
-
margin: 0;
|
|
233
|
-
padding: 0;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
.ui-chart__legend > * {
|
|
237
|
-
align-items: center;
|
|
238
|
-
color: var(--text-soft);
|
|
239
|
-
display: inline-flex;
|
|
240
|
-
font-family: var(--mono);
|
|
241
|
-
font-size: var(--text-xs);
|
|
242
|
-
gap: 0.45rem;
|
|
232
|
+
gap: var(--space-md);
|
|
233
|
+
grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
|
|
243
234
|
}
|
|
244
235
|
|
|
245
|
-
.ui-
|
|
246
|
-
|
|
247
|
-
background-image: var(--chart-pattern, var(--chart-pattern-1, none));
|
|
248
|
-
background-size: var(--chart-pattern-size, 8px);
|
|
249
|
-
border: 1px solid var(--line-strong);
|
|
250
|
-
block-size: 0.8rem;
|
|
251
|
-
flex: 0 0 auto;
|
|
252
|
-
inline-size: 0.8rem;
|
|
236
|
+
.ui-compare--2up {
|
|
237
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
253
238
|
}
|
|
254
239
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
240
|
+
@media (max-width: 33rem) {
|
|
241
|
+
.ui-compare--2up {
|
|
242
|
+
grid-template-columns: 1fr;
|
|
243
|
+
}
|
|
258
244
|
}
|
|
259
245
|
|
|
260
|
-
.ui-
|
|
261
|
-
|
|
262
|
-
|
|
246
|
+
.ui-compare__col {
|
|
247
|
+
align-content: start;
|
|
263
248
|
display: grid;
|
|
264
|
-
gap: 0.35rem;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
.ui-chart__label {
|
|
268
|
-
align-items: center;
|
|
269
|
-
color: var(--text-soft);
|
|
270
|
-
display: flex;
|
|
271
|
-
font-family: var(--mono);
|
|
272
|
-
font-size: var(--text-xs);
|
|
273
249
|
gap: var(--space-sm);
|
|
274
|
-
justify-content: space-between;
|
|
275
250
|
}
|
|
276
251
|
|
|
277
|
-
.ui-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
.ui-chart__fill {
|
|
285
|
-
background: var(--chart-color, var(--chart-1, var(--accent)));
|
|
286
|
-
background-image: var(--chart-pattern, var(--chart-pattern-1, none));
|
|
287
|
-
background-size: var(--chart-pattern-size, 8px);
|
|
288
|
-
block-size: 100%;
|
|
289
|
-
inline-size: clamp(0%, var(--chart-value), 100%);
|
|
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;
|
|
290
258
|
}
|
|
291
259
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
260
|
+
/* A chart is NOT a bronto component — it needs scales + data binding, which the
|
|
261
|
+
analytical layer refuses to own. Theme Vega-Lite with `@ponchia/ui/vega`
|
|
262
|
+
(docs/vega.md), or hand-author a token-themed inline `<svg>`, and drop it in a
|
|
263
|
+
`.ui-report__figure` with a `.ui-report__caption` + a `.ui-legend` key. */
|
|
295
264
|
|
|
296
265
|
.ui-print-only {
|
|
297
266
|
display: none !important;
|
|
@@ -331,28 +300,17 @@
|
|
|
331
300
|
padding: 0;
|
|
332
301
|
}
|
|
333
302
|
|
|
334
|
-
/* Meaning-carrying chart fills must survive the print "economy" default
|
|
335
|
-
(which drops backgrounds) without relying on a `.ui-print-exact`
|
|
336
|
-
ancestor. The accent on `.ui-report__summary` is a border, so it already
|
|
337
|
-
prints. */
|
|
338
|
-
.ui-chart__fill,
|
|
339
|
-
.ui-chart__swatch {
|
|
340
|
-
-webkit-print-color-adjust: exact;
|
|
341
|
-
print-color-adjust: exact;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
303
|
.ui-report__cover {
|
|
345
304
|
min-block-size: auto;
|
|
346
305
|
}
|
|
347
306
|
|
|
348
307
|
.ui-report__cover,
|
|
349
|
-
.ui-
|
|
308
|
+
.ui-report__head,
|
|
350
309
|
.ui-report__section,
|
|
351
310
|
.ui-report__summary,
|
|
352
311
|
.ui-report__finding,
|
|
353
312
|
.ui-report__evidence,
|
|
354
|
-
.ui-report__figure
|
|
355
|
-
.ui-chart {
|
|
313
|
+
.ui-report__figure {
|
|
356
314
|
break-inside: avoid;
|
|
357
315
|
}
|
|
358
316
|
|