@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.
Files changed (196) hide show
  1. package/CHANGELOG.md +386 -4
  2. package/MIGRATIONS.json +14 -0
  3. package/README.md +29 -6
  4. package/annotations/index.d.ts +398 -276
  5. package/annotations/index.d.ts.map +1 -0
  6. package/annotations/index.js +350 -77
  7. package/behaviors/carousel.d.ts +28 -0
  8. package/behaviors/carousel.d.ts.map +1 -0
  9. package/behaviors/carousel.js +20 -16
  10. package/behaviors/combobox.d.ts +40 -0
  11. package/behaviors/combobox.d.ts.map +1 -0
  12. package/behaviors/combobox.js +111 -29
  13. package/behaviors/command.d.ts +41 -0
  14. package/behaviors/command.d.ts.map +1 -0
  15. package/behaviors/command.js +27 -15
  16. package/behaviors/connectors.d.ts +17 -0
  17. package/behaviors/connectors.d.ts.map +1 -0
  18. package/behaviors/connectors.js +7 -5
  19. package/behaviors/crosshair.d.ts +42 -0
  20. package/behaviors/crosshair.d.ts.map +1 -0
  21. package/behaviors/crosshair.js +23 -6
  22. package/behaviors/dialog.d.ts +20 -0
  23. package/behaviors/dialog.d.ts.map +1 -0
  24. package/behaviors/dialog.js +6 -2
  25. package/behaviors/disclosure.d.ts +10 -0
  26. package/behaviors/disclosure.d.ts.map +1 -0
  27. package/behaviors/disclosure.js +6 -2
  28. package/behaviors/dismissible.d.ts +10 -0
  29. package/behaviors/dismissible.d.ts.map +1 -0
  30. package/behaviors/dismissible.js +6 -2
  31. package/behaviors/forms.d.ts +27 -0
  32. package/behaviors/forms.d.ts.map +1 -0
  33. package/behaviors/forms.js +54 -13
  34. package/behaviors/glyph.d.ts +14 -0
  35. package/behaviors/glyph.d.ts.map +1 -0
  36. package/behaviors/glyph.js +28 -5
  37. package/behaviors/index.d.ts +31 -237
  38. package/behaviors/index.d.ts.map +1 -0
  39. package/behaviors/index.js +17 -0
  40. package/behaviors/inert.d.ts +20 -0
  41. package/behaviors/inert.d.ts.map +1 -0
  42. package/behaviors/inert.js +46 -0
  43. package/behaviors/internal.d.ts +25 -0
  44. package/behaviors/internal.d.ts.map +1 -0
  45. package/behaviors/internal.js +77 -1
  46. package/behaviors/legend.d.ts +35 -0
  47. package/behaviors/legend.d.ts.map +1 -0
  48. package/behaviors/legend.js +32 -2
  49. package/behaviors/menu.d.ts +16 -0
  50. package/behaviors/menu.d.ts.map +1 -0
  51. package/behaviors/menu.js +6 -2
  52. package/behaviors/modal.d.ts +41 -0
  53. package/behaviors/modal.d.ts.map +1 -0
  54. package/behaviors/modal.js +124 -0
  55. package/behaviors/popover.d.ts +28 -0
  56. package/behaviors/popover.d.ts.map +1 -0
  57. package/behaviors/popover.js +78 -7
  58. package/behaviors/spotlight.d.ts +17 -0
  59. package/behaviors/spotlight.d.ts.map +1 -0
  60. package/behaviors/spotlight.js +7 -5
  61. package/behaviors/table.d.ts +36 -0
  62. package/behaviors/table.d.ts.map +1 -0
  63. package/behaviors/table.js +84 -17
  64. package/behaviors/tabs.d.ts +20 -0
  65. package/behaviors/tabs.d.ts.map +1 -0
  66. package/behaviors/tabs.js +17 -14
  67. package/behaviors/theme.d.ts +54 -0
  68. package/behaviors/theme.d.ts.map +1 -0
  69. package/behaviors/theme.js +22 -3
  70. package/behaviors/toast.d.ts +49 -0
  71. package/behaviors/toast.d.ts.map +1 -0
  72. package/behaviors/toast.js +47 -3
  73. package/classes/classes.json +2527 -0
  74. package/classes/index.d.ts +134 -15
  75. package/classes/index.js +280 -80
  76. package/classes/vscode.css-custom-data.json +12 -0
  77. package/connectors/index.d.ts +201 -69
  78. package/connectors/index.d.ts.map +1 -0
  79. package/connectors/index.js +142 -25
  80. package/css/app.css +69 -13
  81. package/css/base.css +15 -10
  82. package/css/bullet.css +108 -0
  83. package/css/code.css +98 -0
  84. package/css/connectors.css +17 -0
  85. package/css/content.css +22 -3
  86. package/css/crosshair.css +7 -7
  87. package/css/dataviz.css +5 -1
  88. package/css/diff.css +153 -0
  89. package/css/disclosure.css +53 -7
  90. package/css/dots.css +94 -7
  91. package/css/feedback.css +97 -7
  92. package/css/forms.css +113 -4
  93. package/css/legend.css +16 -9
  94. package/css/marks.css +38 -8
  95. package/css/motion.css +98 -53
  96. package/css/navigation.css +7 -0
  97. package/css/overlay.css +90 -3
  98. package/css/primitives.css +158 -13
  99. package/css/report.css +73 -56
  100. package/css/sidenote.css +67 -0
  101. package/css/site.css +16 -2
  102. package/css/sources.css +43 -1
  103. package/css/spark.css +62 -0
  104. package/css/spotlight.css +1 -1
  105. package/css/table.css +9 -2
  106. package/css/term.css +110 -0
  107. package/css/textref.css +63 -0
  108. package/css/toc.css +91 -0
  109. package/css/tokens.css +49 -1
  110. package/css/tree.css +134 -0
  111. package/css/workbench.css +1 -1
  112. package/dist/bronto.css +1 -1
  113. package/dist/css/analytical.css +1 -1
  114. package/dist/css/app.css +1 -1
  115. package/dist/css/base.css +1 -1
  116. package/dist/css/bullet.css +1 -0
  117. package/dist/css/code.css +1 -0
  118. package/dist/css/connectors.css +1 -1
  119. package/dist/css/content.css +1 -1
  120. package/dist/css/crosshair.css +1 -1
  121. package/dist/css/diff.css +1 -0
  122. package/dist/css/disclosure.css +1 -1
  123. package/dist/css/dots.css +1 -1
  124. package/dist/css/feedback.css +1 -1
  125. package/dist/css/forms.css +1 -1
  126. package/dist/css/legend.css +1 -1
  127. package/dist/css/marks.css +1 -1
  128. package/dist/css/motion.css +1 -1
  129. package/dist/css/navigation.css +1 -1
  130. package/dist/css/overlay.css +1 -1
  131. package/dist/css/primitives.css +1 -1
  132. package/dist/css/report.css +1 -1
  133. package/dist/css/sidenote.css +1 -0
  134. package/dist/css/site.css +1 -1
  135. package/dist/css/sources.css +1 -1
  136. package/dist/css/spark.css +1 -0
  137. package/dist/css/spotlight.css +1 -1
  138. package/dist/css/table.css +1 -1
  139. package/dist/css/term.css +1 -0
  140. package/dist/css/textref.css +1 -0
  141. package/dist/css/toc.css +1 -0
  142. package/dist/css/tokens.css +1 -1
  143. package/dist/css/tree.css +1 -0
  144. package/dist/css/workbench.css +1 -1
  145. package/docs/adr/0003-theme-model.md +1 -1
  146. package/docs/annotations.md +133 -14
  147. package/docs/architecture.md +49 -6
  148. package/docs/bullet.md +78 -0
  149. package/docs/code.md +76 -0
  150. package/docs/contrast.md +116 -92
  151. package/docs/d2.md +196 -0
  152. package/docs/diff.md +146 -0
  153. package/docs/legends.md +23 -3
  154. package/docs/marks.md +9 -2
  155. package/docs/mermaid.md +169 -0
  156. package/docs/reference.md +201 -26
  157. package/docs/reporting.md +416 -57
  158. package/docs/sidenote.md +64 -0
  159. package/docs/sources.md +27 -0
  160. package/docs/spark.md +78 -0
  161. package/docs/stability.md +10 -2
  162. package/docs/term.md +81 -0
  163. package/docs/textref.md +78 -0
  164. package/docs/theming.md +44 -5
  165. package/docs/toc.md +83 -0
  166. package/docs/tree.md +74 -0
  167. package/docs/usage.md +354 -16
  168. package/docs/vega.md +244 -0
  169. package/docs/workbench.md +7 -1
  170. package/glyphs/glyphs.js +13 -5
  171. package/llms.txt +285 -14
  172. package/package.json +95 -17
  173. package/qwik/index.d.ts +44 -59
  174. package/qwik/index.d.ts.map +1 -0
  175. package/qwik/index.js +65 -3
  176. package/react/index.d.ts +41 -61
  177. package/react/index.d.ts.map +1 -0
  178. package/react/index.js +63 -3
  179. package/solid/index.d.ts +68 -61
  180. package/solid/index.d.ts.map +1 -0
  181. package/solid/index.js +66 -3
  182. package/tokens/d2.d.ts +38 -0
  183. package/tokens/d2.js +71 -0
  184. package/tokens/d2.json +43 -0
  185. package/tokens/index.d.ts +5 -5
  186. package/tokens/index.js +15 -1
  187. package/tokens/index.json +9 -0
  188. package/tokens/mermaid.d.ts +23 -0
  189. package/tokens/mermaid.js +181 -0
  190. package/tokens/mermaid.json +163 -0
  191. package/tokens/resolved.json +45 -1
  192. package/tokens/skins.js +3 -2
  193. package/tokens/tokens.dtcg.json +26 -0
  194. package/tokens/vega.d.ts +34 -0
  195. package/tokens/vega.js +155 -0
  196. package/tokens/vega.json +179 -0
package/css/spark.css ADDED
@@ -0,0 +1,62 @@
1
+ /* ==========================================================================
2
+ spark — opt-in inline datawords (word-sized microcharts).
3
+
4
+ A trend-in-a-sentence for generated reports and dense tables — the inline
5
+ counterpart to the scalar `ui-delta` / `ui-num` / `ui-stat`. Pure CSS, no
6
+ measurement, SSR-static, print-survivable. Not imported by core.css.
7
+
8
+ Boundary: the HOST normalises each point to 0..1 and sets it as `--v` on a
9
+ `.ui-spark__bar`; Bronto only paints the geometry. It refuses raw values and
10
+ min/max/scale computation. A bare spark is opaque to assistive tech, so the
11
+ container MUST carry a host-written `role="img"` + `aria-label` text
12
+ equivalent (e.g. "weekly signups, trending up"). Colour is never the only
13
+ channel — pair it with that label.
14
+ ========================================================================== */
15
+
16
+ .ui-spark {
17
+ align-items: flex-end;
18
+ block-size: 1em;
19
+ display: inline-flex;
20
+ gap: 1px;
21
+ inline-size: max-content;
22
+ vertical-align: -0.15em;
23
+ }
24
+
25
+ .ui-spark__bar {
26
+ background: currentColor;
27
+ block-size: max(1px, calc(var(--v, 0) * 100%));
28
+ border-radius: 0.5px;
29
+ flex: 0 0 0.25em;
30
+ min-inline-size: 2px;
31
+ }
32
+
33
+ /* Emphasise / tone a single bar — the rationed accent or a status tone. The
34
+ meaning still has to be in the aria-label (WCAG 1.4.1). */
35
+ .ui-spark__bar--accent {
36
+ background: var(--accent);
37
+ }
38
+
39
+ .ui-spark__bar--pos {
40
+ background: var(--success);
41
+ }
42
+
43
+ .ui-spark__bar--neg {
44
+ background: var(--danger);
45
+ }
46
+
47
+ /* Forced colours would force the bar backgrounds to the system surface and the
48
+ chart would vanish — repaint the bars in the system text colour so the shape
49
+ survives (the tone distinction is carried by the required aria-label). */
50
+ @media (forced-colors: active) {
51
+ .ui-spark__bar {
52
+ background: CanvasText;
53
+ }
54
+ }
55
+
56
+ /* Print: the bars are currentColor fills the print economy would drop. */
57
+ @media print {
58
+ .ui-spark__bar {
59
+ -webkit-print-color-adjust: exact;
60
+ print-color-adjust: exact;
61
+ }
62
+ }
package/css/spotlight.css CHANGED
@@ -66,7 +66,7 @@
66
66
  color: var(--text);
67
67
  display: grid;
68
68
  gap: var(--space-sm);
69
- max-inline-size: 22rem;
69
+ max-inline-size: min(22rem, calc(100vw - 2rem));
70
70
  padding: var(--space-md);
71
71
  pointer-events: auto;
72
72
  }
package/css/table.css CHANGED
@@ -35,6 +35,11 @@
35
35
  position: sticky;
36
36
  text-transform: uppercase;
37
37
  inset-block-start: 0;
38
+
39
+ /* Keep the sticky header above body cells — cheap insurance for the
40
+ sticky-header + pinned/positioned-column combo, where an un-z-indexed th
41
+ scrolls under a positioned cell. (audit C30.) */
42
+ z-index: 1;
38
43
  }
39
44
 
40
45
  .ui-table td {
@@ -154,8 +159,10 @@
154
159
  padding: var(--space-sm) var(--space-md);
155
160
  }
156
161
 
157
- /* --- Loading state: set aria-busy + .ui-table--loading on the wrap --- */
158
- .ui-table--loading {
162
+ /* --- Loading state: set aria-busy + .ui-table-wrap--loading on the wrap. The
163
+ modifier is named for the element it goes ON (the wrap), not `.ui-table`, so
164
+ the BEM host matches the documented placement. (component audit C19.) --- */
165
+ .ui-table-wrap--loading {
159
166
  opacity: 0.6;
160
167
  pointer-events: none;
161
168
  }
package/css/term.css ADDED
@@ -0,0 +1,110 @@
1
+ /* ==========================================================================
2
+ term — opt-in inline glossary term + definition, and an end-of-report glossary.
3
+
4
+ The accessible upgrade of the famously touch/keyboard-broken `abbr[title]`: a
5
+ dotted-underline term whose definition lives in real, reachable DOM via the
6
+ native `[popover]` + `popovertarget` pairing, plus a `ui-glossary` `<dl>` block
7
+ that collects every term at the end of a document. Jargon that explains itself
8
+ inline and gathers into a reference — dead-centre on the explanation pillar.
9
+ Pure CSS over native popover, no kernel. Not imported by core.css.
10
+
11
+ Boundary: the HOST owns the wiring. The term is a `<button class="ui-term"
12
+ popovertarget="…">`; the definition is `<div class="ui-def" popover id="…">`.
13
+ That native pairing gives keyboard + touch + light-dismiss for free — no JS.
14
+ The glossary is a plain `<dl>`; the printed document leans on it because
15
+ popovers don't print (see docs/term.md). Anchor positioning is a gated
16
+ enhancement; without it the definition opens centred in the top layer.
17
+ ========================================================================== */
18
+
19
+ /* The inline term marker — a real <button> so it is keyboard- and touch-
20
+ reachable (the abbr[title] failure). Reset to inline text, keep a dotted
21
+ underline as the "has a definition" cue. */
22
+ .ui-term {
23
+ background: none;
24
+ border: 0;
25
+ color: inherit;
26
+ cursor: help;
27
+ font: inherit;
28
+ padding: 0;
29
+ text-decoration: underline;
30
+ text-decoration-color: var(--line-strong);
31
+ text-decoration-style: dotted;
32
+ text-underline-offset: 0.2em;
33
+ }
34
+
35
+ @media (hover: hover) {
36
+ .ui-term:hover {
37
+ text-decoration-color: var(--accent);
38
+ }
39
+ }
40
+
41
+ .ui-term:focus-visible {
42
+ outline: 2px solid var(--focus-ring);
43
+ outline-offset: 2px;
44
+ }
45
+
46
+ /* The definition — a native popover. Reset the UA popover chrome to the Bronto
47
+ raised-surface card. */
48
+ .ui-def {
49
+ background: var(--surface-raised);
50
+ border: 1px solid var(--line);
51
+ border-radius: var(--radius-md);
52
+ box-shadow: var(--shadow-raised);
53
+ color: var(--text);
54
+ font-family: var(--sans);
55
+ font-size: var(--text-sm);
56
+ line-height: 1.5;
57
+ margin: 0;
58
+ max-inline-size: 22rem;
59
+ padding: var(--space-sm) var(--space-md);
60
+ }
61
+
62
+ /* Progressive enhancement: anchor the definition to its term where CSS anchor
63
+ positioning exists, so it opens beside the word and flips at the viewport
64
+ edge. The host sets the matching `anchor-name` on the term (see docs). Without
65
+ support the popover keeps its centred top-layer fallback. */
66
+ @supports (anchor-name: --x) {
67
+ .ui-def {
68
+ inset: auto;
69
+ margin-block-start: 0.4rem;
70
+ position-area: block-end span-inline-end;
71
+ position-try-fallbacks: flip-block, flip-inline;
72
+ }
73
+ }
74
+
75
+ /* --- Glossary — the end-of-document <dl> the terms collect into. --- */
76
+
77
+ .ui-glossary {
78
+ border-block-start: 1px solid var(--line);
79
+ display: grid;
80
+ gap: var(--space-2xs) var(--space-md);
81
+ grid-template-columns: minmax(6rem, max-content) 1fr;
82
+ margin: 0;
83
+ padding-block-start: var(--space-md);
84
+ }
85
+
86
+ .ui-glossary__term {
87
+ color: var(--text);
88
+ font-family: var(--mono);
89
+ font-size: var(--text-xs);
90
+ font-weight: 600;
91
+ letter-spacing: var(--tracking-wide);
92
+ }
93
+
94
+ .ui-glossary__def {
95
+ color: var(--text-dim);
96
+ font-size: var(--text-sm);
97
+ margin: 0;
98
+ }
99
+
100
+ /* Narrow viewports: stack each term over its definition. */
101
+ @media (max-width: 32rem) {
102
+ .ui-glossary {
103
+ grid-template-columns: 1fr;
104
+ gap: 0.15rem var(--space-md);
105
+ }
106
+
107
+ .ui-glossary__def {
108
+ margin-block-end: var(--space-xs);
109
+ }
110
+ }
@@ -0,0 +1,63 @@
1
+ /* ==========================================================================
2
+ textref — opt-in deep-link-to-the-cited-sentence provenance primitive.
3
+
4
+ A citation that jumps to the EXACT quoted text. The link's href is a URL
5
+ Text Fragment (`#…:~:text=`); the browser scrolls to the match and highlights
6
+ it for free, and Bronto owns the on-brand `::target-text` paint. The inline
7
+ counterpart to the static `ui-src` / `ui-citation` trust layer (sources.css),
8
+ which can label a source but not point inside it. Pure CSS + a host-built URL,
9
+ no kernel, SSR-static. Not imported by core.css.
10
+
11
+ Boundary: the HOST builds the fragment URL and sets it as the link's href.
12
+ The encoder is a three-line pure function (see docs/textref.md) — Bronto does
13
+ not ship runtime here, it owns the affordance class + the highlight paint.
14
+ `::target-text` is global by design: any text-fragment landing on the page
15
+ gets the brand highlight once this leaf is imported. On engines without Text
16
+ Fragments the link still navigates to the section; the highlight is additive.
17
+ ========================================================================== */
18
+
19
+ .ui-textref {
20
+ --textref-highlight: var(--accent-soft);
21
+
22
+ color: var(--accent-text);
23
+ text-decoration: underline;
24
+ text-decoration-style: dotted;
25
+ text-underline-offset: 0.2em;
26
+ }
27
+
28
+ /* A small leading caret signals "this jumps to the quoted text", distinct from
29
+ a plain external link. currentColor only — no raw paint. */
30
+ .ui-textref::before {
31
+ content: '\201F'; /* double high-reversed-9 quote — a quote-jump cue */
32
+ margin-inline-end: 0.15em;
33
+ }
34
+
35
+ @media (hover: hover) {
36
+ .ui-textref:hover {
37
+ text-decoration-style: solid;
38
+ }
39
+ }
40
+
41
+ .ui-textref:focus-visible {
42
+ outline: 2px solid var(--focus-ring);
43
+ outline-offset: 2px;
44
+ }
45
+
46
+ /* The browser-painted highlight on the matched fragment. Scoped to the page
47
+ the link lands on; the accent-soft wash is the same rationed-accent surface
48
+ the rest of the trust layer uses. `--textref-highlight` lets a host retune it
49
+ per-surface. */
50
+ ::target-text {
51
+ background-color: var(--textref-highlight, var(--accent-soft));
52
+ color: var(--text);
53
+ }
54
+
55
+ /* Forced colours: the accent wash collapses to the system surface and the match
56
+ would be invisible — repaint with the system selection colours so the jump
57
+ target still reads. */
58
+ @media (forced-colors: active) {
59
+ ::target-text {
60
+ background-color: Highlight;
61
+ color: HighlightText;
62
+ }
63
+ }
package/css/toc.css ADDED
@@ -0,0 +1,91 @@
1
+ /* ==========================================================================
2
+ toc — opt-in scrollspy table-of-contents rail for long reports.
3
+
4
+ A sticky contents list whose entry for the section currently in view is
5
+ highlighted, so a reader of a long generated report always knows where they
6
+ are. Long-document orientation, on the generated-reports pillar. Degrades to a
7
+ plain anchored list with zero JS. Not imported by core.css.
8
+
9
+ Boundary: the HOST owns the section IDs and the anchor list; Bronto owns the
10
+ rail's classes + the active treatment. The active state keys on the standard
11
+ `aria-current="true"` hook. CSS alone cannot know which section is in view, so
12
+ the host mirrors the in-view section onto its link's `aria-current` — either
13
+ statically (server-rendered "current page") or with a small IntersectionObserver
14
+ (~15 lines, copy-paste recipe in docs/toc.md). No Bronto kernel ships for it;
15
+ the rail is fully useful as a static sticky list without the observer.
16
+ ========================================================================== */
17
+
18
+ .ui-toc {
19
+ --toc-top: var(--space-md);
20
+
21
+ align-self: start;
22
+ font-family: var(--mono);
23
+ font-size: var(--text-xs);
24
+ inset-block-start: var(--toc-top);
25
+ letter-spacing: var(--tracking-wide);
26
+ position: sticky;
27
+ }
28
+
29
+ /* An optional eyebrow heading for the rail. */
30
+ .ui-toc__title {
31
+ color: var(--text-dim);
32
+ font-size: var(--text-2xs);
33
+ margin-block-end: var(--space-xs);
34
+ text-transform: uppercase;
35
+ }
36
+
37
+ .ui-toc__list {
38
+ display: grid;
39
+ gap: 1px;
40
+ list-style: none;
41
+ margin: 0;
42
+ padding: 0;
43
+ }
44
+
45
+ /* Nested lists indent for sub-sections. */
46
+ .ui-toc__list .ui-toc__list {
47
+ margin-inline-start: var(--space-sm);
48
+ }
49
+
50
+ .ui-toc__link {
51
+ border-inline-start: 2px solid var(--line);
52
+ color: var(--text-dim);
53
+ display: block;
54
+ padding: 0.3rem var(--space-sm);
55
+ text-decoration: none;
56
+ transition: color var(--duration-fast) var(--ease-standard);
57
+ }
58
+
59
+ /* The section in view. Keys on `aria-current` (the framework rule every other
60
+ nav surface here uses) so a host that sets only aria-current still lights up. */
61
+ .ui-toc__link[aria-current]:not([aria-current='false']) {
62
+ border-inline-start-color: var(--accent);
63
+ color: var(--accent-text);
64
+ }
65
+
66
+ .ui-toc__link:focus-visible {
67
+ outline: 2px solid var(--focus-ring);
68
+ outline-offset: -2px;
69
+ }
70
+
71
+ @media (hover: hover) {
72
+ .ui-toc__link:hover:not([aria-current]:not([aria-current='false'])) {
73
+ color: var(--text);
74
+ }
75
+ }
76
+
77
+ /* Forced colours: the accent border + text collapse to the system surface and
78
+ the active entry loses its only cue — re-assert with the system highlight. */
79
+ @media (forced-colors: active) {
80
+ .ui-toc__link[aria-current]:not([aria-current='false']) {
81
+ border-inline-start-color: Highlight;
82
+ color: Highlight;
83
+ }
84
+ }
85
+
86
+ /* Reduced motion: drop the colour transition. */
87
+ @media (prefers-reduced-motion: reduce) {
88
+ .ui-toc__link {
89
+ transition: none;
90
+ }
91
+ }
package/css/tokens.css CHANGED
@@ -3,7 +3,7 @@
3
3
  Single source of truth: tokens/index.js (`cssVars`). Edit token VALUES
4
4
  there, then run `npm run tokens:css:build`. The four :root blocks below are
5
5
  emitted from cssVars — the dark palette is authored ONCE (not the former two
6
- CSS blocks + the JS mirror). check-tokens.mjs gates this file against cssVars.
6
+ CSS blocks + the JS mirror). Drift-checked by `npm run check:fresh` (scripts/check-fresh.mjs).
7
7
  The Doto @font-face lives in fonts.css; override --display / --dot-font to
8
8
  self-host. CSS-only presets (density / contrast / OLED) are hand-authored
9
9
  below the marker — they are intentionally not part of the JS token model.
@@ -31,6 +31,8 @@
31
31
  --sans: 'Inter', 'SF Pro Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
32
32
  --dot-font: 'Doto', var(--mono);
33
33
  --display: var(--dot-font);
34
+ --display-weight: 700;
35
+ --display-weight-strong: 800;
34
36
  --text-2xs: 0.68rem;
35
37
  --text-xs: 0.76rem;
36
38
  --text-sm: 0.86rem;
@@ -122,6 +124,7 @@
122
124
  --accent-ramp-end: #ffffff;
123
125
  --accent-strong: color-mix(in srgb, var(--accent) 83%, #000);
124
126
  --accent-text: var(--accent-strong);
127
+ --on-accent: var(--button-text);
125
128
  --accent-soft: color-mix(in srgb, var(--accent) 10%, transparent);
126
129
  --success: #2f7d4f;
127
130
  --success-soft: rgb(47, 125, 79, 0.12);
@@ -165,6 +168,7 @@
165
168
  --accent-ramp-end: #000000;
166
169
  --accent-strong: color-mix(in srgb, var(--accent) 84%, #fff);
167
170
  --accent-text: var(--accent-strong);
171
+ --on-accent: var(--button-text);
168
172
  --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
169
173
  --success: #4ec27e;
170
174
  --success-soft: rgb(78, 194, 126, 0.14);
@@ -203,6 +207,7 @@
203
207
  --accent-ramp-end: #000000;
204
208
  --accent-strong: color-mix(in srgb, var(--accent) 84%, #fff);
205
209
  --accent-text: var(--accent-strong);
210
+ --on-accent: var(--button-text);
206
211
  --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
207
212
  --success: #4ec27e;
208
213
  --success-soft: rgb(78, 194, 126, 0.14);
@@ -311,3 +316,46 @@
311
316
  --panel-soft: #1a1a1a;
312
317
  }
313
318
  }
319
+
320
+ /* --------------------------------------------------------------------------
321
+ Print — force an ink-on-white document regardless of the on-screen theme.
322
+ The palette tokens are [data-theme]-scoped raw values, so `color-scheme`
323
+ alone can't flip them: re-point the neutrals to achromatic ink/paper and the
324
+ status/accent hues to their light-theme (print-legible) values. This lifts
325
+ the same remap report.css scopes to `.ui-report` up to :root, so a bare
326
+ .ui-card / .ui-statgrid / .ui-table (the markup an external LLM emits) also
327
+ prints dark-on-white instead of light-grey text or a dark panel on white.
328
+ Lives here, in the exempt tier-definition file, because it is a token-value
329
+ override (ADR-0001), not component styling. CSS-only, like the presets above.
330
+
331
+ Selector is `:root:root:root` (specificity 0,3,0), not a bare `:root`: a media
332
+ query adds NO specificity, so a bare `:root` (0,1,0) loses the cascade to the
333
+ on-screen dark palette at `:root[data-theme='dark']` (0,2,0) and the OLED
334
+ surface at `:root[data-theme='dark'][data-surface='oled']` (0,3,0) — i.e. a
335
+ dark-mode user would print a near-black `.ui-card` on white paper, the exact
336
+ opposite of what this block promises. Tripling `:root` matches the OLED rule's
337
+ specificity and wins on source order (this block is last), so the remap also
338
+ beats the `prefers-color-scheme: dark` blocks. Neutralise the OLED-only dark
339
+ surfaces (--bg / --bg-elevated / --panel-strong) too, or they'd leak through.
340
+ -------------------------------------------------------------------------- */
341
+ @media print {
342
+ :root:root:root {
343
+ color-scheme: light;
344
+
345
+ --text: #111;
346
+ --text-soft: #2a2a2a;
347
+ --text-dim: #555;
348
+ --bg: #fff;
349
+ --bg-elevated: #fff;
350
+ --panel: #fff;
351
+ --panel-strong: #fff;
352
+ --panel-soft: #f7f7f7;
353
+ --line: #d9d9d9;
354
+ --line-strong: #b3b3b3;
355
+ --success: #2f7d4f;
356
+ --danger: #c01622;
357
+ --warning: #806414;
358
+ --info: #1f63c4;
359
+ --accent: #d71921;
360
+ }
361
+ }
package/css/tree.css ADDED
@@ -0,0 +1,134 @@
1
+ /* ==========================================================================
2
+ tree — opt-in hierarchy outline on nested native <details name> disclosures.
3
+
4
+ A depth-indented outline for hierarchies: file trees, report contents, nested
5
+ generated-content provenance, object graphs. Built on nested native
6
+ `<details>` (optionally `name` exclusive-accordion groups) so open/close,
7
+ keyboard toggling and animation come from the platform — this leaf is the
8
+ hierarchy LAYER (rails, indent, chevron), it does NOT reinvent the disclosure
9
+ grammar that `ui-accordion` already owns. Pure CSS, SSR-static. Not imported
10
+ by core.css.
11
+
12
+ Boundary: the HOST owns the nesting and the labels. A11y honesty — a native
13
+ `<details>` group is a disclosure group, NOT an ARIA `tree`; do not bolt on
14
+ `role="tree"`/`treeitem` without the roving-focus keyboard model it implies.
15
+ That kernel is intentionally NOT shipped here; it lands behind a real consumer
16
+ (see docs/tree.md). The visuals below work on the full browser floor with zero
17
+ JS.
18
+ ========================================================================== */
19
+
20
+ .ui-tree {
21
+ color: var(--text);
22
+ font-family: var(--mono);
23
+ font-size: var(--text-sm);
24
+ line-height: 1.5;
25
+ }
26
+
27
+ /* A branch is a <details>; a leaf is a plain row with no disclosure. Both are
28
+ rows in the outline. */
29
+ .ui-tree__branch,
30
+ .ui-tree__leaf {
31
+ display: block;
32
+ }
33
+
34
+ /* Nested rows indent and carry a hairline guide rail back to their parent. */
35
+ .ui-tree__branch .ui-tree__branch,
36
+ .ui-tree__branch .ui-tree__leaf {
37
+ border-inline-start: 1px solid var(--line);
38
+ margin-inline-start: 0.5rem;
39
+ padding-inline-start: var(--space-sm);
40
+ }
41
+
42
+ /* The summary is the clickable branch row; reset the native marker, lay it out
43
+ as label + twist. */
44
+ .ui-tree__summary {
45
+ align-items: center;
46
+ cursor: pointer;
47
+ display: flex;
48
+ gap: var(--space-2xs);
49
+ list-style: none;
50
+ padding-block: var(--space-2xs);
51
+ }
52
+
53
+ .ui-tree__summary::-webkit-details-marker {
54
+ display: none;
55
+ }
56
+
57
+ /* Twist chevron — a currentColor caret that rotates open. */
58
+ .ui-tree__summary::before {
59
+ block-size: 0.4rem;
60
+ border-block-end: 1.5px solid var(--text-dim);
61
+ border-inline-end: 1.5px solid var(--text-dim);
62
+ content: '';
63
+ flex: 0 0 auto;
64
+ inline-size: 0.4rem;
65
+ transform: rotate(-45deg);
66
+ transition: transform var(--duration-fast) var(--ease-spring);
67
+ }
68
+
69
+ .ui-tree__branch[open] > .ui-tree__summary::before {
70
+ border-color: var(--accent);
71
+ transform: rotate(45deg);
72
+ }
73
+
74
+ .ui-tree__branch[open] > .ui-tree__summary {
75
+ color: var(--accent-text);
76
+ }
77
+
78
+ /* A leaf has no chevron; align its label with branch labels via a spacer the
79
+ width of the chevron + gap. */
80
+ .ui-tree__leaf {
81
+ align-items: center;
82
+ display: flex;
83
+ gap: var(--space-2xs);
84
+ padding-block: var(--space-2xs);
85
+ }
86
+
87
+ .ui-tree__leaf::before {
88
+ content: '';
89
+ flex: 0 0 auto;
90
+ inline-size: 0.4rem;
91
+ }
92
+
93
+ .ui-tree__label {
94
+ min-inline-size: 0;
95
+ overflow: hidden;
96
+ text-overflow: ellipsis;
97
+ white-space: nowrap;
98
+ }
99
+
100
+ /* Auto-height open/close, gated exactly like ui-accordion (Chrome 131+/Safari
101
+ 18.4+; Firefox snaps). Strict progressive enhancement + reduced-motion. */
102
+ @supports selector(::details-content) {
103
+ @media (prefers-reduced-motion: no-preference) {
104
+ .ui-tree {
105
+ interpolate-size: allow-keywords;
106
+ }
107
+
108
+ .ui-tree__branch::details-content {
109
+ block-size: 0;
110
+ overflow: hidden;
111
+ transition:
112
+ block-size var(--duration-base) var(--ease-out),
113
+ content-visibility var(--duration-base) allow-discrete;
114
+ }
115
+
116
+ .ui-tree__branch[open]::details-content {
117
+ block-size: auto;
118
+ }
119
+ }
120
+ }
121
+
122
+ /* Reduced motion: no chevron spin. */
123
+ @media (prefers-reduced-motion: reduce) {
124
+ .ui-tree__summary::before {
125
+ transition: none;
126
+ }
127
+ }
128
+
129
+ /* Forced colours: keep the open branch distinguishable when accent flattens. */
130
+ @media (forced-colors: active) {
131
+ .ui-tree__branch[open] > .ui-tree__summary::before {
132
+ border-color: Highlight;
133
+ }
134
+ }
package/css/workbench.css CHANGED
@@ -19,7 +19,7 @@
19
19
  padding: var(--space-md);
20
20
  }
21
21
 
22
- .ui-inspector__header {
22
+ .ui-inspector__head {
23
23
  align-items: baseline;
24
24
  border-block-end: 1px solid var(--line);
25
25
  display: flex;