@ponchia/ui 0.4.0 → 0.4.1
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 +128 -10
- package/README.md +20 -13
- package/behaviors/index.d.ts +3 -1
- package/behaviors/index.js +179 -106
- package/classes/index.d.ts +40 -0
- package/classes/index.js +41 -0
- package/classes/vscode.css-custom-data.json +18 -14
- package/css/disclosure.css +29 -0
- package/css/dots.css +2 -0
- package/css/feedback.css +53 -0
- package/css/motion.css +88 -0
- package/css/overlay.css +52 -1
- package/css/report.css +382 -0
- package/css/tokens.css +56 -26
- package/dist/bronto.css +1 -1
- package/dist/css/disclosure.css +1 -1
- package/dist/css/dots.css +1 -1
- package/dist/css/feedback.css +1 -1
- package/dist/css/motion.css +1 -1
- package/dist/css/overlay.css +1 -1
- package/dist/css/report.css +1 -0
- package/dist/css/tokens.css +1 -1
- package/docs/adr/0001-color-system.md +26 -27
- package/docs/adr/0002-scope-and-2026-baseline.md +104 -0
- package/docs/adr/0003-theme-model.md +94 -0
- package/docs/contrast.md +42 -42
- package/docs/reference.md +112 -15
- package/docs/reporting.md +270 -0
- package/docs/stability.md +37 -0
- package/docs/theming.md +18 -6
- package/docs/usage.md +21 -3
- package/llms.txt +61 -4
- package/package.json +28 -3
- package/qwik/index.d.ts +55 -0
- package/qwik/index.js +129 -0
- package/react/index.d.ts +35 -14
- package/react/index.js +22 -5
- package/solid/index.d.ts +35 -14
- package/solid/index.js +21 -3
- package/tokens/index.d.ts +3 -3
- package/tokens/index.js +16 -14
- package/tokens/index.json +32 -28
- package/tokens/resolved.json +34 -32
- package/tokens/tokens.dtcg.json +22 -14
package/docs/reference.md
CHANGED
|
@@ -9,7 +9,7 @@ rendering of every class is the kitchen-sink demo:
|
|
|
9
9
|
**<https://ponchia.github.io/bronto-ui/>**. Theming knobs and the token
|
|
10
10
|
contract: [docs/theming.md](theming.md).
|
|
11
11
|
|
|
12
|
-
-
|
|
12
|
+
- 303 classes across 121 component groups
|
|
13
13
|
- Import the typed registry: `import { cls, ui, cx } from '@ponchia/ui/classes'`
|
|
14
14
|
- Tokens as data: `import { cssVars, tokens, themeColor } from '@ponchia/ui/tokens'`
|
|
15
15
|
|
|
@@ -179,6 +179,18 @@ each one matches a real selector in the stylesheet.
|
|
|
179
179
|
| `cls.breadcrumb` | `ui-breadcrumb` | base |
|
|
180
180
|
| `cls.breadcrumbItem` | `ui-breadcrumb__item` | part |
|
|
181
181
|
|
|
182
|
+
### `.ui-break-after`
|
|
183
|
+
|
|
184
|
+
| Registry key | Class | Kind |
|
|
185
|
+
| --- | --- | --- |
|
|
186
|
+
| `cls.breakAfter` | `ui-break-after` | base |
|
|
187
|
+
|
|
188
|
+
### `.ui-break-before`
|
|
189
|
+
|
|
190
|
+
| Registry key | Class | Kind |
|
|
191
|
+
| --- | --- | --- |
|
|
192
|
+
| `cls.breakBefore` | `ui-break-before` | base |
|
|
193
|
+
|
|
182
194
|
### `.ui-button`
|
|
183
195
|
|
|
184
196
|
| Registry key | Class | Kind |
|
|
@@ -226,6 +238,21 @@ each one matches a real selector in the stylesheet.
|
|
|
226
238
|
| --- | --- | --- |
|
|
227
239
|
| `cls.center` | `ui-center` | base |
|
|
228
240
|
|
|
241
|
+
### `.ui-chart`
|
|
242
|
+
|
|
243
|
+
| Registry key | Class | Kind |
|
|
244
|
+
| --- | --- | --- |
|
|
245
|
+
| `cls.chart` | `ui-chart` | base |
|
|
246
|
+
| `cls.chartBar` | `ui-chart__bar` | part |
|
|
247
|
+
| `cls.chartCaption` | `ui-chart__caption` | part |
|
|
248
|
+
| `cls.chartFallback` | `ui-chart__fallback` | part |
|
|
249
|
+
| `cls.chartFill` | `ui-chart__fill` | part |
|
|
250
|
+
| `cls.chartLabel` | `ui-chart__label` | part |
|
|
251
|
+
| `cls.chartLegend` | `ui-chart__legend` | part |
|
|
252
|
+
| `cls.chartPlot` | `ui-chart__plot` | part |
|
|
253
|
+
| `cls.chartSwatch` | `ui-chart__swatch` | part |
|
|
254
|
+
| `cls.chartTrack` | `ui-chart__track` | part |
|
|
255
|
+
|
|
229
256
|
### `.ui-check`
|
|
230
257
|
|
|
231
258
|
| Registry key | Class | Kind |
|
|
@@ -426,6 +453,12 @@ each one matches a real selector in the stylesheet.
|
|
|
426
453
|
| --- | --- | --- |
|
|
427
454
|
| `cls.kbd` | `ui-kbd` | base |
|
|
428
455
|
|
|
456
|
+
### `.ui-keep`
|
|
457
|
+
|
|
458
|
+
| Registry key | Class | Kind |
|
|
459
|
+
| --- | --- | --- |
|
|
460
|
+
| `cls.keep` | `ui-keep` | base |
|
|
461
|
+
|
|
429
462
|
### `.ui-key-value`
|
|
430
463
|
|
|
431
464
|
| Registry key | Class | Kind |
|
|
@@ -553,6 +586,18 @@ each one matches a real selector in the stylesheet.
|
|
|
553
586
|
| --- | --- | --- |
|
|
554
587
|
| `cls.popover` | `ui-popover` | base |
|
|
555
588
|
|
|
589
|
+
### `.ui-print-exact`
|
|
590
|
+
|
|
591
|
+
| Registry key | Class | Kind |
|
|
592
|
+
| --- | --- | --- |
|
|
593
|
+
| `cls.printExact` | `ui-print-exact` | base |
|
|
594
|
+
|
|
595
|
+
### `.ui-print-only`
|
|
596
|
+
|
|
597
|
+
| Registry key | Class | Kind |
|
|
598
|
+
| --- | --- | --- |
|
|
599
|
+
| `cls.printOnly` | `ui-print-only` | base |
|
|
600
|
+
|
|
556
601
|
### `.ui-progress`
|
|
557
602
|
|
|
558
603
|
| Registry key | Class | Kind |
|
|
@@ -587,12 +632,56 @@ each one matches a real selector in the stylesheet.
|
|
|
587
632
|
| --- | --- | --- |
|
|
588
633
|
| `cls.ratio` | `ui-ratio` | base |
|
|
589
634
|
|
|
635
|
+
### `.ui-report`
|
|
636
|
+
|
|
637
|
+
| Registry key | Class | Kind |
|
|
638
|
+
| --- | --- | --- |
|
|
639
|
+
| `cls.report` | `ui-report` | base |
|
|
640
|
+
| `cls.reportAppendix` | `ui-report__appendix` | part |
|
|
641
|
+
| `cls.reportCaption` | `ui-report__caption` | part |
|
|
642
|
+
| `cls.reportCover` | `ui-report__cover` | part |
|
|
643
|
+
| `cls.reportCoverCompact` | `ui-report__cover--compact` | modifier |
|
|
644
|
+
| `cls.reportEvidence` | `ui-report__evidence` | part |
|
|
645
|
+
| `cls.reportFigure` | `ui-report__figure` | part |
|
|
646
|
+
| `cls.reportFinding` | `ui-report__finding` | part |
|
|
647
|
+
| `cls.reportFootnotes` | `ui-report__footnotes` | part |
|
|
648
|
+
| `cls.reportHeader` | `ui-report__header` | part |
|
|
649
|
+
| `cls.reportMeta` | `ui-report__meta` | part |
|
|
650
|
+
| `cls.reportSection` | `ui-report__section` | part |
|
|
651
|
+
| `cls.reportSectionUnnumbered` | `ui-report__section--unnumbered` | modifier |
|
|
652
|
+
| `cls.reportSectionHead` | `ui-report__section-head` | part |
|
|
653
|
+
| `cls.reportSources` | `ui-report__sources` | part |
|
|
654
|
+
| `cls.reportSubtitle` | `ui-report__subtitle` | part |
|
|
655
|
+
| `cls.reportSummary` | `ui-report__summary` | part |
|
|
656
|
+
| `cls.reportTitle` | `ui-report__title` | part |
|
|
657
|
+
| `cls.reportToc` | `ui-report__toc` | part |
|
|
658
|
+
| `cls.reportCompact` | `ui-report--compact` | modifier |
|
|
659
|
+
| `cls.reportNumbered` | `ui-report--numbered` | modifier |
|
|
660
|
+
|
|
590
661
|
### `.ui-reveal`
|
|
591
662
|
|
|
592
663
|
| Registry key | Class | Kind |
|
|
593
664
|
| --- | --- | --- |
|
|
594
665
|
| `cls.reveal` | `ui-reveal` | base |
|
|
595
666
|
|
|
667
|
+
### `.ui-screen-only`
|
|
668
|
+
|
|
669
|
+
| Registry key | Class | Kind |
|
|
670
|
+
| --- | --- | --- |
|
|
671
|
+
| `cls.screenOnly` | `ui-screen-only` | base |
|
|
672
|
+
|
|
673
|
+
### `.ui-scroll-progress`
|
|
674
|
+
|
|
675
|
+
| Registry key | Class | Kind |
|
|
676
|
+
| --- | --- | --- |
|
|
677
|
+
| `cls.scrollProgress` | `ui-scroll-progress` | base |
|
|
678
|
+
|
|
679
|
+
### `.ui-scroll-reveal`
|
|
680
|
+
|
|
681
|
+
| Registry key | Class | Kind |
|
|
682
|
+
| --- | --- | --- |
|
|
683
|
+
| `cls.scrollReveal` | `ui-scroll-reveal` | base |
|
|
684
|
+
|
|
596
685
|
### `.ui-search`
|
|
597
686
|
|
|
598
687
|
| Registry key | Class | Kind |
|
|
@@ -832,6 +921,12 @@ each one matches a real selector in the stylesheet.
|
|
|
832
921
|
| --- | --- | --- |
|
|
833
922
|
| `cls.visuallyHidden` | `ui-visually-hidden` | base |
|
|
834
923
|
|
|
924
|
+
### `.ui-vt`
|
|
925
|
+
|
|
926
|
+
| Registry key | Class | Kind |
|
|
927
|
+
| --- | --- | --- |
|
|
928
|
+
| `cls.vt` | `ui-vt` | base |
|
|
929
|
+
|
|
835
930
|
## Table-local state classes
|
|
836
931
|
|
|
837
932
|
Not in `cls` by design — these are plain `is-*` state hooks scoped to
|
|
@@ -919,10 +1014,10 @@ Exact mirror of the `:root` blocks in `css/tokens.css`
|
|
|
919
1014
|
| `--z-overlay` | `30` |
|
|
920
1015
|
| `--z-popover` | `50` |
|
|
921
1016
|
| `--z-toast` | `60` |
|
|
922
|
-
| `--accent-1` | `color-mix(in oklch, var(--accent) 8%, var(--
|
|
923
|
-
| `--accent-2` | `color-mix(in oklch, var(--accent) 16%, var(--
|
|
924
|
-
| `--accent-3` | `color-mix(in oklch, var(--accent) 32%, var(--
|
|
925
|
-
| `--accent-4` | `color-mix(in oklch, var(--accent) 60%, var(--
|
|
1017
|
+
| `--accent-1` | `color-mix(in oklch, var(--accent) 8%, var(--accent-ramp-end))` |
|
|
1018
|
+
| `--accent-2` | `color-mix(in oklch, var(--accent) 16%, var(--accent-ramp-end))` |
|
|
1019
|
+
| `--accent-3` | `color-mix(in oklch, var(--accent) 32%, var(--accent-ramp-end))` |
|
|
1020
|
+
| `--accent-4` | `color-mix(in oklch, var(--accent) 60%, var(--accent-ramp-end))` |
|
|
926
1021
|
| `--accent-5` | `var(--accent)` |
|
|
927
1022
|
| `--accent-6` | `var(--accent-strong)` |
|
|
928
1023
|
| `--surface-1` | `var(--bg)` |
|
|
@@ -967,6 +1062,7 @@ Exact mirror of the `:root` blocks in `css/tokens.css`
|
|
|
967
1062
|
| `--text-soft` | `#353533` |
|
|
968
1063
|
| `--text-dim` | `#686863` |
|
|
969
1064
|
| `--accent` | `#d71921` |
|
|
1065
|
+
| `--accent-ramp-end` | `#ffffff` |
|
|
970
1066
|
| `--accent-strong` | `color-mix(in srgb, var(--accent) 83%, #000)` |
|
|
971
1067
|
| `--accent-text` | `var(--accent-strong)` |
|
|
972
1068
|
| `--accent-soft` | `color-mix(in srgb, var(--accent) 10%, transparent)` |
|
|
@@ -991,18 +1087,19 @@ Exact mirror of the `:root` blocks in `css/tokens.css`
|
|
|
991
1087
|
|
|
992
1088
|
| Token | Value |
|
|
993
1089
|
| --- | --- |
|
|
994
|
-
| `--bg` | `#
|
|
995
|
-
| `--bg-elevated` | `#
|
|
1090
|
+
| `--bg` | `#121212` |
|
|
1091
|
+
| `--bg-elevated` | `#181818` |
|
|
996
1092
|
| `--bg-accent` | `color-mix(in srgb, var(--accent) 8%, transparent)` |
|
|
997
|
-
| `--panel` | `#
|
|
998
|
-
| `--panel-strong` | `#
|
|
999
|
-
| `--panel-soft` | `#
|
|
1000
|
-
| `--line` | `#
|
|
1001
|
-
| `--line-strong` | `#
|
|
1002
|
-
| `--text` | `#
|
|
1003
|
-
| `--text-soft` | `#
|
|
1004
|
-
| `--text-dim` | `#
|
|
1093
|
+
| `--panel` | `#1c1c1c` |
|
|
1094
|
+
| `--panel-strong` | `#222222` |
|
|
1095
|
+
| `--panel-soft` | `#242424` |
|
|
1096
|
+
| `--line` | `#383838` |
|
|
1097
|
+
| `--line-strong` | `#555555` |
|
|
1098
|
+
| `--text` | `#e6e6e6` |
|
|
1099
|
+
| `--text-soft` | `#c8c8c8` |
|
|
1100
|
+
| `--text-dim` | `#a0a0a0` |
|
|
1005
1101
|
| `--accent` | `#ff3b41` |
|
|
1102
|
+
| `--accent-ramp-end` | `#000000` |
|
|
1006
1103
|
| `--accent-strong` | `color-mix(in srgb, var(--accent) 84%, #fff)` |
|
|
1007
1104
|
| `--accent-text` | `var(--accent-strong)` |
|
|
1008
1105
|
| `--accent-soft` | `color-mix(in srgb, var(--accent) 14%, transparent)` |
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# Static reports
|
|
2
|
+
|
|
3
|
+
`@ponchia/ui` can dress static, LLM-authored HTML reports without a component
|
|
4
|
+
runtime. Load the normal bundle, then opt in to the report layer and the chart
|
|
5
|
+
palette only when the report needs them.
|
|
6
|
+
|
|
7
|
+
In a bundled app, package specifiers are fine because Vite or another bundler
|
|
8
|
+
rewrites them:
|
|
9
|
+
|
|
10
|
+
```css
|
|
11
|
+
@import '@ponchia/ui';
|
|
12
|
+
@import '@ponchia/ui/css/report.css';
|
|
13
|
+
@import '@ponchia/ui/css/dataviz.css';
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
For standalone browser HTML, use real stylesheet URLs. Package specifiers like
|
|
17
|
+
`@ponchia/ui/css/report.css` do not resolve in a saved `.html` file:
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<link rel="stylesheet" href="./node_modules/@ponchia/ui/dist/bronto.css" />
|
|
21
|
+
<link rel="stylesheet" href="./node_modules/@ponchia/ui/dist/css/report.css" />
|
|
22
|
+
<link rel="stylesheet" href="./node_modules/@ponchia/ui/dist/css/dataviz.css" />
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If you copy the built CSS next to the report, keep the same relationship between
|
|
26
|
+
`dist/bronto.css`, `dist/css/report.css`, `dist/css/dataviz.css`, and `fonts/`
|
|
27
|
+
so font URLs continue to resolve.
|
|
28
|
+
|
|
29
|
+
The report layer is static and PDF-first. It does not initialize behaviors and
|
|
30
|
+
does not sanitize content. If a report includes arbitrary LLM, CMS, or user HTML,
|
|
31
|
+
sanitize that content before rendering it and do not initialize
|
|
32
|
+
`data-bronto-*` behaviors on the generated region.
|
|
33
|
+
|
|
34
|
+
## Canonical skeleton
|
|
35
|
+
|
|
36
|
+
```html
|
|
37
|
+
<main class="ui-report ui-report--numbered">
|
|
38
|
+
<header class="ui-report__cover">
|
|
39
|
+
<p class="ui-eyebrow">Quarterly review</p>
|
|
40
|
+
<h1 class="ui-report__title">Personal systems report</h1>
|
|
41
|
+
<p class="ui-report__subtitle">A static report generated from trusted data.</p>
|
|
42
|
+
<ul class="ui-report__meta">
|
|
43
|
+
<li><time datetime="2026-06-01">2026-06-01</time></li>
|
|
44
|
+
<li>Static HTML</li>
|
|
45
|
+
<li>Chromium PDF-ready</li>
|
|
46
|
+
</ul>
|
|
47
|
+
</header>
|
|
48
|
+
|
|
49
|
+
<nav class="ui-report__toc" aria-label="Report contents">
|
|
50
|
+
<p class="ui-eyebrow ui-eyebrow--muted">Contents</p>
|
|
51
|
+
<ol>
|
|
52
|
+
<li><a href="#summary">Executive summary</a></li>
|
|
53
|
+
<li><a href="#findings">Findings</a></li>
|
|
54
|
+
</ol>
|
|
55
|
+
</nav>
|
|
56
|
+
|
|
57
|
+
<section id="summary" class="ui-report__section">
|
|
58
|
+
<h2 class="ui-report__section-head">Executive summary</h2>
|
|
59
|
+
<div class="ui-report__summary">
|
|
60
|
+
<p>The summary block is for the decision-level conclusion.</p>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="ui-statgrid">
|
|
63
|
+
<div class="ui-stat">
|
|
64
|
+
<span class="ui-stat__label">Open risks</span>
|
|
65
|
+
<span class="ui-stat__value">3</span>
|
|
66
|
+
<span class="ui-stat__delta is-neg">+1 this week</span>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</section>
|
|
70
|
+
|
|
71
|
+
<section id="findings" class="ui-report__section">
|
|
72
|
+
<h2 class="ui-report__section-head">Findings</h2>
|
|
73
|
+
<article class="ui-report__finding" aria-labelledby="finding-1">
|
|
74
|
+
<p class="ui-eyebrow" id="finding-1">Finding 1 — short title</p>
|
|
75
|
+
<div class="ui-prose">
|
|
76
|
+
<p>Use prose only for narrative body content.</p>
|
|
77
|
+
</div>
|
|
78
|
+
</article>
|
|
79
|
+
</section>
|
|
80
|
+
</main>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Composition rules
|
|
84
|
+
|
|
85
|
+
- Use `ui-report` as the page-level wrapper. Add `ui-report--numbered` when
|
|
86
|
+
section headings should auto-number. Add `ui-report--compact` to tighten the
|
|
87
|
+
whole report's vertical rhythm (gap + page padding) for dense briefs — this
|
|
88
|
+
is the document-level density toggle, distinct from `ui-report__cover--compact`
|
|
89
|
+
below, which only shrinks the cover.
|
|
90
|
+
- Use `ui-report__cover` for title, subtitle, author/date, and generation
|
|
91
|
+
metadata. Add `ui-report__cover--compact` for short screen-first reports.
|
|
92
|
+
Use `ui-report__header` for a compact in-page header instead of a full cover
|
|
93
|
+
(same role, no tall hero block). Author `ui-report__meta` as a `<ul>` — the
|
|
94
|
+
facts it lists are unordered.
|
|
95
|
+
- Use `ui-report__section` and `ui-report__section-head` for report chapters.
|
|
96
|
+
Keep one `h1` for the report title; use ordered `h2`/`h3` headings after it.
|
|
97
|
+
- Add `ui-report__section--unnumbered` to appendices, sources, or footnotes
|
|
98
|
+
when the report uses `ui-report--numbered` but the section should not count as
|
|
99
|
+
a numbered chapter.
|
|
100
|
+
- Use `ui-prose` only around narrative HTML you do not fully control, such as
|
|
101
|
+
Markdown output. Do not wrap structured app/report UI in `ui-prose`.
|
|
102
|
+
- Use existing primitives for shared meanings: `ui-statgrid` for KPIs,
|
|
103
|
+
`ui-alert` for persistent notices, `ui-table` for structured evidence,
|
|
104
|
+
`ui-timeline` for events, `ui-meter` for measured values, and `ui-num` for
|
|
105
|
+
non-table numeric values.
|
|
106
|
+
- Give `ui-report__finding` blocks an accessible name so the visual grouping is
|
|
107
|
+
also programmatic: point `aria-labelledby` at the block's `ui-eyebrow` label
|
|
108
|
+
(give it an `id`), or lead with a real heading. Do the same for a
|
|
109
|
+
multi-part `ui-report__evidence` block; a single evidence table is already
|
|
110
|
+
named by its own `<caption>`.
|
|
111
|
+
- Name the `ui-report__sources` and `ui-report__footnotes` blocks
|
|
112
|
+
(`aria-labelledby` on their `ui-eyebrow`), and link footnotes both ways:
|
|
113
|
+
an in-text `<sup><a id="fnref1" href="#fn1">1</a></sup>` to an
|
|
114
|
+
`<ol><li id="fn1">… <a href="#fnref1">↩</a></li></ol>`. They are real
|
|
115
|
+
regions, not decoration.
|
|
116
|
+
- Every `<table>` that carries report data should have a `<caption>`, header
|
|
117
|
+
cells, and `.is-num` on numeric columns. (`.is-num`, `.is-pos`, `.is-neg`
|
|
118
|
+
and `.is-key` only take effect inside `.ui-table` cells and `.ui-stat`
|
|
119
|
+
deltas — they are not free-standing utilities.) Keep raw Markdown tables
|
|
120
|
+
inside `ui-prose`; use `.ui-table` for curated evidence tables. If a
|
|
121
|
+
`ui-report__evidence` block contains only a `ui-table-wrap`, the report layer
|
|
122
|
+
removes the inner frame so evidence tables do not look double-boxed.
|
|
123
|
+
- Every `<figure>` should include a `figcaption` using
|
|
124
|
+
`ui-chart__caption` (chart figures) or `ui-report__caption` (any other
|
|
125
|
+
report figure); the two are interchangeable in style.
|
|
126
|
+
- Do not use raw color values. Theme with `--accent`; use status tones for
|
|
127
|
+
status; use chart tokens only in chart figures.
|
|
128
|
+
|
|
129
|
+
## Chart figure recipe
|
|
130
|
+
|
|
131
|
+
The report layer supplies chart containers, legends, and a small static bar
|
|
132
|
+
pattern, not a chart engine. For CSS/HTML/SVG charts, pair each chart color with
|
|
133
|
+
a direct label, a pattern, or a fallback table.
|
|
134
|
+
|
|
135
|
+
```html
|
|
136
|
+
<figure class="ui-report__figure ui-chart ui-print-exact" role="group" aria-labelledby="chart-title">
|
|
137
|
+
<figcaption id="chart-title" class="ui-chart__caption">
|
|
138
|
+
Fig 1 - Weekly focus split
|
|
139
|
+
</figcaption>
|
|
140
|
+
<ul class="ui-chart__legend" aria-label="Series">
|
|
141
|
+
<li>
|
|
142
|
+
<span
|
|
143
|
+
class="ui-chart__swatch"
|
|
144
|
+
style="--chart-color: var(--chart-1); --chart-pattern: var(--chart-pattern-1)"
|
|
145
|
+
aria-hidden="true"
|
|
146
|
+
></span>
|
|
147
|
+
Research
|
|
148
|
+
</li>
|
|
149
|
+
<li>
|
|
150
|
+
<span
|
|
151
|
+
class="ui-chart__swatch"
|
|
152
|
+
style="--chart-color: var(--chart-2); --chart-pattern: var(--chart-pattern-2)"
|
|
153
|
+
aria-hidden="true"
|
|
154
|
+
></span>
|
|
155
|
+
Delivery
|
|
156
|
+
</li>
|
|
157
|
+
</ul>
|
|
158
|
+
<div class="ui-chart__plot" aria-hidden="true">
|
|
159
|
+
<div
|
|
160
|
+
class="ui-chart__bar"
|
|
161
|
+
style="--chart-value: 72%; --chart-color: var(--chart-1); --chart-pattern: var(--chart-pattern-1)"
|
|
162
|
+
>
|
|
163
|
+
<div class="ui-chart__label"><span>Research</span><span>18 h</span></div>
|
|
164
|
+
<div class="ui-chart__track"><div class="ui-chart__fill"></div></div>
|
|
165
|
+
</div>
|
|
166
|
+
<div
|
|
167
|
+
class="ui-chart__bar"
|
|
168
|
+
style="--chart-value: 44%; --chart-color: var(--chart-2); --chart-pattern: var(--chart-pattern-2)"
|
|
169
|
+
>
|
|
170
|
+
<div class="ui-chart__label"><span>Delivery</span><span>11 h</span></div>
|
|
171
|
+
<div class="ui-chart__track"><div class="ui-chart__fill"></div></div>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
<div class="ui-chart__fallback">
|
|
175
|
+
<div class="ui-table-wrap">
|
|
176
|
+
<table class="ui-table ui-table--dense">
|
|
177
|
+
<caption>Chart source data</caption>
|
|
178
|
+
<thead>
|
|
179
|
+
<tr><th>Series</th><th class="is-num">Hours</th></tr>
|
|
180
|
+
</thead>
|
|
181
|
+
<tbody>
|
|
182
|
+
<tr><td>Research</td><td class="is-num">18</td></tr>
|
|
183
|
+
<tr><td>Delivery</td><td class="is-num">11</td></tr>
|
|
184
|
+
</tbody>
|
|
185
|
+
</table>
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
</figure>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
For canvas or SVG libraries, import resolved series colors from
|
|
192
|
+
`@ponchia/ui/charts.json` and keep the same legend/caption/fallback structure in
|
|
193
|
+
the surrounding HTML.
|
|
194
|
+
|
|
195
|
+
## Timeline recipe
|
|
196
|
+
|
|
197
|
+
Incident reviews and research logs should use the existing timeline primitive
|
|
198
|
+
with its required item and time parts. Do not emit a bare list and expect it to
|
|
199
|
+
style itself.
|
|
200
|
+
|
|
201
|
+
```html
|
|
202
|
+
<ol class="ui-timeline">
|
|
203
|
+
<li class="ui-timeline__item">
|
|
204
|
+
<time class="ui-timeline__time" datetime="2026-06-01T09:12:00">09:12</time>
|
|
205
|
+
<span>Latency alert fired for p95 over threshold.</span>
|
|
206
|
+
</li>
|
|
207
|
+
<li class="ui-timeline__item" aria-current="step">
|
|
208
|
+
<time class="ui-timeline__time" datetime="2026-06-01T09:54:00">09:54</time>
|
|
209
|
+
<span>Latency returned to baseline.</span>
|
|
210
|
+
</li>
|
|
211
|
+
</ol>
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Common templates
|
|
215
|
+
|
|
216
|
+
- Executive brief: compact cover, one summary block, KPI `ui-statgrid`, short
|
|
217
|
+
findings, and sources.
|
|
218
|
+
- Research brief: compact header, decision frame, evidence table, quotes or
|
|
219
|
+
prose excerpts, and sources.
|
|
220
|
+
- Incident review: compact cover, summary, `ui-timeline`, corrective-action
|
|
221
|
+
evidence table, and footnotes.
|
|
222
|
+
- Project status: compact header, KPI `ui-statgrid`, chart figure with fallback
|
|
223
|
+
data, print-only notes, and unnumbered appendix.
|
|
224
|
+
|
|
225
|
+
## Print and PDF
|
|
226
|
+
|
|
227
|
+
The supported export target is modern Chromium print/PDF. Two ways to produce
|
|
228
|
+
the file:
|
|
229
|
+
|
|
230
|
+
- **By hand:** open the report in Chrome/Edge → Print (Cmd/Ctrl+P) → "Save as
|
|
231
|
+
PDF". In **More settings**, enable **Background graphics** (the dialog's
|
|
232
|
+
equivalent of `printBackground` — without it chart fills and swatches drop
|
|
233
|
+
out), and pick the paper size there. Paper size is a browser print setting,
|
|
234
|
+
not a token; the layer only themes the page _margin_ via
|
|
235
|
+
`--report-page-margin`.
|
|
236
|
+
- **Headless (agents/CI):** `await page.pdf({ format: 'A4', printBackground: true })`
|
|
237
|
+
with Playwright or Puppeteer.
|
|
238
|
+
|
|
239
|
+
The report prints ink-on-white regardless of the on-screen theme. Older
|
|
240
|
+
HTML-to-PDF engines are not part of the browser floor and may not support
|
|
241
|
+
cascade layers, `oklch()`, `color-mix()`, `:has()`, or modern paged-media
|
|
242
|
+
behavior.
|
|
243
|
+
|
|
244
|
+
- Use `ui-print-only` for content that should appear only in print.
|
|
245
|
+
- Use `ui-screen-only` for navigation or helper content that should not print.
|
|
246
|
+
- Use `ui-break-before` and `ui-break-after` for deliberate page boundaries.
|
|
247
|
+
- Use `ui-keep` on short figures, findings, and summary blocks that should not
|
|
248
|
+
split across pages.
|
|
249
|
+
- Use `ui-print-exact` on charts whose fills and patterns must survive PDF
|
|
250
|
+
export.
|
|
251
|
+
- External links inside `ui-prose` print their URL automatically through the
|
|
252
|
+
base print stylesheet.
|
|
253
|
+
|
|
254
|
+
**Not provided** (use the browser's paged-media features, or author the markup
|
|
255
|
+
yourself): running headers/footers with "Page X of Y", automatic table-of-contents
|
|
256
|
+
pagination, multi-column layout, and automatic citation/footnote numbering. The
|
|
257
|
+
report layer is a document grammar, not a paged-media or citation engine — do not
|
|
258
|
+
fake page numbers with inert markup.
|
|
259
|
+
|
|
260
|
+
## LLM checklist
|
|
261
|
+
|
|
262
|
+
Before returning a report, an LLM should verify:
|
|
263
|
+
|
|
264
|
+
- All `ui-*` classes exist in `@ponchia/ui/classes`.
|
|
265
|
+
- The document has one `h1`, ordered headings, and a single main report region.
|
|
266
|
+
- Tables have captions and header cells.
|
|
267
|
+
- Charts have captions, direct labels or legends, and fallback data.
|
|
268
|
+
- No raw chromatic colors appear in inline styles.
|
|
269
|
+
- No remote scripts, styles, iframes, or images are required for the report.
|
|
270
|
+
- Generated/untrusted body HTML was sanitized before insertion.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Public API Stability
|
|
2
|
+
|
|
3
|
+
`@ponchia/ui` is pre-1.0. Breaking changes ship in the minor (`0.x.0`), and
|
|
4
|
+
patches are non-breaking. This matrix defines what counts as public API.
|
|
5
|
+
|
|
6
|
+
| Surface | Stability | Contract |
|
|
7
|
+
| --- | --- | --- |
|
|
8
|
+
| CSS package root (`@ponchia/ui`) | Stable | CSS-only entrypoint. CSS side-effect imports are supported in CSS-aware bundlers; Node/runtime JS root imports are not. |
|
|
9
|
+
| JS module format | Stable | JS subpaths are ESM-only. CommonJS consumers use dynamic `import()`. |
|
|
10
|
+
| CSS class names (`.ui-*`) | Stable | Names and documented modifier semantics are public. Internal selector structure and leaf-file boundaries may change. |
|
|
11
|
+
| Class recipes (`@ponchia/ui/classes`) | Stable | Exported `cls`, `ui`, `cx`, recipe names, and option unions are public. |
|
|
12
|
+
| Design tokens | Stable names/roles | Token names and documented roles are public. Exact values and generated colour math outputs may change for visual tuning before 1.0. |
|
|
13
|
+
| `--accent-1..6` | Stable names/roles | A subtle-to-bold accent ramp derived from `--accent`. Exact resolved values are visual tuning; algorithm changes require release-note visibility and resolver/browser checks. |
|
|
14
|
+
| Behavior attributes (`data-bronto-*`) | Stable | Attribute names and documented markup relationships are public. Behavior internals are not. |
|
|
15
|
+
| Behavior functions (`@ponchia/ui/behaviors`) | Stable | Exported function names, option names, custom events, SSR no-op behavior, idempotency, and cleanup-returning contract are public. |
|
|
16
|
+
| Glyph registry/renderers (`@ponchia/ui/glyphs`) | Stable additive | Existing glyph names stay valid. New glyphs are additive. Renderer option names and accessibility defaults are public. |
|
|
17
|
+
| `.ui-icon` mask renderer | Stable | Class name, `--icon-size`, currentColor inheritance, and `--icon-mask` contract are public. The internal data URL encoding is not. |
|
|
18
|
+
| React/Solid/Qwik bindings | Stable thin adapters | Hook/primitive names, optional peer behavior, root ref/signal/resolver support, and cleanup lifecycle are public. They remain wrappers over vanilla behaviors, not component APIs. |
|
|
19
|
+
| Skins (`@ponchia/ui/skins`, `css/skins.css`) | Stable additive | Existing skin names stay valid. New skins are additive. Skins are root-level choices. |
|
|
20
|
+
| Charts (`@ponchia/ui/charts`, `charts.json`, `css/dataviz.css`) | Stable additive | Token names, JSON shape, and 8 categorical slots are public. Exact palette values may tune if gates and release notes justify it. |
|
|
21
|
+
| Reports (`css/report.css`, `.ui-report*`, `.ui-chart*`, print utilities) | Stable additive | Report class names, BEM part names, chart helper class names, and print utility names are public. Report CSS is opt-in and not imported by the default bundle. |
|
|
22
|
+
| Generated docs shipped in npm | Stable paths | `llms.txt` and exported docs paths stay shipped and resolvable within a compatible minor. Markdown/text assets are for reading unless your runtime has a loader. Generated content may change with the source contract. |
|
|
23
|
+
| Demo, examples, tests, scripts | Internal | Useful for learning and verification, but not shipped runtime API unless a path is explicitly exported in `package.json`. |
|
|
24
|
+
|
|
25
|
+
## Trust Boundary
|
|
26
|
+
|
|
27
|
+
Behaviors assume trusted application markup. If a delegated root includes
|
|
28
|
+
untrusted CMS or user HTML, sanitize it first or do not initialize behaviors on
|
|
29
|
+
that root. The behavior layer intentionally lets authored `data-bronto-*`,
|
|
30
|
+
`aria-controls`, and `id` relationships control elements inside the root.
|
|
31
|
+
Dialog, disclosure, and popover targets resolve root-first and then
|
|
32
|
+
document-wide for body/portal-mounted overlays; scoped roots are not a sandbox
|
|
33
|
+
for untrusted markup.
|
|
34
|
+
|
|
35
|
+
The one-node glyph mask renderer emits inline style/custom-property data. Apps
|
|
36
|
+
with a strict CSP should either allow the required `data:` mask/image source and
|
|
37
|
+
inline custom-property style path, or use the DOM dot/solid renderers.
|
package/docs/theming.md
CHANGED
|
@@ -4,13 +4,15 @@
|
|
|
4
4
|
This is the **stable, supported surface** for re-branding without forking.
|
|
5
5
|
Anything not listed here is internal and may change between minor versions.
|
|
6
6
|
|
|
7
|
-
## The
|
|
7
|
+
## The brand knob: `--accent`
|
|
8
8
|
|
|
9
|
-
The
|
|
9
|
+
The accent family derives from `--accent` via `color-mix()` and the
|
|
10
|
+
theme-owned neutral ramp endpoint:
|
|
10
11
|
|
|
11
12
|
| Token | Derivation (light / dark) | Role |
|
|
12
13
|
| --------------------- | -------------------------------------------- | ---- |
|
|
13
14
|
| `--accent-strong` | `--accent` mixed 83% with black / 84% white | darker/lighter accent for hover, emphasis |
|
|
15
|
+
| `--accent-ramp-end` | white / black | neutral endpoint for the low-chroma OKLCH ramp |
|
|
14
16
|
| `--accent-text` | `var(--accent-strong)` (alias) | **accent used as foreground text** — the on-surface, AA-safe one |
|
|
15
17
|
| `--accent-soft` | `--accent` at 10% / 14% over transparent | tinted fills |
|
|
16
18
|
| `--bg-accent` | `--accent` at 6% / 8% | faint accent backgrounds |
|
|
@@ -49,6 +51,14 @@ fills — follows automatically, in both light and dark.
|
|
|
49
51
|
- **Spacing** — override the `--space-2xs … --space-2xl` scale, or use a
|
|
50
52
|
preset: `data-density="compact"` / `data-density="comfortable"` on any
|
|
51
53
|
element (defaults to the middle scale).
|
|
54
|
+
- **Dark surface** — the dark theme's base is a deliberately *elevated*
|
|
55
|
+
near-black (`--bg: #121212`) for readability: pure black + bright text
|
|
56
|
+
causes halation, and near-black-on-black surface steps are imperceptible.
|
|
57
|
+
For OLED power-saving or the original true-black "Nothing" look, opt in with
|
|
58
|
+
`data-surface="oled"` on `:root` (a root-level attribute like `data-theme`).
|
|
59
|
+
It only affects the dark theme and is a CSS-only preset (not in the JS token
|
|
60
|
+
model), so it never blacks out the light theme. See
|
|
61
|
+
[ADR-0003](adr/0003-theme-model.md) for the theme-model rationale.
|
|
52
62
|
- **Radius** — `--radius-sm … --radius-xl`, `--radius-pill`. The Nothing
|
|
53
63
|
default is near-sharp; raise these for a softer brand.
|
|
54
64
|
- **Type** — `--display` (dot-matrix face), `--mono`, `--sans`. Override
|
|
@@ -115,7 +125,7 @@ is not. The values above are *measured* (white label on `#a8431a` =
|
|
|
115
125
|
the same check. Don't set one global `--accent` and hope — that is why
|
|
116
126
|
this example is split per theme.
|
|
117
127
|
|
|
118
|
-
## Token tiers
|
|
128
|
+
## Token tiers
|
|
119
129
|
|
|
120
130
|
Three additive, non-breaking tiers sit on top of the primitives. The
|
|
121
131
|
short legacy names (`--panel`, `--line`, `--accent`, …) keep working
|
|
@@ -131,9 +141,11 @@ coarser-grained handles.
|
|
|
131
141
|
primitives, so light/dark still Just Works.
|
|
132
142
|
- **Accent ramp — `--accent-1 … --accent-6`.** A stepped family
|
|
133
143
|
(subtle → bold) derived from the single `--accent` knob via
|
|
134
|
-
`color-mix` against
|
|
135
|
-
|
|
136
|
-
surfaces
|
|
144
|
+
`color-mix(in oklch, …)` against a per-theme white/black endpoint
|
|
145
|
+
(`--accent-ramp-end`). Re-brands and theme-adapts automatically. Steps
|
|
146
|
+
1–4 are subtle surfaces; steps 5–6 are the accent and strong accent.
|
|
147
|
+
Exact hex outputs are visual tuning, but the token names and roles are
|
|
148
|
+
stable.
|
|
137
149
|
- **Neutral ramp — `--surface-1 … --surface-6`** (low → high contrast
|
|
138
150
|
against `--bg`) for layered surfaces without hand-picking greys.
|
|
139
151
|
- **Stacking scale — `--z-base / -raised / -sticky / -overlay /
|
package/docs/usage.md
CHANGED
|
@@ -60,6 +60,22 @@ Rule of thumb: state → dot, classification → badge, user-controlled value
|
|
|
60
60
|
`.ui-card` itself, so card padding/border stays the card's and prose
|
|
61
61
|
rhythm stays the content's. One responsibility per element.
|
|
62
62
|
|
|
63
|
+
## Static reports
|
|
64
|
+
|
|
65
|
+
Use the opt-in `@ponchia/ui/css/report.css` layer for static, PDF-first
|
|
66
|
+
reports. A report composes `ui-report` + existing primitives: `ui-statgrid`
|
|
67
|
+
for KPIs, `ui-alert` for persistent notices, `ui-table` for evidence,
|
|
68
|
+
`ui-timeline` for events, `ui-meter` for measured values, and `ui-prose` only
|
|
69
|
+
for narrative body content you do not fully control.
|
|
70
|
+
|
|
71
|
+
Do not turn every report block into a card. Use `ui-report__summary`,
|
|
72
|
+
`ui-report__finding`, and `ui-report__evidence` for document structure; use
|
|
73
|
+
`ui-card` only when the block is genuinely a repeated card item. Charts use
|
|
74
|
+
the report `ui-chart*` wrappers plus the opt-in data-viz tokens; simple static
|
|
75
|
+
bar charts can use `ui-chart__plot`, `ui-chart__bar`, and `ui-chart__fill`.
|
|
76
|
+
Always include a caption and fallback data. Full LLM/static report cookbook:
|
|
77
|
+
[reporting.md](reporting.md).
|
|
78
|
+
|
|
63
79
|
## Buttons: variant and size
|
|
64
80
|
|
|
65
81
|
- **primary** — the single most important action in a view. Aim for one.
|
|
@@ -148,12 +164,14 @@ infinite-clone track). It's a gallery: the user drives it.
|
|
|
148
164
|
|
|
149
165
|
## Display glyphs: when (and when not)
|
|
150
166
|
|
|
151
|
-
`@ponchia/ui/glyphs` is a
|
|
167
|
+
`@ponchia/ui/glyphs` is a 48-glyph dot-matrix icon set — navigation
|
|
152
168
|
(`arrow-*`, `chevron-*`), actions (`check`, `close`, `plus`, `minus`,
|
|
153
169
|
`search`, `menu`, `gear`), status (`info`, `warning`, `bell`, `lock`) and
|
|
154
|
-
common marks (`home`, `user`, `heart`, `star`, `spark
|
|
170
|
+
common marks (`home`, `user`, `heart`, `star`, `spark`, circle-family marks) — rendered on the
|
|
155
171
|
`.ui-dotmatrix` primitive, so they re-skin with the same `--field-dot*`
|
|
156
|
-
tokens as every other dot surface
|
|
172
|
+
tokens as every other dot surface. The default and `solid` renderers emit
|
|
173
|
+
dot-matrix DOM, not an icon font; the dense `.ui-icon` renderer uses an
|
|
174
|
+
internal SVG data URL as a CSS mask so it can stay one DOM node.
|
|
157
175
|
|
|
158
176
|
**Two rendering modes — pick by size.** The dots need physical room to
|
|
159
177
|
read, so the default _dot_ look is for **display** sizes (~40px up: hero
|