@misoto22/design 0.3.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.
Files changed (266) hide show
  1. package/README.md +124 -0
  2. package/bin/misoto22-design.mjs +205 -0
  3. package/dist/agent/Accordion.md +41 -0
  4. package/dist/agent/Alert.md +42 -0
  5. package/dist/agent/AppShell.md +40 -0
  6. package/dist/agent/AreaChart.md +68 -0
  7. package/dist/agent/Article.md +41 -0
  8. package/dist/agent/Avatar.md +32 -0
  9. package/dist/agent/Badge.md +40 -0
  10. package/dist/agent/BarChart.md +65 -0
  11. package/dist/agent/BarList.md +40 -0
  12. package/dist/agent/BigNumber.md +45 -0
  13. package/dist/agent/BoxPlot.md +58 -0
  14. package/dist/agent/Breadcrumb.md +32 -0
  15. package/dist/agent/BulletChart.md +48 -0
  16. package/dist/agent/Button.md +56 -0
  17. package/dist/agent/Calendar.md +42 -0
  18. package/dist/agent/Card.md +49 -0
  19. package/dist/agent/Checkbox.md +35 -0
  20. package/dist/agent/Collapsible.md +46 -0
  21. package/dist/agent/Combobox.md +50 -0
  22. package/dist/agent/Command.md +93 -0
  23. package/dist/agent/ComposedChart.md +57 -0
  24. package/dist/agent/ContextMenu.md +59 -0
  25. package/dist/agent/DatePicker.md +75 -0
  26. package/dist/agent/Diagram.md +46 -0
  27. package/dist/agent/Dialog.md +52 -0
  28. package/dist/agent/DropdownMenu.md +70 -0
  29. package/dist/agent/EmptyState.md +37 -0
  30. package/dist/agent/ErrorState.md +41 -0
  31. package/dist/agent/Facet.md +82 -0
  32. package/dist/agent/Field.md +37 -0
  33. package/dist/agent/FigureBand.md +37 -0
  34. package/dist/agent/FloatingIconButton.md +38 -0
  35. package/dist/agent/FunnelChart.md +52 -0
  36. package/dist/agent/Heatmap.md +53 -0
  37. package/dist/agent/Histogram.md +63 -0
  38. package/dist/agent/Input.md +30 -0
  39. package/dist/agent/Kbd.md +29 -0
  40. package/dist/agent/LineChart.md +60 -0
  41. package/dist/agent/LinkArrow.md +29 -0
  42. package/dist/agent/NativeSelect.md +40 -0
  43. package/dist/agent/NavItem.md +35 -0
  44. package/dist/agent/Pagination.md +43 -0
  45. package/dist/agent/PieChart.md +55 -0
  46. package/dist/agent/Popover.md +57 -0
  47. package/dist/agent/Progress.md +33 -0
  48. package/dist/agent/RadarChart.md +54 -0
  49. package/dist/agent/RadialChart.md +57 -0
  50. package/dist/agent/RadioGroup.md +44 -0
  51. package/dist/agent/SankeyChart.md +61 -0
  52. package/dist/agent/ScatterChart.md +54 -0
  53. package/dist/agent/ScrollArea.md +40 -0
  54. package/dist/agent/SearchableMenu.md +46 -0
  55. package/dist/agent/Select.md +75 -0
  56. package/dist/agent/Separator.md +35 -0
  57. package/dist/agent/Sheet.md +57 -0
  58. package/dist/agent/Skeleton.md +73 -0
  59. package/dist/agent/Slider.md +39 -0
  60. package/dist/agent/Sparkline.md +45 -0
  61. package/dist/agent/Spinner.md +39 -0
  62. package/dist/agent/StatusDot.md +36 -0
  63. package/dist/agent/StatusPill.md +28 -0
  64. package/dist/agent/Steps.md +44 -0
  65. package/dist/agent/Switch.md +29 -0
  66. package/dist/agent/Table.md +85 -0
  67. package/dist/agent/Tabs.md +48 -0
  68. package/dist/agent/Tag.md +35 -0
  69. package/dist/agent/Textarea.md +26 -0
  70. package/dist/agent/Toast.md +26 -0
  71. package/dist/agent/ToggleGroup.md +44 -0
  72. package/dist/agent/Tooltip.md +51 -0
  73. package/dist/agent/TreemapChart.md +52 -0
  74. package/dist/agent/WaterfallChart.md +62 -0
  75. package/dist/agent/catalog.json +1791 -0
  76. package/dist/agent/index.md +131 -0
  77. package/dist/article.css +393 -0
  78. package/dist/charts/AreaChart/AreaChart.d.ts +191 -0
  79. package/dist/charts/AreaChart/AreaChart.js +480 -0
  80. package/dist/charts/AreaChart/AreaChart.js.map +1 -0
  81. package/dist/charts/BarChart/BarChart.d.ts +179 -0
  82. package/dist/charts/BarChart/BarChart.js +591 -0
  83. package/dist/charts/BarChart/BarChart.js.map +1 -0
  84. package/dist/charts/BarList/BarList.d.ts +57 -0
  85. package/dist/charts/BarList/BarList.js +71 -0
  86. package/dist/charts/BarList/BarList.js.map +1 -0
  87. package/dist/charts/BigNumber/BigNumber.d.ts +56 -0
  88. package/dist/charts/BigNumber/BigNumber.js +31 -0
  89. package/dist/charts/BigNumber/BigNumber.js.map +1 -0
  90. package/dist/charts/BoxPlot/BoxPlot.d.ts +177 -0
  91. package/dist/charts/BoxPlot/BoxPlot.js +495 -0
  92. package/dist/charts/BoxPlot/BoxPlot.js.map +1 -0
  93. package/dist/charts/BulletChart/BulletChart.d.ts +100 -0
  94. package/dist/charts/BulletChart/BulletChart.js +162 -0
  95. package/dist/charts/BulletChart/BulletChart.js.map +1 -0
  96. package/dist/charts/ComposedChart/ComposedChart.d.ts +171 -0
  97. package/dist/charts/ComposedChart/ComposedChart.js +667 -0
  98. package/dist/charts/ComposedChart/ComposedChart.js.map +1 -0
  99. package/dist/charts/Facet/Facet.d.ts +240 -0
  100. package/dist/charts/Facet/Facet.js +133 -0
  101. package/dist/charts/Facet/Facet.js.map +1 -0
  102. package/dist/charts/Facet/panels.d.ts +187 -0
  103. package/dist/charts/Facet/panels.js +203 -0
  104. package/dist/charts/Facet/panels.js.map +1 -0
  105. package/dist/charts/FunnelChart/FunnelChart.d.ts +101 -0
  106. package/dist/charts/FunnelChart/FunnelChart.js +147 -0
  107. package/dist/charts/FunnelChart/FunnelChart.js.map +1 -0
  108. package/dist/charts/Heatmap/Heatmap.d.ts +78 -0
  109. package/dist/charts/Heatmap/Heatmap.js +108 -0
  110. package/dist/charts/Heatmap/Heatmap.js.map +1 -0
  111. package/dist/charts/Histogram/Histogram.d.ts +165 -0
  112. package/dist/charts/Histogram/Histogram.js +350 -0
  113. package/dist/charts/Histogram/Histogram.js.map +1 -0
  114. package/dist/charts/LineChart/LineChart.d.ts +167 -0
  115. package/dist/charts/LineChart/LineChart.js +486 -0
  116. package/dist/charts/LineChart/LineChart.js.map +1 -0
  117. package/dist/charts/PieChart/PieChart.d.ts +128 -0
  118. package/dist/charts/PieChart/PieChart.js +309 -0
  119. package/dist/charts/PieChart/PieChart.js.map +1 -0
  120. package/dist/charts/RadarChart/RadarChart.d.ts +123 -0
  121. package/dist/charts/RadarChart/RadarChart.js +299 -0
  122. package/dist/charts/RadarChart/RadarChart.js.map +1 -0
  123. package/dist/charts/RadialChart/RadialChart.d.ts +124 -0
  124. package/dist/charts/RadialChart/RadialChart.js +257 -0
  125. package/dist/charts/RadialChart/RadialChart.js.map +1 -0
  126. package/dist/charts/SankeyChart/SankeyChart.d.ts +137 -0
  127. package/dist/charts/SankeyChart/SankeyChart.js +501 -0
  128. package/dist/charts/SankeyChart/SankeyChart.js.map +1 -0
  129. package/dist/charts/ScatterChart/ScatterChart.d.ts +128 -0
  130. package/dist/charts/ScatterChart/ScatterChart.js +269 -0
  131. package/dist/charts/ScatterChart/ScatterChart.js.map +1 -0
  132. package/dist/charts/Sparkline/Sparkline.d.ts +53 -0
  133. package/dist/charts/Sparkline/Sparkline.js +93 -0
  134. package/dist/charts/Sparkline/Sparkline.js.map +1 -0
  135. package/dist/charts/TreemapChart/TreemapChart.d.ts +93 -0
  136. package/dist/charts/TreemapChart/TreemapChart.js +118 -0
  137. package/dist/charts/TreemapChart/TreemapChart.js.map +1 -0
  138. package/dist/charts/WaterfallChart/WaterfallChart.d.ts +164 -0
  139. package/dist/charts/WaterfallChart/WaterfallChart.js +319 -0
  140. package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -0
  141. package/dist/charts/index.d.ts +41 -0
  142. package/dist/charts/index.js +128 -0
  143. package/dist/charts/index.js.map +1 -0
  144. package/dist/charts/lib/annotations.d.ts +103 -0
  145. package/dist/charts/lib/annotations.js +99 -0
  146. package/dist/charts/lib/annotations.js.map +1 -0
  147. package/dist/charts/lib/axis.d.ts +18 -0
  148. package/dist/charts/lib/axis.js +21 -0
  149. package/dist/charts/lib/axis.js.map +1 -0
  150. package/dist/charts/lib/background.d.ts +33 -0
  151. package/dist/charts/lib/background.js +173 -0
  152. package/dist/charts/lib/background.js.map +1 -0
  153. package/dist/charts/lib/brush.d.ts +94 -0
  154. package/dist/charts/lib/brush.js +535 -0
  155. package/dist/charts/lib/brush.js.map +1 -0
  156. package/dist/charts/lib/chart.d.ts +94 -0
  157. package/dist/charts/lib/chart.js +134 -0
  158. package/dist/charts/lib/chart.js.map +1 -0
  159. package/dist/charts/lib/dot.d.ts +29 -0
  160. package/dist/charts/lib/dot.js +78 -0
  161. package/dist/charts/lib/dot.js.map +1 -0
  162. package/dist/charts/lib/empty.d.ts +31 -0
  163. package/dist/charts/lib/empty.js +13 -0
  164. package/dist/charts/lib/empty.js.map +1 -0
  165. package/dist/charts/lib/export.d.ts +103 -0
  166. package/dist/charts/lib/export.js +204 -0
  167. package/dist/charts/lib/export.js.map +1 -0
  168. package/dist/charts/lib/figure.d.ts +61 -0
  169. package/dist/charts/lib/figure.js +59 -0
  170. package/dist/charts/lib/figure.js.map +1 -0
  171. package/dist/charts/lib/format.d.ts +46 -0
  172. package/dist/charts/lib/format.js +56 -0
  173. package/dist/charts/lib/format.js.map +1 -0
  174. package/dist/charts/lib/legend.d.ts +45 -0
  175. package/dist/charts/lib/legend.js +117 -0
  176. package/dist/charts/lib/legend.js.map +1 -0
  177. package/dist/charts/lib/loading.d.ts +48 -0
  178. package/dist/charts/lib/loading.js +105 -0
  179. package/dist/charts/lib/loading.js.map +1 -0
  180. package/dist/charts/lib/paint.d.ts +154 -0
  181. package/dist/charts/lib/paint.js +551 -0
  182. package/dist/charts/lib/paint.js.map +1 -0
  183. package/dist/charts/lib/sonify-control.d.ts +163 -0
  184. package/dist/charts/lib/sonify-control.js +172 -0
  185. package/dist/charts/lib/sonify-control.js.map +1 -0
  186. package/dist/charts/lib/sonify.d.ts +248 -0
  187. package/dist/charts/lib/sonify.js +262 -0
  188. package/dist/charts/lib/sonify.js.map +1 -0
  189. package/dist/charts/lib/toolbar.d.ts +143 -0
  190. package/dist/charts/lib/toolbar.js +156 -0
  191. package/dist/charts/lib/toolbar.js.map +1 -0
  192. package/dist/charts/lib/tooltip.d.ts +59 -0
  193. package/dist/charts/lib/tooltip.js +135 -0
  194. package/dist/charts/lib/tooltip.js.map +1 -0
  195. package/dist/charts/lib/values.d.ts +56 -0
  196. package/dist/charts/lib/values.js +71 -0
  197. package/dist/charts/lib/values.js.map +1 -0
  198. package/dist/charts/lib/zoom.d.ts +139 -0
  199. package/dist/charts/lib/zoom.js +314 -0
  200. package/dist/charts/lib/zoom.js.map +1 -0
  201. package/dist/components/AppShell/AppShell.d.ts +15 -1
  202. package/dist/components/AppShell/AppShell.js +8 -4
  203. package/dist/components/AppShell/AppShell.js.map +1 -1
  204. package/dist/components/Article/Article.d.ts +51 -0
  205. package/dist/components/Article/Article.js +21 -0
  206. package/dist/components/Article/Article.js.map +1 -0
  207. package/dist/components/Button/Button.js +2 -2
  208. package/dist/components/Button/Button.js.map +1 -1
  209. package/dist/components/Calendar/Calendar.d.ts +1 -1
  210. package/dist/components/Calendar/Calendar.js +259 -24
  211. package/dist/components/Calendar/Calendar.js.map +1 -1
  212. package/dist/components/Checkbox/Checkbox.js +1 -1
  213. package/dist/components/Checkbox/Checkbox.js.map +1 -1
  214. package/dist/components/Collapsible/Collapsible.d.ts +15 -1
  215. package/dist/components/Collapsible/Collapsible.js +18 -0
  216. package/dist/components/Collapsible/Collapsible.js.map +1 -1
  217. package/dist/components/Combobox/Combobox.js +1 -1
  218. package/dist/components/Combobox/Combobox.js.map +1 -1
  219. package/dist/components/Command/Command.js +7 -7
  220. package/dist/components/Command/Command.js.map +1 -1
  221. package/dist/components/ContextMenu/ContextMenu.js +2 -2
  222. package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
  223. package/dist/components/Diagram/Diagram.d.ts +81 -0
  224. package/dist/components/Diagram/Diagram.js +139 -0
  225. package/dist/components/Diagram/Diagram.js.map +1 -0
  226. package/dist/components/Dialog/Dialog.js +1 -1
  227. package/dist/components/Dialog/Dialog.js.map +1 -1
  228. package/dist/components/DropdownMenu/DropdownMenu.js +2 -2
  229. package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
  230. package/dist/components/FigureBand/FigureBand.js +41 -30
  231. package/dist/components/FigureBand/FigureBand.js.map +1 -1
  232. package/dist/components/Popover/Popover.js +1 -1
  233. package/dist/components/Popover/Popover.js.map +1 -1
  234. package/dist/components/Select/Select.js +2 -2
  235. package/dist/components/Select/Select.js.map +1 -1
  236. package/dist/components/Sheet/Sheet.js +1 -1
  237. package/dist/components/Sheet/Sheet.js.map +1 -1
  238. package/dist/components/Slider/Slider.js +1 -1
  239. package/dist/components/Slider/Slider.js.map +1 -1
  240. package/dist/components/Steps/Steps.d.ts +65 -0
  241. package/dist/components/Steps/Steps.js +55 -0
  242. package/dist/components/Steps/Steps.js.map +1 -0
  243. package/dist/components/Switch/Switch.js +1 -1
  244. package/dist/components/Switch/Switch.js.map +1 -1
  245. package/dist/components/Tooltip/Tooltip.js +1 -1
  246. package/dist/components/Tooltip/Tooltip.js.map +1 -1
  247. package/dist/index.d.ts +4 -1
  248. package/dist/index.js +3 -0
  249. package/dist/index.js.map +1 -1
  250. package/dist/lib/useSelectionIndicator.js +14 -10
  251. package/dist/lib/useSelectionIndicator.js.map +1 -1
  252. package/dist/semantic.css +19 -0
  253. package/dist/styles.css +1 -1
  254. package/dist/themes.css +103 -7
  255. package/dist/tokens.css +193 -10
  256. package/dist/tokens.d.ts +25 -0
  257. package/dist/tokens.js +154 -8
  258. package/dist/tokens.json +154 -8
  259. package/package.json +45 -20
  260. package/skills/misoto22-design/SKILL.md +171 -0
  261. package/skills/misoto22-design/evals/claims.json +95 -0
  262. package/skills/misoto22-design/rules/a11y.md +115 -0
  263. package/skills/misoto22-design/rules/composition.md +108 -0
  264. package/skills/misoto22-design/rules/forms.md +128 -0
  265. package/skills/misoto22-design/rules/naming.md +155 -0
  266. package/skills/misoto22-design/rules/tokens.md +131 -0
package/dist/tokens.css CHANGED
@@ -76,6 +76,59 @@
76
76
 
77
77
  --shadow-offset: var(--clay);
78
78
 
79
+ /* ─── Data ───────────────────────────────────────────────────────────────
80
+ The series ramp a chart paints with, and the one place the White Reset
81
+ has to answer a question a monochrome system would rather not be asked:
82
+ how do you tell six lines apart with no hue left to spend?
83
+
84
+ The answer is that hue was never the primary carrier here — TEXTURE is.
85
+ Every chart primitive ships a fill variant (hatched, dotted, lines,
86
+ stripped, duotone) and the series ramp below is the SECOND encoding, not
87
+ the first. That ordering is what makes the set legible to a colour-blind
88
+ reader, in greyscale print, and under forced-colours, none of which a
89
+ hue-first categorical palette survives.
90
+
91
+ The eight steps are interleaved rather than sequential — light, dark,
92
+ light, dark — so neighbouring series sit as far apart on the lightness
93
+ ramp as eight steps allow. Adjacent separation is ΔE 21.0 (OKLab ×100)
94
+ against a 15 floor, and every step clears 3:1 on its own ground.
95
+
96
+ Two checks a chromatic palette would pass fail here BY DESIGN, and are
97
+ stated rather than hidden: the chroma floor (these are greys) and the
98
+ lightness band (--series-1 is ink, and ink is the darkest mark the system
99
+ has). Texture plus a legend is the relief, and both are mandatory —
100
+ `Chart.Legend` is not optional above one series.
101
+
102
+ A consumer who genuinely needs hue does not hand-pick hexes: it sets
103
+ `data-chart-palette="chroma"` (see themes.css), which re-points these
104
+ eight names onto a categorical palette validated against both grounds. */
105
+ --series-1: #101010;
106
+ --series-2: #565656;
107
+ --series-3: #202020;
108
+ --series-4: #6a6a6a;
109
+ --series-5: #313131;
110
+ --series-6: #7e7e7e;
111
+ --series-7: #434343;
112
+ --series-8: #939393;
113
+ /* The empty ground a part-of-whole mark is drawn against — the unfilled
114
+ remainder of a radial bar, the track behind a gauge. Not --rule: a track
115
+ is a field, and a field that reads as a hairline disappears at radius. */
116
+ --series-track: #eeece7;
117
+
118
+ /* How solid a translucent mark is, and the one pair of tokens in the file
119
+ that is NOT the same number on both grounds.
120
+
121
+ A wash is `ink at N% over the page`. On paper, ink at 14% lands around
122
+ #e3e3e3 — a legible, recessive band. Run the same 14% the other way and
123
+ paper-white over near-black lands around #2c2c2c, which on a #0d0d0d
124
+ ground is not a band, it is nothing. Perceived lightness is not linear and
125
+ the two directions do not meet in the middle, so a single number cannot
126
+ serve both: the dark side needs roughly twice the alpha to read as the
127
+ same weight of mark. Every area fill, texture and flow band in the chart
128
+ package reads these rather than carrying its own literal. */
129
+ --chart-fill: 0.14;
130
+ --chart-texture: 0.42;
131
+
79
132
  color-scheme: light;
80
133
  }
81
134
 
@@ -117,6 +170,19 @@
117
170
 
118
171
  --shadow-offset: var(--clay);
119
172
 
173
+ --series-1: #f4f4f2;
174
+ --series-2: #9b9b9b;
175
+ --series-3: #dddddd;
176
+ --series-4: #868686;
177
+ --series-5: #c7c7c7;
178
+ --series-6: #727272;
179
+ --series-7: #b0b0b0;
180
+ --series-8: #636363;
181
+ --series-track: #232323;
182
+
183
+ --chart-fill: 0.3;
184
+ --chart-texture: 0.72;
185
+
120
186
  color-scheme: dark;
121
187
  }
122
188
 
@@ -201,17 +267,62 @@
201
267
  --sec-tight: clamp(40px, calc(5 * var(--fluid)), 68px);
202
268
  }
203
269
 
204
- :root {
205
- /* ─── Radius ─────────────────────────────────────────────────────────────
206
- Four steps, and there is no fifth. The old law was "0 everywhere"; the
207
- White Reset replaces that with a scale small enough to stay quiet on a
208
- white page. A 50% circle is geometry rather than a corner and is not a
209
- step here. */
210
- --radius-sm: 6px; /* images, thumbnails, media frames */
211
- --radius: 8px; /* inputs, buttons, small plates */
212
- --radius-lg: 14px; /* feature panels, dark plates */
213
- --radius-pill: 999px; /* tabs, chips, counters, circular controls */
270
+ /* ─── Radius ───────────────────────────────────────────────────────────────
271
+ One ladder, and a single factor that moves the whole of it.
272
+
273
+ The four steps used to be four independent numbers, and a radius theme
274
+ re-typed all four. That is how the ladder went out of proportion with
275
+ itself: nothing held the steps in a fixed ratio, so a corner nested inside
276
+ another corner matched it at the one setting somebody checked and at no
277
+ other. Here the steps are derived, the factor is the only thing a theme
278
+ sets, and the proportions are the same at every setting by construction.
279
+
280
+ THE NESTING LAW. Two rounded edges separated by a gap of `p` are concentric
281
+ only when the inner radius is the outer minus `p`. Anything else pinches at
282
+ the corner — the gap narrows as it turns, which is the mismatch you see
283
+ before you can name it. Both directions are named below (`--radius-row`
284
+ subtracts, `--radius-frame` adds) so a surface never has to guess.
285
+
286
+ THE PILL IS ON THE LADDER, which is a change. It used to be exempt, on the
287
+ grounds that a pill is a shape rather than a corner. It is — but a square
288
+ theme that left every button a capsule was not a square theme, and that
289
+ exemption is what bought it. A true CIRCLE is still geometry and still
290
+ `rounded-full`: an avatar, a status dot, a spinner, a radio (which is round
291
+ so it cannot be mistaken for a checkbox).
292
+
293
+ Declared for `:root` AND for `[data-radius]`, rather than composed once and
294
+ inherited. A custom property substitutes `var()` where it is DECLARED, so a
295
+ ladder written only on `:root` bakes in the root's factor and a themed
296
+ subtree deeper in the page never reaches it — the same trap `--fluid` above
297
+ documents, and the reason five themes can share the themes page at all. */
298
+ :root,
299
+ [data-radius] {
300
+ --radius-factor: 1;
301
+ /* Clamps the factor at 1 for the ADDING direction only. A frame's air is a
302
+ fixed number of pixels, so `--radius-lg + 16px` would leave a rounded
303
+ frame around a square panel the moment the theme went square; gated, it
304
+ collapses to nothing along with everything else. */
305
+ --radius-gate: min(1, var(--radius-factor));
306
+
307
+ /* The numbers are the ones the rest of the industry settled on, and that is
308
+ the argument for them: 8px for a control, 12px for a panel, and 4/6 for the
309
+ small marks inside one. Tailwind's own scale, shadcn's `--radius` ± 2 and
310
+ ± 4, Radix Themes' steps 3 and 4, and Material's `xs`/`sm`/`md` all agree
311
+ within a pixel of this. The previous 2/4/6/10 was a step tighter than any
312
+ of them, which is what made a card read as a rectangle with the corners
313
+ shaved rather than as a rounded panel. */
314
+ --radius-xs: calc(4px * var(--radius-factor)); /* a mark inside a tight box */
315
+ --radius-sm: calc(6px * var(--radius-factor)); /* chips, keys, list rows */
316
+ --radius: calc(8px * var(--radius-factor)); /* inputs, code, small plates */
317
+ --radius-lg: calc(12px * var(--radius-factor)); /* cards, dialogs, menu panels */
318
+ --radius-pill: calc(999px * var(--radius-factor)); /* capsules and counters */
319
+
320
+ /* The nesting law, applied to the two insets this system actually uses. */
321
+ --radius-row: max(0px, calc(var(--radius-lg) - 0.375rem)); /* a row in a 6px-padded panel */
322
+ --radius-frame: calc(var(--radius-lg) + 1rem * var(--radius-gate)); /* a frame 16px outside a panel */
323
+ }
214
324
 
325
+ :root {
215
326
  /* ─── Density ────────────────────────────────────────────────────────────
216
327
  The second theming axis, and the only other one. Light/dark swaps colour;
217
328
  density swaps the size of anything a finger or a pointer has to hit.
@@ -254,6 +365,26 @@
254
365
  declaration is dropped and every column loses its gutter in silence. */
255
366
  --table-pad-x: 0px;
256
367
 
368
+ /* ─── Floating surfaces ──────────────────────────────────────────────────
369
+ What a panel that FLOATS fills with, and what it does to whatever is
370
+ behind it. A dialog, a menu, a popover, a palette — the surfaces that sit
371
+ OVER the page rather than in it, and therefore the only ones with anything
372
+ behind them to treat.
373
+
374
+ Both default to the plain surface and cost nothing. `--panel-filter: none`
375
+ matters more than it looks: a `backdrop-filter` of any value, `blur(0px)`
376
+ included, promotes its element to its own compositing layer and makes it a
377
+ containing block for fixed descendants. Paid on every menu in the system,
378
+ for a theme most readers will never turn on. `none` is not a blur of zero;
379
+ it is no filter at all.
380
+
381
+ A card is deliberately NOT on this list. It sits on the page ground, so
382
+ there is nothing behind it to see through, and a card that blurs its own
383
+ background is drawing an effect rather than an object. */
384
+ --panel-bg: var(--paper);
385
+ --panel-border: var(--rule-2);
386
+ --panel-filter: none;
387
+
257
388
  /* ─── Motion ─── */
258
389
  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
259
390
  --fast: 0.13s;
@@ -321,3 +452,55 @@
321
452
  [data-table-density='compact'] {
322
453
  --table-pad-y: 0.5rem;
323
454
  }
455
+
456
+ /* ==========================================================================
457
+ FORCED COLOURS
458
+ --------------------------------------------------------------------------
459
+ What a chart does when the reader has taken the palette away.
460
+
461
+ Windows High Contrast (and any forced-colours mode) remaps CSS colours to a
462
+ small set of system keywords. It does that for HTML automatically — a
463
+ tooltip's border and ground are handled without us — but it does NOT reach
464
+ inside SVG: Chrome and Edge ship `forced-color-adjust: none` on SVG by
465
+ default, and a gradient paint server is not something a browser can remap
466
+ even where it tries. So a chart that says nothing here keeps painting its
467
+ greys onto a black ground, and the reader's setting is quietly ignored.
468
+
469
+ The eight-step ramp collapses to one colour, because forced-colours has one
470
+ colour to give. That would be fatal to a system where hue carried identity,
471
+ and is survivable here for the reason the ramp is second in the first place:
472
+ TEXTURE is the primary encoding, and a hatch is still a hatch when every
473
+ series is CanvasText. This block is where that design decision gets cashed.
474
+
475
+ Scoped to the chart tokens on purpose. Restyling every component's rules and
476
+ surfaces from here would be a system-wide change wearing a chart fix.
477
+ ========================================================================== */
478
+
479
+ @media (forced-colors: active) {
480
+ :root,
481
+ [data-mode='light'],
482
+ [data-mode='dark'] {
483
+ --series-1: CanvasText;
484
+ --series-2: CanvasText;
485
+ --series-3: CanvasText;
486
+ --series-4: CanvasText;
487
+ --series-5: CanvasText;
488
+ --series-6: CanvasText;
489
+ --series-7: CanvasText;
490
+ --series-8: CanvasText;
491
+ --series-track: Canvas;
492
+
493
+ --chart-surface: Canvas;
494
+ --chart-grid: GrayText;
495
+ --chart-cursor: CanvasText;
496
+ --chart-axis: CanvasText;
497
+ --chart-track: Canvas;
498
+ --chart-pattern: GrayText;
499
+
500
+ /* Textures go to full strength — they are now the only thing separating
501
+ one series from another. The wash stays under half so two overlapping
502
+ areas still read as two. */
503
+ --chart-fill: 0.45;
504
+ --chart-texture: 1;
505
+ }
506
+ }
package/dist/tokens.d.ts CHANGED
@@ -27,6 +27,14 @@ export type TokenName =
27
27
  | 'border-subtle'
28
28
  | 'brand-plate'
29
29
  | 'card-background'
30
+ | 'chart-axis'
31
+ | 'chart-cursor'
32
+ | 'chart-fill'
33
+ | 'chart-grid'
34
+ | 'chart-pattern'
35
+ | 'chart-surface'
36
+ | 'chart-texture'
37
+ | 'chart-track'
30
38
  | 'cjk-sans'
31
39
  | 'cjk-serif'
32
40
  | 'clay'
@@ -98,15 +106,23 @@ export type TokenName =
98
106
  | 'overlay'
99
107
  | 'pad'
100
108
  | 'page-pad'
109
+ | 'panel-bg'
110
+ | 'panel-border'
111
+ | 'panel-filter'
101
112
  | 'paper'
102
113
  | 'paper-2'
103
114
  | 'photo-caption-surface'
104
115
  | 'photo-scrim'
105
116
  | 'photo-shadow'
106
117
  | 'radius'
118
+ | 'radius-factor'
119
+ | 'radius-frame'
120
+ | 'radius-gate'
107
121
  | 'radius-lg'
108
122
  | 'radius-pill'
123
+ | 'radius-row'
109
124
  | 'radius-sm'
125
+ | 'radius-xs'
110
126
  | 'red'
111
127
  | 'red-ink'
112
128
  | 'red-soft'
@@ -122,6 +138,15 @@ export type TokenName =
122
138
  | 'sec'
123
139
  | 'sec-tight'
124
140
  | 'secondary-text'
141
+ | 'series-1'
142
+ | 'series-2'
143
+ | 'series-3'
144
+ | 'series-4'
145
+ | 'series-5'
146
+ | 'series-6'
147
+ | 'series-7'
148
+ | 'series-8'
149
+ | 'series-track'
125
150
  | 'serif'
126
151
  | 'shadow'
127
152
  | 'shadow-color'
package/dist/tokens.js CHANGED
@@ -168,6 +168,75 @@ export const TOKENS = {
168
168
  "light": "var(--clay)",
169
169
  "dark": "var(--clay)"
170
170
  },
171
+ "series-1": {
172
+ "layer": "tokens",
173
+ "category": "data",
174
+ "light": "#101010",
175
+ "comment": "─── Data ─────────────────────────────────────────────────────────────── The series ramp a chart paints with, and the one place the White Reset has to answer a question a monochrome system would rather not be asked: how do you tell six lines apart with no hue left to spend? The answer is that hue was never the primary carrier here — TEXTURE is. Every chart primitive ships a fill variant (hatched, dotted, lines, stripped, duotone) and the series ramp below is the SECOND encoding, not the first. That ordering is what makes the set legible to a colour-blind reader, in greyscale print, and under forced-colours, none of which a hue-first categorical palette survives. The eight steps are interleaved rather than sequential — light, dark, light, dark — so neighbouring series sit as far apart on the lightness ramp as eight steps allow. Adjacent separation is ΔE 21.0 (OKLab ×100) against a 15 floor, and every step clears 3:1 on its own ground. Two checks a chromatic palette would pass fail here BY DESIGN, and are stated rather than hidden: the chroma floor (these are greys) and the lightness band (--series-1 is ink, and ink is the darkest mark the system has). Texture plus a legend is the relief, and both are mandatory — `Chart.Legend` is not optional above one series. A consumer who genuinely needs hue does not hand-pick hexes: it sets `data-chart-palette=\"chroma\"` (see themes.css), which re-points these eight names onto a categorical palette validated against both grounds.",
176
+ "dark": "CanvasText"
177
+ },
178
+ "series-2": {
179
+ "layer": "tokens",
180
+ "category": "data",
181
+ "light": "#565656",
182
+ "dark": "CanvasText"
183
+ },
184
+ "series-3": {
185
+ "layer": "tokens",
186
+ "category": "data",
187
+ "light": "#202020",
188
+ "dark": "CanvasText"
189
+ },
190
+ "series-4": {
191
+ "layer": "tokens",
192
+ "category": "data",
193
+ "light": "#6a6a6a",
194
+ "dark": "CanvasText"
195
+ },
196
+ "series-5": {
197
+ "layer": "tokens",
198
+ "category": "data",
199
+ "light": "#313131",
200
+ "dark": "CanvasText"
201
+ },
202
+ "series-6": {
203
+ "layer": "tokens",
204
+ "category": "data",
205
+ "light": "#7e7e7e",
206
+ "dark": "CanvasText"
207
+ },
208
+ "series-7": {
209
+ "layer": "tokens",
210
+ "category": "data",
211
+ "light": "#434343",
212
+ "dark": "CanvasText"
213
+ },
214
+ "series-8": {
215
+ "layer": "tokens",
216
+ "category": "data",
217
+ "light": "#939393",
218
+ "dark": "CanvasText"
219
+ },
220
+ "series-track": {
221
+ "layer": "tokens",
222
+ "category": "data",
223
+ "light": "#eeece7",
224
+ "comment": "The empty ground a part-of-whole mark is drawn against — the unfilled remainder of a radial bar, the track behind a gauge. Not --rule: a track is a field, and a field that reads as a hairline disappears at radius.",
225
+ "dark": "Canvas"
226
+ },
227
+ "chart-fill": {
228
+ "layer": "tokens",
229
+ "category": "data",
230
+ "light": "0.14",
231
+ "comment": "How solid a translucent mark is, and the one pair of tokens in the file that is NOT the same number on both grounds. A wash is `ink at N% over the page`. On paper, ink at 14% lands around #e3e3e3 — a legible, recessive band. Run the same 14% the other way and paper-white over near-black lands around #2c2c2c, which on a #0d0d0d ground is not a band, it is nothing. Perceived lightness is not linear and the two directions do not meet in the middle, so a single number cannot serve both: the dark side needs roughly twice the alpha to read as the same weight of mark. Every area fill, texture and flow band in the chart package reads these rather than carrying its own literal.",
232
+ "dark": "0.45"
233
+ },
234
+ "chart-texture": {
235
+ "layer": "tokens",
236
+ "category": "data",
237
+ "light": "0.42",
238
+ "dark": "1"
239
+ },
171
240
  "sans": {
172
241
  "layer": "tokens",
173
242
  "category": "type",
@@ -270,29 +339,58 @@ export const TOKENS = {
270
339
  "category": "space",
271
340
  "light": "clamp(40px, calc(5 * var(--fluid)), 68px)"
272
341
  },
342
+ "radius-factor": {
343
+ "layer": "tokens",
344
+ "category": "radius",
345
+ "light": "1"
346
+ },
347
+ "radius-gate": {
348
+ "layer": "tokens",
349
+ "category": "radius",
350
+ "light": "min(1, var(--radius-factor))",
351
+ "comment": "Clamps the factor at 1 for the ADDING direction only. A frame's air is a fixed number of pixels, so `--radius-lg + 16px` would leave a rounded frame around a square panel the moment the theme went square; gated, it collapses to nothing along with everything else."
352
+ },
353
+ "radius-xs": {
354
+ "layer": "tokens",
355
+ "category": "radius",
356
+ "light": "calc(4px * var(--radius-factor))",
357
+ "comment": "The numbers are the ones the rest of the industry settled on, and that is the argument for them: 8px for a control, 12px for a panel, and 4/6 for the small marks inside one. Tailwind's own scale, shadcn's `--radius` ± 2 and ± 4, Radix Themes' steps 3 and 4, and Material's `xs`/`sm`/`md` all agree within a pixel of this. The previous 2/4/6/10 was a step tighter than any of them, which is what made a card read as a rectangle with the corners shaved rather than as a rounded panel."
358
+ },
273
359
  "radius-sm": {
274
360
  "layer": "tokens",
275
361
  "category": "radius",
276
- "light": "6px",
277
- "comment": "─── Radius ───────────────────────────────────────────────────────────── Four steps, and there is no fifth. The old law was \"0 everywhere\"; the White Reset replaces that with a scale small enough to stay quiet on a white page. A 50% circle is geometry rather than a corner and is not a step here."
362
+ "light": "calc(6px * var(--radius-factor))",
363
+ "comment": "a mark inside a tight box"
278
364
  },
279
365
  "radius": {
280
366
  "layer": "tokens",
281
367
  "category": "radius",
282
- "light": "8px",
283
- "comment": "images, thumbnails, media frames"
368
+ "light": "calc(8px * var(--radius-factor))",
369
+ "comment": "chips, keys, list rows"
284
370
  },
285
371
  "radius-lg": {
286
372
  "layer": "tokens",
287
373
  "category": "radius",
288
- "light": "14px",
289
- "comment": "inputs, buttons, small plates"
374
+ "light": "calc(12px * var(--radius-factor))",
375
+ "comment": "inputs, code, small plates"
290
376
  },
291
377
  "radius-pill": {
292
378
  "layer": "tokens",
293
379
  "category": "radius",
294
- "light": "999px",
295
- "comment": "feature panels, dark plates"
380
+ "light": "calc(999px * var(--radius-factor))",
381
+ "comment": "cards, dialogs, menu panels"
382
+ },
383
+ "radius-row": {
384
+ "layer": "tokens",
385
+ "category": "radius",
386
+ "light": "max(0px, calc(var(--radius-lg) - 0.375rem))",
387
+ "comment": "The nesting law, applied to the two insets this system actually uses."
388
+ },
389
+ "radius-frame": {
390
+ "layer": "tokens",
391
+ "category": "radius",
392
+ "light": "calc(var(--radius-lg) + 1rem * var(--radius-gate))",
393
+ "comment": "a row in a 6px-padded panel"
296
394
  },
297
395
  "control-h-sm": {
298
396
  "layer": "tokens",
@@ -368,6 +466,22 @@ export const TOKENS = {
368
466
  "light": "0px",
369
467
  "comment": "`0px`, not `0`. The cell rule adds to this inside a calc, and a unitless zero makes `calc(0 + 1.5rem)` invalid at computed-value time — the whole declaration is dropped and every column loses its gutter in silence."
370
468
  },
469
+ "panel-bg": {
470
+ "layer": "tokens",
471
+ "category": "other",
472
+ "light": "var(--paper)",
473
+ "comment": "─── Floating surfaces ────────────────────────────────────────────────── What a panel that FLOATS fills with, and what it does to whatever is behind it. A dialog, a menu, a popover, a palette — the surfaces that sit OVER the page rather than in it, and therefore the only ones with anything behind them to treat. Both default to the plain surface and cost nothing. `--panel-filter: none` matters more than it looks: a `backdrop-filter` of any value, `blur(0px)` included, promotes its element to its own compositing layer and makes it a containing block for fixed descendants. Paid on every menu in the system, for a theme most readers will never turn on. `none` is not a blur of zero; it is no filter at all. A card is deliberately NOT on this list. It sits on the page ground, so there is nothing behind it to see through, and a card that blurs its own background is drawing an effect rather than an object."
474
+ },
475
+ "panel-border": {
476
+ "layer": "tokens",
477
+ "category": "other",
478
+ "light": "var(--rule-2)"
479
+ },
480
+ "panel-filter": {
481
+ "layer": "tokens",
482
+ "category": "other",
483
+ "light": "none"
484
+ },
371
485
  "ease": {
372
486
  "layer": "tokens",
373
487
  "category": "motion",
@@ -650,6 +764,38 @@ export const TOKENS = {
650
764
  "light": "#101010",
651
765
  "comment": "The photo scrim is always dark by design, so it takes the ink literal rather than the semantic token (which inverts)."
652
766
  },
767
+ "chart-surface": {
768
+ "layer": "semantic",
769
+ "category": "data",
770
+ "light": "var(--paper)",
771
+ "comment": "─── Data ───────────────────────────────────────────────────────────── What a chart is allowed to read. The series ramp itself stays a primitive — a chart names a SERIES by index, and an index has no role to alias — but everything around the marks does have one, and naming it here is what keeps a chart from reaching for --rule or --ink directly. --chart-cursor is deliberately heavier than --chart-grid: the crosshair has to be findable against the grid it crosses, and at hairline weight on a dashed grid it was not."
772
+ },
773
+ "chart-grid": {
774
+ "layer": "semantic",
775
+ "category": "data",
776
+ "light": "var(--rule)"
777
+ },
778
+ "chart-cursor": {
779
+ "layer": "semantic",
780
+ "category": "data",
781
+ "light": "var(--rule-2)"
782
+ },
783
+ "chart-axis": {
784
+ "layer": "semantic",
785
+ "category": "data",
786
+ "light": "var(--ink-3-aa)"
787
+ },
788
+ "chart-track": {
789
+ "layer": "semantic",
790
+ "category": "data",
791
+ "light": "var(--series-track)"
792
+ },
793
+ "chart-pattern": {
794
+ "layer": "semantic",
795
+ "category": "data",
796
+ "light": "var(--rule)",
797
+ "comment": "The decorative plate behind the plot — a dot field, a hatch, a grid of plus marks. One step quieter than the grid, because it sits BEHIND data and must never compete with it for the same read."
798
+ },
653
799
  "shadow-color": {
654
800
  "layer": "semantic",
655
801
  "category": "depth",