@ponchia/ui 0.3.1 → 0.3.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/README.md +6 -0
- package/classes/index.d.ts +45 -2
- package/classes/index.js +41 -6
- package/css/app.css +28 -66
- package/css/dots.css +24 -0
- package/css/overlay.css +10 -0
- package/css/primitives.css +193 -4
- package/css/site.css +14 -0
- package/dist/bronto.css +1 -1
- package/dist/css/app.css +1 -1
- package/dist/css/dots.css +1 -1
- package/dist/css/overlay.css +1 -1
- package/dist/css/primitives.css +1 -1
- package/dist/css/site.css +1 -1
- package/docs/reference.md +941 -0
- package/docs/theming.md +160 -0
- package/llms.txt +85 -0
- package/package.json +13 -4
- package/tokens/resolved.json +125 -0
package/README.md
CHANGED
|
@@ -25,6 +25,12 @@ flat hairline borders, restrained motion. CSS-first and framework-agnostic.
|
|
|
25
25
|
> }
|
|
26
26
|
> ```
|
|
27
27
|
|
|
28
|
+
> **For AI agents / LLMs.** The package ships `llms.txt` at its root —
|
|
29
|
+
> point a coding agent at `node_modules/@ponchia/ui/llms.txt` for a
|
|
30
|
+
> self-contained orientation. The full class catalog
|
|
31
|
+
> (`docs/reference.md`) and the token contract (`docs/theming.md`) also
|
|
32
|
+
> ship in the tarball, so an offline agent never has to guess at the API.
|
|
33
|
+
|
|
28
34
|
**[Live demo →](https://ponchia.github.io/bronto-ui/)** — the kitchen
|
|
29
35
|
sink (every component, light/dark, RTL, theming) deployed from `demo/`.
|
|
30
36
|
|
package/classes/index.d.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
/** @ponchia/ui — GENERATED from classes/index.js by scripts/gen-dts.mjs.
|
|
2
2
|
* Do not edit by hand; run `npm run dts:build`. Drift-checked in CI. */
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// Mirrors clsx's permissive input: `number`/`boolean` accepted so the
|
|
5
|
+
// idiomatic React `reactNode && 'cls'` guard (where the node may be 0 or
|
|
6
|
+
// '') type-checks. The runtime `cx` skips every falsy value regardless.
|
|
7
|
+
export type ClassValue =
|
|
8
|
+
| string
|
|
9
|
+
| number
|
|
10
|
+
| boolean
|
|
11
|
+
| null
|
|
12
|
+
| undefined
|
|
13
|
+
| ClassValue[];
|
|
5
14
|
|
|
6
15
|
/** The flat registry of every class @ponchia/ui defines (literal). */
|
|
7
16
|
export declare const cls: {
|
|
@@ -10,20 +19,35 @@ export declare const cls: {
|
|
|
10
19
|
readonly buttonSubtle: 'ui-button--subtle';
|
|
11
20
|
readonly buttonDanger: 'ui-button--danger';
|
|
12
21
|
readonly buttonIcon: 'ui-button--icon';
|
|
22
|
+
readonly buttonSm: 'ui-button--sm';
|
|
23
|
+
readonly buttonLg: 'ui-button--lg';
|
|
13
24
|
readonly card: 'ui-card';
|
|
14
25
|
readonly cardHead: 'ui-card__head';
|
|
15
26
|
readonly cardAccent: 'ui-card--accent';
|
|
16
27
|
readonly cardInteractive: 'ui-card--interactive';
|
|
28
|
+
readonly stat: 'ui-stat';
|
|
29
|
+
readonly statgrid: 'ui-statgrid';
|
|
30
|
+
readonly statLabel: 'ui-stat__label';
|
|
31
|
+
readonly statValue: 'ui-stat__value';
|
|
32
|
+
readonly statDelta: 'ui-stat__delta';
|
|
33
|
+
readonly num: 'ui-num';
|
|
34
|
+
readonly numPos: 'ui-num--pos';
|
|
35
|
+
readonly numNeg: 'ui-num--neg';
|
|
36
|
+
readonly numMuted: 'ui-num--muted';
|
|
17
37
|
readonly badge: 'ui-badge';
|
|
18
38
|
readonly badgeAccent: 'ui-badge--accent';
|
|
19
39
|
readonly badgeSuccess: 'ui-badge--success';
|
|
20
40
|
readonly badgeWarning: 'ui-badge--warning';
|
|
21
41
|
readonly badgeDanger: 'ui-badge--danger';
|
|
42
|
+
readonly badgeMuted: 'ui-badge--muted';
|
|
43
|
+
readonly badgeDot: 'ui-badge--dot';
|
|
22
44
|
readonly chip: 'ui-chip';
|
|
23
45
|
readonly chipAccent: 'ui-chip--accent';
|
|
24
46
|
readonly link: 'ui-link';
|
|
25
47
|
readonly linkArrow: 'ui-link--arrow';
|
|
48
|
+
readonly linkCta: 'ui-link--cta';
|
|
26
49
|
readonly keyValue: 'ui-key-value';
|
|
50
|
+
readonly emptyState: 'ui-empty-state';
|
|
27
51
|
readonly dot: 'ui-dot';
|
|
28
52
|
readonly dotAccent: 'ui-dot--accent';
|
|
29
53
|
readonly dotSuccess: 'ui-dot--success';
|
|
@@ -33,6 +57,10 @@ export declare const cls: {
|
|
|
33
57
|
readonly dotgrid: 'ui-dotgrid';
|
|
34
58
|
readonly dotgridAccent: 'ui-dotgrid--accent';
|
|
35
59
|
readonly dotgridDense: 'ui-dotgrid--dense';
|
|
60
|
+
readonly dotmatrix: 'ui-dotmatrix';
|
|
61
|
+
readonly dotmatrixCell: 'ui-dotmatrix__cell';
|
|
62
|
+
readonly dotmatrixCellHot: 'ui-dotmatrix__cell--hot';
|
|
63
|
+
readonly dotmatrixCellAccent: 'ui-dotmatrix__cell--accent';
|
|
36
64
|
readonly dotfield: 'ui-dotfield';
|
|
37
65
|
readonly dotrule: 'ui-dotrule';
|
|
38
66
|
readonly dotbar: 'ui-dotbar';
|
|
@@ -145,14 +173,17 @@ export declare const cls: {
|
|
|
145
173
|
readonly status: 'ui-status';
|
|
146
174
|
readonly eyebrow: 'ui-eyebrow';
|
|
147
175
|
readonly eyebrowMuted: 'ui-eyebrow--muted';
|
|
176
|
+
readonly eyebrowSm: 'ui-eyebrow--sm';
|
|
148
177
|
readonly prose: 'ui-prose';
|
|
149
178
|
readonly proseCompact: 'ui-prose--compact';
|
|
150
179
|
readonly quote: 'ui-quote';
|
|
151
180
|
readonly quoteCite: 'ui-quote__cite';
|
|
152
181
|
readonly container: 'ui-container';
|
|
153
182
|
readonly containerNarrow: 'ui-container--narrow';
|
|
183
|
+
readonly containerWide: 'ui-container--wide';
|
|
154
184
|
readonly skiplink: 'ui-skiplink';
|
|
155
185
|
readonly siteheader: 'ui-siteheader';
|
|
186
|
+
readonly siteheaderSticky: 'ui-siteheader--sticky';
|
|
156
187
|
readonly siteheaderBrand: 'ui-siteheader__brand';
|
|
157
188
|
readonly siteheaderActions: 'ui-siteheader__actions';
|
|
158
189
|
readonly sitenav: 'ui-sitenav';
|
|
@@ -186,6 +217,7 @@ export declare const cls: {
|
|
|
186
217
|
readonly appRailBrand: 'ui-app-rail__brand';
|
|
187
218
|
readonly appRailToggle: 'ui-app-rail__toggle';
|
|
188
219
|
readonly appRailFoot: 'ui-app-rail__foot';
|
|
220
|
+
readonly appRailAccount: 'ui-app-rail__account';
|
|
189
221
|
readonly appTopbar: 'ui-app-topbar';
|
|
190
222
|
readonly appTopbarTitle: 'ui-app-topbar__title';
|
|
191
223
|
readonly appToolbar: 'ui-app-toolbar';
|
|
@@ -216,19 +248,25 @@ export declare function cx(...parts: ClassValue[]): string;
|
|
|
216
248
|
export interface ButtonOpts {
|
|
217
249
|
variant?: 'ghost' | 'subtle' | 'danger';
|
|
218
250
|
icon?: boolean;
|
|
251
|
+
size?: 'sm' | 'lg';
|
|
219
252
|
}
|
|
220
253
|
export interface CardOpts {
|
|
221
254
|
accent?: boolean;
|
|
222
255
|
interactive?: boolean;
|
|
223
256
|
}
|
|
224
257
|
export interface BadgeOpts {
|
|
225
|
-
tone?: 'accent' | 'success' | 'warning' | 'danger';
|
|
258
|
+
tone?: 'accent' | 'success' | 'warning' | 'danger' | 'muted';
|
|
259
|
+
dot?: boolean;
|
|
260
|
+
}
|
|
261
|
+
export interface NumOpts {
|
|
262
|
+
tone?: 'pos' | 'neg' | 'muted';
|
|
226
263
|
}
|
|
227
264
|
export interface ChipOpts {
|
|
228
265
|
accent?: boolean;
|
|
229
266
|
}
|
|
230
267
|
export interface LinkOpts {
|
|
231
268
|
arrow?: boolean;
|
|
269
|
+
cta?: boolean;
|
|
232
270
|
}
|
|
233
271
|
export interface DotOpts {
|
|
234
272
|
tone?: 'accent' | 'success' | 'warning' | 'danger';
|
|
@@ -244,6 +282,7 @@ export interface TableOpts {
|
|
|
244
282
|
}
|
|
245
283
|
export interface EyebrowOpts {
|
|
246
284
|
muted?: boolean;
|
|
285
|
+
sm?: boolean;
|
|
247
286
|
}
|
|
248
287
|
export interface HintOpts {
|
|
249
288
|
error?: boolean;
|
|
@@ -272,6 +311,8 @@ export interface DotbarOpts {
|
|
|
272
311
|
}
|
|
273
312
|
export interface ModalOpts {
|
|
274
313
|
drawer?: boolean;
|
|
314
|
+
/** Controlled non-dialog usage — adds the is-open state (focus-trap is yours). */
|
|
315
|
+
open?: boolean;
|
|
275
316
|
}
|
|
276
317
|
export interface TabOpts {
|
|
277
318
|
active?: boolean;
|
|
@@ -284,6 +325,7 @@ export interface ProseOpts {
|
|
|
284
325
|
}
|
|
285
326
|
export interface ContainerOpts {
|
|
286
327
|
narrow?: boolean;
|
|
328
|
+
wide?: boolean;
|
|
287
329
|
}
|
|
288
330
|
export interface TagOpts {
|
|
289
331
|
accent?: boolean;
|
|
@@ -293,6 +335,7 @@ export interface Ui {
|
|
|
293
335
|
button(opts?: ButtonOpts): string;
|
|
294
336
|
card(opts?: CardOpts): string;
|
|
295
337
|
badge(opts?: BadgeOpts): string;
|
|
338
|
+
num(opts?: NumOpts): string;
|
|
296
339
|
chip(opts?: ChipOpts): string;
|
|
297
340
|
link(opts?: LinkOpts): string;
|
|
298
341
|
dot(opts?: DotOpts): string;
|
package/classes/index.js
CHANGED
|
@@ -23,20 +23,35 @@ export const cls = Object.freeze({
|
|
|
23
23
|
buttonSubtle: 'ui-button--subtle',
|
|
24
24
|
buttonDanger: 'ui-button--danger',
|
|
25
25
|
buttonIcon: 'ui-button--icon',
|
|
26
|
+
buttonSm: 'ui-button--sm',
|
|
27
|
+
buttonLg: 'ui-button--lg',
|
|
26
28
|
card: 'ui-card',
|
|
27
29
|
cardHead: 'ui-card__head',
|
|
28
30
|
cardAccent: 'ui-card--accent',
|
|
29
31
|
cardInteractive: 'ui-card--interactive',
|
|
32
|
+
stat: 'ui-stat',
|
|
33
|
+
statgrid: 'ui-statgrid',
|
|
34
|
+
statLabel: 'ui-stat__label',
|
|
35
|
+
statValue: 'ui-stat__value',
|
|
36
|
+
statDelta: 'ui-stat__delta',
|
|
37
|
+
num: 'ui-num',
|
|
38
|
+
numPos: 'ui-num--pos',
|
|
39
|
+
numNeg: 'ui-num--neg',
|
|
40
|
+
numMuted: 'ui-num--muted',
|
|
30
41
|
badge: 'ui-badge',
|
|
31
42
|
badgeAccent: 'ui-badge--accent',
|
|
32
43
|
badgeSuccess: 'ui-badge--success',
|
|
33
44
|
badgeWarning: 'ui-badge--warning',
|
|
34
45
|
badgeDanger: 'ui-badge--danger',
|
|
46
|
+
badgeMuted: 'ui-badge--muted',
|
|
47
|
+
badgeDot: 'ui-badge--dot',
|
|
35
48
|
chip: 'ui-chip',
|
|
36
49
|
chipAccent: 'ui-chip--accent',
|
|
37
50
|
link: 'ui-link',
|
|
38
51
|
linkArrow: 'ui-link--arrow',
|
|
52
|
+
linkCta: 'ui-link--cta',
|
|
39
53
|
keyValue: 'ui-key-value',
|
|
54
|
+
emptyState: 'ui-empty-state',
|
|
40
55
|
// dots
|
|
41
56
|
dot: 'ui-dot',
|
|
42
57
|
dotAccent: 'ui-dot--accent',
|
|
@@ -47,6 +62,10 @@ export const cls = Object.freeze({
|
|
|
47
62
|
dotgrid: 'ui-dotgrid',
|
|
48
63
|
dotgridAccent: 'ui-dotgrid--accent',
|
|
49
64
|
dotgridDense: 'ui-dotgrid--dense',
|
|
65
|
+
dotmatrix: 'ui-dotmatrix',
|
|
66
|
+
dotmatrixCell: 'ui-dotmatrix__cell',
|
|
67
|
+
dotmatrixCellHot: 'ui-dotmatrix__cell--hot',
|
|
68
|
+
dotmatrixCellAccent: 'ui-dotmatrix__cell--accent',
|
|
50
69
|
dotfield: 'ui-dotfield',
|
|
51
70
|
dotrule: 'ui-dotrule',
|
|
52
71
|
dotbar: 'ui-dotbar',
|
|
@@ -166,6 +185,7 @@ export const cls = Object.freeze({
|
|
|
166
185
|
// typography / utilities
|
|
167
186
|
eyebrow: 'ui-eyebrow',
|
|
168
187
|
eyebrowMuted: 'ui-eyebrow--muted',
|
|
188
|
+
eyebrowSm: 'ui-eyebrow--sm',
|
|
169
189
|
prose: 'ui-prose',
|
|
170
190
|
proseCompact: 'ui-prose--compact',
|
|
171
191
|
quote: 'ui-quote',
|
|
@@ -173,8 +193,10 @@ export const cls = Object.freeze({
|
|
|
173
193
|
// site shell
|
|
174
194
|
container: 'ui-container',
|
|
175
195
|
containerNarrow: 'ui-container--narrow',
|
|
196
|
+
containerWide: 'ui-container--wide',
|
|
176
197
|
skiplink: 'ui-skiplink',
|
|
177
198
|
siteheader: 'ui-siteheader',
|
|
199
|
+
siteheaderSticky: 'ui-siteheader--sticky',
|
|
178
200
|
siteheaderBrand: 'ui-siteheader__brand',
|
|
179
201
|
siteheaderActions: 'ui-siteheader__actions',
|
|
180
202
|
sitenav: 'ui-sitenav',
|
|
@@ -210,6 +232,7 @@ export const cls = Object.freeze({
|
|
|
210
232
|
appRailBrand: 'ui-app-rail__brand',
|
|
211
233
|
appRailToggle: 'ui-app-rail__toggle',
|
|
212
234
|
appRailFoot: 'ui-app-rail__foot',
|
|
235
|
+
appRailAccount: 'ui-app-rail__account',
|
|
213
236
|
appTopbar: 'ui-app-topbar',
|
|
214
237
|
appTopbarTitle: 'ui-app-topbar__title',
|
|
215
238
|
appToolbar: 'ui-app-toolbar',
|
|
@@ -245,26 +268,37 @@ export function cx(...parts) {
|
|
|
245
268
|
const j = (...p) => p.filter(Boolean).join(' ');
|
|
246
269
|
|
|
247
270
|
export const ui = {
|
|
248
|
-
button: ({ variant, icon } = {}) =>
|
|
271
|
+
button: ({ variant, icon, size } = {}) =>
|
|
249
272
|
j(
|
|
250
273
|
cls.button,
|
|
251
274
|
variant === 'ghost' && cls.buttonGhost,
|
|
252
275
|
variant === 'subtle' && cls.buttonSubtle,
|
|
253
276
|
variant === 'danger' && cls.buttonDanger,
|
|
254
277
|
icon && cls.buttonIcon,
|
|
278
|
+
size === 'sm' && cls.buttonSm,
|
|
279
|
+
size === 'lg' && cls.buttonLg,
|
|
255
280
|
),
|
|
256
281
|
card: ({ accent, interactive } = {}) =>
|
|
257
282
|
j(cls.card, accent && cls.cardAccent, interactive && cls.cardInteractive),
|
|
258
|
-
badge: ({ tone } = {}) =>
|
|
283
|
+
badge: ({ tone, dot } = {}) =>
|
|
259
284
|
j(
|
|
260
285
|
cls.badge,
|
|
261
286
|
tone === 'accent' && cls.badgeAccent,
|
|
262
287
|
tone === 'success' && cls.badgeSuccess,
|
|
263
288
|
tone === 'warning' && cls.badgeWarning,
|
|
264
289
|
tone === 'danger' && cls.badgeDanger,
|
|
290
|
+
tone === 'muted' && cls.badgeMuted,
|
|
291
|
+
dot && cls.badgeDot,
|
|
292
|
+
),
|
|
293
|
+
num: ({ tone } = {}) =>
|
|
294
|
+
j(
|
|
295
|
+
cls.num,
|
|
296
|
+
tone === 'pos' && cls.numPos,
|
|
297
|
+
tone === 'neg' && cls.numNeg,
|
|
298
|
+
tone === 'muted' && cls.numMuted,
|
|
265
299
|
),
|
|
266
300
|
chip: ({ accent } = {}) => j(cls.chip, accent && cls.chipAccent),
|
|
267
|
-
link: ({ arrow } = {}) => j(cls.link, arrow && cls.linkArrow),
|
|
301
|
+
link: ({ arrow, cta } = {}) => j(cls.link, arrow && cls.linkArrow, cta && cls.linkCta),
|
|
268
302
|
dot: ({ tone, live } = {}) =>
|
|
269
303
|
j(
|
|
270
304
|
cls.dot,
|
|
@@ -283,7 +317,7 @@ export const ui = {
|
|
|
283
317
|
density === 'comfortable' && cls.tableComfortable,
|
|
284
318
|
lined && cls.tableLined,
|
|
285
319
|
),
|
|
286
|
-
eyebrow: ({ muted } = {}) => j(cls.eyebrow, muted && cls.eyebrowMuted),
|
|
320
|
+
eyebrow: ({ muted, sm } = {}) => j(cls.eyebrow, muted && cls.eyebrowMuted, sm && cls.eyebrowSm),
|
|
287
321
|
hint: ({ error } = {}) => j(cls.hint, error && cls.hintError),
|
|
288
322
|
cluster: ({ between } = {}) => j(cls.cluster, between && cls.clusterBetween),
|
|
289
323
|
stagger: ({ auto } = {}) => j(cls.stagger, auto && cls.staggerAuto),
|
|
@@ -307,12 +341,13 @@ export const ui = {
|
|
|
307
341
|
dotspinner: ({ size } = {}) =>
|
|
308
342
|
j(cls.dotspinner, size === 'sm' && cls.dotspinnerSm, size === 'lg' && cls.dotspinnerLg),
|
|
309
343
|
dotbar: ({ indeterminate } = {}) => j(cls.dotbar, indeterminate && cls.dotbarIndeterminate),
|
|
310
|
-
modal: ({ drawer } = {}) => j(cls.modal, drawer && cls.modalDrawer),
|
|
344
|
+
modal: ({ drawer, open } = {}) => j(cls.modal, drawer && cls.modalDrawer, open && 'is-open'),
|
|
311
345
|
tab: ({ active } = {}) => j(cls.tab, active && 'is-active'),
|
|
312
346
|
avatar: ({ size } = {}) =>
|
|
313
347
|
j(cls.avatar, size === 'sm' && cls.avatarSm, size === 'lg' && cls.avatarLg),
|
|
314
348
|
prose: ({ compact } = {}) => j(cls.prose, compact && cls.proseCompact),
|
|
315
|
-
container: ({ narrow } = {}) =>
|
|
349
|
+
container: ({ narrow, wide } = {}) =>
|
|
350
|
+
j(cls.container, narrow && cls.containerNarrow, wide && cls.containerWide),
|
|
316
351
|
tag: ({ accent } = {}) => j(cls.tag, accent && cls.tagAccent),
|
|
317
352
|
};
|
|
318
353
|
|
package/css/app.css
CHANGED
|
@@ -111,6 +111,22 @@
|
|
|
111
111
|
padding-block-start: var(--space-sm);
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
/* Account / identity slot — signed-in user + sign-out. A framework-
|
|
115
|
+
blessed home for what every shell otherwise hand-rolls. Pinned to the
|
|
116
|
+
rail end like __foot, but it stays visible when the rail collapses to
|
|
117
|
+
a horizontal bar on mobile (sign-out must not vanish). */
|
|
118
|
+
.ui-app-rail__account {
|
|
119
|
+
align-items: center;
|
|
120
|
+
display: flex;
|
|
121
|
+
gap: var(--space-xs);
|
|
122
|
+
margin-block-start: auto;
|
|
123
|
+
padding-block-start: var(--space-sm);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.ui-app-rail__account + .ui-app-rail__foot {
|
|
127
|
+
margin-block-start: 0;
|
|
128
|
+
}
|
|
129
|
+
|
|
114
130
|
/* --- Main column --- */
|
|
115
131
|
|
|
116
132
|
.ui-app-main {
|
|
@@ -196,77 +212,23 @@
|
|
|
196
212
|
text-transform: uppercase;
|
|
197
213
|
}
|
|
198
214
|
|
|
199
|
-
.ui-app-panel__head p
|
|
200
|
-
.ui-app-empty-state p {
|
|
215
|
+
.ui-app-panel__head p {
|
|
201
216
|
color: var(--text-dim);
|
|
202
217
|
margin: 0.3rem 0 0;
|
|
203
218
|
}
|
|
204
219
|
|
|
205
|
-
/* --- Metric tiles ---
|
|
206
|
-
|
|
207
|
-
.ui-app-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}
|
|
220
|
+
/* --- Metric tiles ---
|
|
221
|
+
The metric primitive itself is shell-agnostic and now lives in
|
|
222
|
+
primitives.css as `.ui-stat` / `.ui-statgrid`; `.ui-app-metric*` and
|
|
223
|
+
`.ui-app-metrics` remain as permanent admin-shell aliases (grouped on
|
|
224
|
+
the canonical rules there — identical output). Nothing app-specific
|
|
225
|
+
left to define here. */
|
|
212
226
|
|
|
213
|
-
/*
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
grid-template-columns: 1fr;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
.ui-app-metric {
|
|
223
|
-
background: var(--panel);
|
|
224
|
-
border: 1px solid var(--line);
|
|
225
|
-
border-radius: var(--radius-md);
|
|
226
|
-
display: grid;
|
|
227
|
-
gap: 0.4rem;
|
|
228
|
-
padding: var(--space-md);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
.ui-app-metric__label {
|
|
232
|
-
color: var(--text-dim);
|
|
233
|
-
font-family: var(--mono);
|
|
234
|
-
font-size: var(--text-2xs);
|
|
235
|
-
letter-spacing: var(--tracking-wide);
|
|
236
|
-
text-transform: uppercase;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
.ui-app-metric__value {
|
|
240
|
-
color: var(--text);
|
|
241
|
-
font-family: var(--display);
|
|
242
|
-
font-size: 1.9rem;
|
|
243
|
-
font-variant-numeric: tabular-nums;
|
|
244
|
-
letter-spacing: 0.01em;
|
|
245
|
-
line-height: 1;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
.ui-app-metric__delta {
|
|
249
|
-
font-family: var(--mono);
|
|
250
|
-
font-size: var(--text-xs);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
.ui-app-metric__delta.is-pos {
|
|
254
|
-
color: var(--success);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
.ui-app-metric__delta.is-neg {
|
|
258
|
-
color: var(--danger);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/* --- Empty state --- */
|
|
262
|
-
|
|
263
|
-
.ui-app-empty-state {
|
|
264
|
-
border: 1px dashed var(--line-strong);
|
|
265
|
-
border-radius: var(--radius-md);
|
|
266
|
-
color: var(--text-dim);
|
|
267
|
-
padding: var(--space-lg);
|
|
268
|
-
text-align: center;
|
|
269
|
-
}
|
|
227
|
+
/* --- Empty state ---
|
|
228
|
+
The empty-state primitive is shell-agnostic and now lives in
|
|
229
|
+
primitives.css as `.ui-empty-state`; `.ui-app-empty-state` remains a
|
|
230
|
+
permanent admin-shell alias (grouped on the canonical rules there —
|
|
231
|
+
identical output). Nothing app-specific left to define here. */
|
|
270
232
|
|
|
271
233
|
/* --- Mobile rail collapse --- */
|
|
272
234
|
|
package/css/dots.css
CHANGED
|
@@ -44,6 +44,30 @@
|
|
|
44
44
|
inline-size: 100%;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
/* Data-bound dot matrix — a grid of state cells (activity / heatmap),
|
|
48
|
+
the on-brand counterpart to the decorative .ui-dotgrid background.
|
|
49
|
+
This is the grid + cell tones only; the data→cell mapping is the
|
|
50
|
+
consumer's. Tune density via --dotmatrix-cols / --dotmatrix-gap. */
|
|
51
|
+
.ui-dotmatrix {
|
|
52
|
+
display: grid;
|
|
53
|
+
gap: var(--dotmatrix-gap, 0.5rem);
|
|
54
|
+
grid-template-columns: repeat(var(--dotmatrix-cols, 12), minmax(0, 1fr));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.ui-dotmatrix__cell {
|
|
58
|
+
aspect-ratio: 1;
|
|
59
|
+
background: var(--field-dot);
|
|
60
|
+
border-radius: 50%;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.ui-dotmatrix__cell--hot {
|
|
64
|
+
background: var(--field-dot-hot);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.ui-dotmatrix__cell--accent {
|
|
68
|
+
background: var(--field-dot-accent);
|
|
69
|
+
}
|
|
70
|
+
|
|
47
71
|
/* Status dot — the glyph-style state indicator. */
|
|
48
72
|
.ui-dot {
|
|
49
73
|
background: var(--text-dim);
|
package/css/overlay.css
CHANGED
|
@@ -31,6 +31,16 @@
|
|
|
31
31
|
grid-template-rows: auto 1fr auto;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/* Controlled (non-<dialog>) usage. A portal/React modal that can't be a
|
|
35
|
+
native <dialog> wears the same skin + open layout via `.is-open`.
|
|
36
|
+
Backdrop, top-layer stacking and focus-trapping are then the
|
|
37
|
+
consumer's responsibility (the native <dialog> path gets them free). */
|
|
38
|
+
.ui-modal.is-open {
|
|
39
|
+
animation: uiToastIn var(--duration-base) var(--ease-spring) both;
|
|
40
|
+
display: grid;
|
|
41
|
+
grid-template-rows: auto 1fr auto;
|
|
42
|
+
}
|
|
43
|
+
|
|
34
44
|
.ui-modal__head {
|
|
35
45
|
align-items: flex-start;
|
|
36
46
|
border-block-end: 1px solid var(--line);
|