@misoto22/design 0.5.0 → 0.6.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.
Files changed (214) 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 +1863 -0
  76. package/dist/agent/index.md +131 -0
  77. package/dist/charts/AreaChart/AreaChart.d.ts +191 -0
  78. package/dist/charts/AreaChart/AreaChart.js +480 -0
  79. package/dist/charts/AreaChart/AreaChart.js.map +1 -0
  80. package/dist/charts/BarChart/BarChart.d.ts +179 -0
  81. package/dist/charts/BarChart/BarChart.js +591 -0
  82. package/dist/charts/BarChart/BarChart.js.map +1 -0
  83. package/dist/charts/BarList/BarList.d.ts +57 -0
  84. package/dist/charts/BarList/BarList.js +71 -0
  85. package/dist/charts/BarList/BarList.js.map +1 -0
  86. package/dist/charts/BigNumber/BigNumber.d.ts +56 -0
  87. package/dist/charts/BigNumber/BigNumber.js +31 -0
  88. package/dist/charts/BigNumber/BigNumber.js.map +1 -0
  89. package/dist/charts/BoxPlot/BoxPlot.d.ts +177 -0
  90. package/dist/charts/BoxPlot/BoxPlot.js +495 -0
  91. package/dist/charts/BoxPlot/BoxPlot.js.map +1 -0
  92. package/dist/charts/BulletChart/BulletChart.d.ts +100 -0
  93. package/dist/charts/BulletChart/BulletChart.js +162 -0
  94. package/dist/charts/BulletChart/BulletChart.js.map +1 -0
  95. package/dist/charts/ComposedChart/ComposedChart.d.ts +171 -0
  96. package/dist/charts/ComposedChart/ComposedChart.js +667 -0
  97. package/dist/charts/ComposedChart/ComposedChart.js.map +1 -0
  98. package/dist/charts/Facet/Facet.d.ts +240 -0
  99. package/dist/charts/Facet/Facet.js +133 -0
  100. package/dist/charts/Facet/Facet.js.map +1 -0
  101. package/dist/charts/Facet/panels.d.ts +187 -0
  102. package/dist/charts/Facet/panels.js +203 -0
  103. package/dist/charts/Facet/panels.js.map +1 -0
  104. package/dist/charts/FunnelChart/FunnelChart.d.ts +101 -0
  105. package/dist/charts/FunnelChart/FunnelChart.js +147 -0
  106. package/dist/charts/FunnelChart/FunnelChart.js.map +1 -0
  107. package/dist/charts/Heatmap/Heatmap.d.ts +78 -0
  108. package/dist/charts/Heatmap/Heatmap.js +108 -0
  109. package/dist/charts/Heatmap/Heatmap.js.map +1 -0
  110. package/dist/charts/Histogram/Histogram.d.ts +165 -0
  111. package/dist/charts/Histogram/Histogram.js +350 -0
  112. package/dist/charts/Histogram/Histogram.js.map +1 -0
  113. package/dist/charts/LineChart/LineChart.d.ts +167 -0
  114. package/dist/charts/LineChart/LineChart.js +486 -0
  115. package/dist/charts/LineChart/LineChart.js.map +1 -0
  116. package/dist/charts/PieChart/PieChart.d.ts +128 -0
  117. package/dist/charts/PieChart/PieChart.js +309 -0
  118. package/dist/charts/PieChart/PieChart.js.map +1 -0
  119. package/dist/charts/RadarChart/RadarChart.d.ts +123 -0
  120. package/dist/charts/RadarChart/RadarChart.js +299 -0
  121. package/dist/charts/RadarChart/RadarChart.js.map +1 -0
  122. package/dist/charts/RadialChart/RadialChart.d.ts +124 -0
  123. package/dist/charts/RadialChart/RadialChart.js +257 -0
  124. package/dist/charts/RadialChart/RadialChart.js.map +1 -0
  125. package/dist/charts/SankeyChart/SankeyChart.d.ts +137 -0
  126. package/dist/charts/SankeyChart/SankeyChart.js +501 -0
  127. package/dist/charts/SankeyChart/SankeyChart.js.map +1 -0
  128. package/dist/charts/ScatterChart/ScatterChart.d.ts +128 -0
  129. package/dist/charts/ScatterChart/ScatterChart.js +269 -0
  130. package/dist/charts/ScatterChart/ScatterChart.js.map +1 -0
  131. package/dist/charts/Sparkline/Sparkline.d.ts +53 -0
  132. package/dist/charts/Sparkline/Sparkline.js +93 -0
  133. package/dist/charts/Sparkline/Sparkline.js.map +1 -0
  134. package/dist/charts/TreemapChart/TreemapChart.d.ts +93 -0
  135. package/dist/charts/TreemapChart/TreemapChart.js +118 -0
  136. package/dist/charts/TreemapChart/TreemapChart.js.map +1 -0
  137. package/dist/charts/WaterfallChart/WaterfallChart.d.ts +164 -0
  138. package/dist/charts/WaterfallChart/WaterfallChart.js +319 -0
  139. package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -0
  140. package/dist/charts/index.d.ts +41 -0
  141. package/dist/charts/index.js +128 -0
  142. package/dist/charts/index.js.map +1 -0
  143. package/dist/charts/lib/annotations.d.ts +103 -0
  144. package/dist/charts/lib/annotations.js +99 -0
  145. package/dist/charts/lib/annotations.js.map +1 -0
  146. package/dist/charts/lib/axis.d.ts +18 -0
  147. package/dist/charts/lib/axis.js +21 -0
  148. package/dist/charts/lib/axis.js.map +1 -0
  149. package/dist/charts/lib/background.d.ts +33 -0
  150. package/dist/charts/lib/background.js +173 -0
  151. package/dist/charts/lib/background.js.map +1 -0
  152. package/dist/charts/lib/brush.d.ts +94 -0
  153. package/dist/charts/lib/brush.js +535 -0
  154. package/dist/charts/lib/brush.js.map +1 -0
  155. package/dist/charts/lib/chart.d.ts +94 -0
  156. package/dist/charts/lib/chart.js +134 -0
  157. package/dist/charts/lib/chart.js.map +1 -0
  158. package/dist/charts/lib/dot.d.ts +29 -0
  159. package/dist/charts/lib/dot.js +78 -0
  160. package/dist/charts/lib/dot.js.map +1 -0
  161. package/dist/charts/lib/empty.d.ts +31 -0
  162. package/dist/charts/lib/empty.js +13 -0
  163. package/dist/charts/lib/empty.js.map +1 -0
  164. package/dist/charts/lib/export.d.ts +103 -0
  165. package/dist/charts/lib/export.js +204 -0
  166. package/dist/charts/lib/export.js.map +1 -0
  167. package/dist/charts/lib/figure.d.ts +61 -0
  168. package/dist/charts/lib/figure.js +59 -0
  169. package/dist/charts/lib/figure.js.map +1 -0
  170. package/dist/charts/lib/format.d.ts +46 -0
  171. package/dist/charts/lib/format.js +56 -0
  172. package/dist/charts/lib/format.js.map +1 -0
  173. package/dist/charts/lib/legend.d.ts +45 -0
  174. package/dist/charts/lib/legend.js +117 -0
  175. package/dist/charts/lib/legend.js.map +1 -0
  176. package/dist/charts/lib/loading.d.ts +48 -0
  177. package/dist/charts/lib/loading.js +105 -0
  178. package/dist/charts/lib/loading.js.map +1 -0
  179. package/dist/charts/lib/paint.d.ts +154 -0
  180. package/dist/charts/lib/paint.js +551 -0
  181. package/dist/charts/lib/paint.js.map +1 -0
  182. package/dist/charts/lib/sonify-control.d.ts +163 -0
  183. package/dist/charts/lib/sonify-control.js +172 -0
  184. package/dist/charts/lib/sonify-control.js.map +1 -0
  185. package/dist/charts/lib/sonify.d.ts +248 -0
  186. package/dist/charts/lib/sonify.js +262 -0
  187. package/dist/charts/lib/sonify.js.map +1 -0
  188. package/dist/charts/lib/toolbar.d.ts +143 -0
  189. package/dist/charts/lib/toolbar.js +156 -0
  190. package/dist/charts/lib/toolbar.js.map +1 -0
  191. package/dist/charts/lib/tooltip.d.ts +59 -0
  192. package/dist/charts/lib/tooltip.js +135 -0
  193. package/dist/charts/lib/tooltip.js.map +1 -0
  194. package/dist/charts/lib/values.d.ts +56 -0
  195. package/dist/charts/lib/values.js +71 -0
  196. package/dist/charts/lib/values.js.map +1 -0
  197. package/dist/charts/lib/zoom.d.ts +139 -0
  198. package/dist/charts/lib/zoom.js +314 -0
  199. package/dist/charts/lib/zoom.js.map +1 -0
  200. package/dist/semantic.css +19 -0
  201. package/dist/styles.css +1 -1
  202. package/dist/themes.css +50 -0
  203. package/dist/tokens.css +118 -0
  204. package/dist/tokens.d.ts +17 -0
  205. package/dist/tokens.js +101 -0
  206. package/dist/tokens.json +101 -0
  207. package/package.json +26 -4
  208. package/skills/misoto22-design/SKILL.md +209 -0
  209. package/skills/misoto22-design/evals/claims.json +95 -0
  210. package/skills/misoto22-design/rules/a11y.md +115 -0
  211. package/skills/misoto22-design/rules/composition.md +108 -0
  212. package/skills/misoto22-design/rules/forms.md +128 -0
  213. package/skills/misoto22-design/rules/naming.md +155 -0
  214. package/skills/misoto22-design/rules/tokens.md +131 -0
@@ -0,0 +1,1863 @@
1
+ {
2
+ "version": "0.6.1",
3
+ "groups": [
4
+ "Actions",
5
+ "Forms",
6
+ "Navigation",
7
+ "Overlays",
8
+ "Feedback",
9
+ "Display",
10
+ "Surfaces",
11
+ "Data",
12
+ "Charts"
13
+ ],
14
+ "components": [
15
+ {
16
+ "slug": "button",
17
+ "entry": "@misoto22/design",
18
+ "name": "Button",
19
+ "group": "Actions",
20
+ "summary": "The system’s action, on the same corner as the field beside it.",
21
+ "when": "Anything that DOES something. If it navigates and looks like text, it is a link, not a ghost button.",
22
+ "accessibility": [
23
+ "A native <button> by default, so Enter and Space both fire it.",
24
+ "loading sets aria-busy and disables the control; the label stays, so the box does not collapse under the pointer that just clicked it.",
25
+ "A link cannot be disabled, so href + loading sets aria-disabled and blocks pointer events instead.",
26
+ "iconOnly has no text, so it requires aria-label — the single most common way a design system ships an unusable control."
27
+ ],
28
+ "keyboard": [
29
+ {
30
+ "keys": [
31
+ "Enter"
32
+ ],
33
+ "does": "Activates the button."
34
+ },
35
+ {
36
+ "keys": [
37
+ "Space"
38
+ ],
39
+ "does": "Activates the button. A native <button> answers to both; a styled <div> answers to neither."
40
+ }
41
+ ],
42
+ "related": [
43
+ "floating-icon-button",
44
+ "spinner"
45
+ ]
46
+ },
47
+ {
48
+ "slug": "floating-icon-button",
49
+ "entry": "@misoto22/design",
50
+ "name": "FloatingIconButton",
51
+ "group": "Actions",
52
+ "summary": "A round action pinned to a screen corner.",
53
+ "when": "A page-level affordance that must stay reachable while the reader scrolls — back to top, a mobile table of contents.",
54
+ "accessibility": [
55
+ "label is the only name the control has; it is required rather than optional.",
56
+ "44px square, which is the pointer-target floor (WCAG 2.5.8)."
57
+ ],
58
+ "related": [
59
+ "button"
60
+ ]
61
+ },
62
+ {
63
+ "slug": "badge",
64
+ "entry": "@misoto22/design",
65
+ "name": "Badge",
66
+ "group": "Display",
67
+ "summary": "A count or a state, set in mono so it reads as metadata.",
68
+ "when": "One fact about one record. If it names what something is ABOUT, that is a Tag.",
69
+ "accessibility": [
70
+ "Not interactive. A badge with an onClick is a control a keyboard cannot reach.",
71
+ "The status tones double their colour with words, so the meaning survives monochrome and colour-blindness."
72
+ ],
73
+ "related": [
74
+ "tag",
75
+ "status-pill"
76
+ ]
77
+ },
78
+ {
79
+ "slug": "tag",
80
+ "entry": "@misoto22/design",
81
+ "name": "Tag",
82
+ "group": "Display",
83
+ "summary": "A subject label — a topic, a technology, a filter facet.",
84
+ "when": "Several sit together and the reader scans them. One fact about one record is a Badge.",
85
+ "accessibility": [
86
+ "Presentational. To filter with it, wrap it in a button and pass active, so the focus ring and the pressed state stay with the element that owns them."
87
+ ],
88
+ "related": [
89
+ "badge"
90
+ ]
91
+ },
92
+ {
93
+ "slug": "kbd",
94
+ "entry": "@misoto22/design",
95
+ "name": "Kbd",
96
+ "group": "Display",
97
+ "summary": "A key on a keyboard, set as one.",
98
+ "accessibility": [
99
+ "Renders <kbd>, which carries the meaning a styled <span> does not."
100
+ ],
101
+ "related": [
102
+ "badge"
103
+ ]
104
+ },
105
+ {
106
+ "slug": "avatar",
107
+ "entry": "@misoto22/design",
108
+ "name": "Avatar",
109
+ "group": "Display",
110
+ "summary": "A person, as a circle, with initials until the image lands.",
111
+ "accessibility": [
112
+ "alt describes the person, not the picture. An empty string is correct when the name is already printed beside it.",
113
+ "The initials are aria-hidden — read aloud they are noise."
114
+ ]
115
+ },
116
+ {
117
+ "slug": "status-dot",
118
+ "entry": "@misoto22/design",
119
+ "name": "StatusDot",
120
+ "group": "Display",
121
+ "summary": "The dot beside a status word.",
122
+ "accessibility": [
123
+ "aria-hidden without exception: it repeats a state the adjacent label already names.",
124
+ "The halo is motion-safe, so a reader who asked for less motion gets a still dot."
125
+ ],
126
+ "related": [
127
+ "status-pill"
128
+ ]
129
+ },
130
+ {
131
+ "slug": "steps",
132
+ "entry": "@misoto22/design",
133
+ "name": "Steps",
134
+ "group": "Display",
135
+ "summary": "A numbered sequence, as a rail — one thing after another, with a rule through them.",
136
+ "when": "A pipeline, a migration, a recipe: an order with no branches. The moment something forks or points at something else it is a Diagram, and drawing a fork as a list hides it.",
137
+ "accessibility": [
138
+ "An <ol>, because the order IS the content — a stack of divs says nothing about sequence.",
139
+ "aria-current=\"step\" marks the filled one, which is the only thing here a reader could not infer from the reading order.",
140
+ "The markers and the connector are aria-hidden: the number is the list position, and screen readers already announce that."
141
+ ],
142
+ "related": [
143
+ "diagram",
144
+ "article"
145
+ ]
146
+ },
147
+ {
148
+ "slug": "status-pill",
149
+ "entry": "@misoto22/design",
150
+ "name": "StatusPill",
151
+ "group": "Display",
152
+ "summary": "A live state, named: a dot plus an uppercase mono label.",
153
+ "related": [
154
+ "status-dot",
155
+ "badge"
156
+ ]
157
+ },
158
+ {
159
+ "slug": "link-arrow",
160
+ "entry": "@misoto22/design",
161
+ "name": "LinkArrow",
162
+ "group": "Display",
163
+ "summary": "The mark on a link that leaves the page.",
164
+ "accessibility": [
165
+ "aria-hidden, so it is not read as “north east arrow” in the middle of a sentence.",
166
+ "Sized in em, so it tracks whatever type it sits beside instead of competing with it."
167
+ ]
168
+ },
169
+ {
170
+ "slug": "separator",
171
+ "entry": "@misoto22/design",
172
+ "name": "Separator",
173
+ "group": "Display",
174
+ "summary": "A rule, in the three weights a monochrome page needs.",
175
+ "when": "Hairline between rows, edge between blocks, hard under a masthead.",
176
+ "accessibility": [
177
+ "role=\"none\" by default. A rule that only groups things visually must not be announced."
178
+ ]
179
+ },
180
+ {
181
+ "slug": "diagram",
182
+ "entry": "@misoto22/design",
183
+ "name": "Diagram",
184
+ "group": "Display",
185
+ "summary": "A flow or architecture figure, drawn out of the system’s own parts.",
186
+ "when": "A picture of structure, in a page rather than in a terminal. Nesting is containment and an edge is a step between siblings — a diagram that needs arbitrary wiring wants a drawing, not this.",
187
+ "accessibility": [
188
+ "A <figure> with role=\"group\", named by its caption, so the whole picture is one thing a reader can skip.",
189
+ "Arrows are aria-hidden: assistive tech reads the nodes in document order and has no use for a glyph pointing at the next one.",
190
+ "Server-rendered markup, not a canvas — every label is real text a screen reader and a search engine can read."
191
+ ],
192
+ "related": [
193
+ "card",
194
+ "figure-band"
195
+ ]
196
+ },
197
+ {
198
+ "slug": "figure-band",
199
+ "entry": "@misoto22/design",
200
+ "name": "FigureBand",
201
+ "group": "Display",
202
+ "summary": "A row of counted facts, divided by hairlines and nothing else.",
203
+ "accessibility": [
204
+ "A <dl>: each cell is a term and its value, which a grid of divs cannot express."
205
+ ],
206
+ "related": [
207
+ "table"
208
+ ]
209
+ },
210
+ {
211
+ "slug": "spinner",
212
+ "entry": "@misoto22/design",
213
+ "name": "Spinner",
214
+ "group": "Feedback",
215
+ "summary": "The one “working” indicator — a ring, never a shimmer.",
216
+ "when": "A wait short enough that the shape of what is coming does not matter. Longer than that, use a Skeleton.",
217
+ "accessibility": [
218
+ "label names the specific thing being waited on; three spinners all saying “Loading” tell a screen reader nothing.",
219
+ "label={null} silences it for use inside a control that already announces the operation.",
220
+ "Spins under motion-safe only; the static ring still reads as unfinished because the leading quarter is darker."
221
+ ],
222
+ "related": [
223
+ "skeleton",
224
+ "progress"
225
+ ]
226
+ },
227
+ {
228
+ "slug": "skeleton",
229
+ "entry": "@misoto22/design",
230
+ "name": "Skeleton",
231
+ "group": "Feedback",
232
+ "summary": "The shape of the page, before the page.",
233
+ "when": "A wait the reader would otherwise think was a broken page. A shape that describes what is coming beats a dot that describes nothing.",
234
+ "accessibility": [
235
+ "One live region on the wrapper; every shape inside it is aria-hidden.",
236
+ "One pulse on the wrapper, not one per bar, so the page breathes together."
237
+ ],
238
+ "related": [
239
+ "spinner",
240
+ "empty-state"
241
+ ]
242
+ },
243
+ {
244
+ "slug": "progress",
245
+ "entry": "@misoto22/design",
246
+ "name": "Progress",
247
+ "group": "Feedback",
248
+ "summary": "A bar that fills, or sweeps when the end is unknown.",
249
+ "accessibility": [
250
+ "Omitting value drops aria-valuenow, so a screen reader hears “indeterminate” rather than a number that is a guess.",
251
+ "label is required — a bare bar announces nothing."
252
+ ],
253
+ "related": [
254
+ "spinner"
255
+ ]
256
+ },
257
+ {
258
+ "slug": "alert",
259
+ "entry": "@misoto22/design",
260
+ "name": "Alert",
261
+ "group": "Feedback",
262
+ "summary": "A message about the page, in place.",
263
+ "when": "Something the reader needs to see and may need to act on. Something they only need to notice is a Toast.",
264
+ "accessibility": [
265
+ "danger is role=\"alert\" and interrupts; the other three are role=\"status\" and wait for a pause.",
266
+ "Colour is doubled by an icon and by the words."
267
+ ],
268
+ "related": [
269
+ "toast",
270
+ "error-state"
271
+ ]
272
+ },
273
+ {
274
+ "slug": "empty-state",
275
+ "entry": "@misoto22/design",
276
+ "name": "EmptyState",
277
+ "group": "Feedback",
278
+ "summary": "A collection with nothing in it — yet.",
279
+ "when": "Nothing went wrong. The copy says what to do, not what failed.",
280
+ "related": [
281
+ "error-state",
282
+ "skeleton"
283
+ ]
284
+ },
285
+ {
286
+ "slug": "error-state",
287
+ "entry": "@misoto22/design",
288
+ "name": "ErrorState",
289
+ "group": "Feedback",
290
+ "summary": "A page that could not be shown.",
291
+ "accessibility": [
292
+ "The big status code is aria-hidden; the heading immediately after says the same thing in words."
293
+ ],
294
+ "related": [
295
+ "empty-state",
296
+ "alert"
297
+ ]
298
+ },
299
+ {
300
+ "slug": "toast",
301
+ "entry": "@misoto22/design",
302
+ "name": "Toast",
303
+ "group": "Feedback",
304
+ "summary": "A transient confirmation, mounted once near the app root.",
305
+ "when": "Something succeeded and needs no response. A toast is dismissed by time, and time is not an acknowledgement.",
306
+ "related": [
307
+ "alert"
308
+ ]
309
+ },
310
+ {
311
+ "slug": "field",
312
+ "entry": "@misoto22/design",
313
+ "name": "Field",
314
+ "group": "Forms",
315
+ "summary": "A labelled form row: label, control, and the one message below it.",
316
+ "accessibility": [
317
+ "Generates an id when none is given, so the label always points at something.",
318
+ "Wires aria-describedby, aria-required and aria-invalid onto the control, so validation is announced and not merely drawn.",
319
+ "hint and error are one slot: when a field is wrong, the thing to read is what is wrong with it."
320
+ ],
321
+ "related": [
322
+ "input",
323
+ "select"
324
+ ]
325
+ },
326
+ {
327
+ "slug": "input",
328
+ "entry": "@misoto22/design",
329
+ "name": "Input",
330
+ "group": "Forms",
331
+ "summary": "A single line of text entry.",
332
+ "accessibility": [
333
+ "A placeholder is not a label — it disappears the moment anyone types. Pair with Field."
334
+ ],
335
+ "related": [
336
+ "field",
337
+ "textarea"
338
+ ]
339
+ },
340
+ {
341
+ "slug": "textarea",
342
+ "entry": "@misoto22/design",
343
+ "name": "Textarea",
344
+ "group": "Forms",
345
+ "summary": "Multi-line text entry, resizable vertically only.",
346
+ "related": [
347
+ "input",
348
+ "field"
349
+ ]
350
+ },
351
+ {
352
+ "slug": "select",
353
+ "entry": "@misoto22/design",
354
+ "name": "Select",
355
+ "group": "Forms",
356
+ "summary": "A choice from a list, styled the whole way down.",
357
+ "when": "Up to roughly a dozen options. Past that a Combobox wins, because a list nobody can filter is slower to scan than one you can type into.",
358
+ "accessibility": [
359
+ "Inside a bounded frame — a device preview, an embedded console — wrap the subtree in `<OverlayContainer container={el}>`. The panel then renders into that element and collides with its edges instead of the viewport’s, and inherits the `dir` and `data-density` set there.",
360
+ "The option list is ours, so it does not change typeface, spacing and selection colour the moment it opens — which is what a native select does.",
361
+ "The keyboard contract is the platform's: typeahead, arrows, Home and End, Escape to close without choosing.",
362
+ "label is required. The trigger shows a value, and a value is not a name."
363
+ ],
364
+ "keyboard": [
365
+ {
366
+ "keys": [
367
+ "Enter",
368
+ "Space",
369
+ "↓"
370
+ ],
371
+ "does": "Opens the list."
372
+ },
373
+ {
374
+ "keys": [
375
+ "↑",
376
+ "↓"
377
+ ],
378
+ "does": "Moves between options."
379
+ },
380
+ {
381
+ "keys": [
382
+ "a–z"
383
+ ],
384
+ "does": "Typeahead — jumps to the next option starting with that letter."
385
+ },
386
+ {
387
+ "keys": [
388
+ "Home",
389
+ "End"
390
+ ],
391
+ "does": "Jumps to the first or last option."
392
+ },
393
+ {
394
+ "keys": [
395
+ "Escape"
396
+ ],
397
+ "does": "Closes without choosing."
398
+ }
399
+ ],
400
+ "related": [
401
+ "combobox",
402
+ "native-select",
403
+ "field"
404
+ ]
405
+ },
406
+ {
407
+ "slug": "native-select",
408
+ "entry": "@misoto22/design",
409
+ "name": "NativeSelect",
410
+ "group": "Forms",
411
+ "summary": "The platform’s own picker, restyled where it can be.",
412
+ "when": "The escape hatch, not the default. Reach for it where the platform genuinely wins: a very long list on a phone, a form that must work without JavaScript, a page counting its last kilobyte.",
413
+ "accessibility": [
414
+ "Typeahead and the mobile wheel come free, from the browser.",
415
+ "What it cannot do is look like the rest of the system once open — the option list is drawn by the operating system and carries none of these tokens."
416
+ ],
417
+ "keyboard": [
418
+ {
419
+ "keys": [
420
+ "Space",
421
+ "↓"
422
+ ],
423
+ "does": "Opens the platform picker."
424
+ },
425
+ {
426
+ "keys": [
427
+ "a–z"
428
+ ],
429
+ "does": "Typeahead, from the browser’s own implementation."
430
+ }
431
+ ],
432
+ "related": [
433
+ "select",
434
+ "field"
435
+ ]
436
+ },
437
+ {
438
+ "slug": "checkbox",
439
+ "entry": "@misoto22/design",
440
+ "name": "Checkbox",
441
+ "group": "Forms",
442
+ "summary": "A choice that takes effect when the form is submitted.",
443
+ "when": "A setting that applies immediately is a Switch.",
444
+ "accessibility": [
445
+ "Supports the indeterminate state, which is what a “select all” header needs when only some rows are selected."
446
+ ],
447
+ "keyboard": [
448
+ {
449
+ "keys": [
450
+ "Space"
451
+ ],
452
+ "does": "Toggles it."
453
+ }
454
+ ],
455
+ "related": [
456
+ "switch",
457
+ "radio-group"
458
+ ]
459
+ },
460
+ {
461
+ "slug": "radio-group",
462
+ "entry": "@misoto22/design",
463
+ "name": "RadioGroup",
464
+ "group": "Forms",
465
+ "summary": "A set of mutually exclusive choices.",
466
+ "accessibility": [
467
+ "One tab stop for the whole group; the arrow keys move between options, per the ARIA radiogroup pattern.",
468
+ "The label is inside the <label>, so the whole row is the click target."
469
+ ],
470
+ "keyboard": [
471
+ {
472
+ "keys": [
473
+ "Tab"
474
+ ],
475
+ "does": "Moves into the group, and out of it — the whole group is one stop."
476
+ },
477
+ {
478
+ "keys": [
479
+ "↑",
480
+ "↓",
481
+ "←",
482
+ "→"
483
+ ],
484
+ "does": "Moves between options AND selects as it goes."
485
+ }
486
+ ],
487
+ "related": [
488
+ "checkbox",
489
+ "select"
490
+ ]
491
+ },
492
+ {
493
+ "slug": "switch",
494
+ "entry": "@misoto22/design",
495
+ "name": "Switch",
496
+ "group": "Forms",
497
+ "summary": "A setting that takes effect immediately.",
498
+ "when": "Inside a form with a Save button, a switch is a lie about when the change happened. Use a Checkbox.",
499
+ "keyboard": [
500
+ {
501
+ "keys": [
502
+ "Space",
503
+ "Enter"
504
+ ],
505
+ "does": "Toggles it, and the change applies immediately."
506
+ }
507
+ ],
508
+ "related": [
509
+ "checkbox"
510
+ ]
511
+ },
512
+ {
513
+ "slug": "dialog",
514
+ "entry": "@misoto22/design",
515
+ "name": "Dialog",
516
+ "group": "Overlays",
517
+ "summary": "A modal surface: portal, scrim, centred panel.",
518
+ "accessibility": [
519
+ "Radix owns the focus trap, Escape, the scroll lock and aria-modal.",
520
+ "A dialog without a visible heading still renders a hidden title, rather than shipping an unnamed modal."
521
+ ],
522
+ "keyboard": [
523
+ {
524
+ "keys": [
525
+ "Escape"
526
+ ],
527
+ "does": "Closes it, and focus returns to the trigger it came from."
528
+ },
529
+ {
530
+ "keys": [
531
+ "Tab"
532
+ ],
533
+ "does": "Cycles inside the dialog; focus cannot leave while it is open."
534
+ }
535
+ ],
536
+ "related": [
537
+ "dropdown-menu",
538
+ "tooltip"
539
+ ]
540
+ },
541
+ {
542
+ "slug": "dropdown-menu",
543
+ "entry": "@misoto22/design",
544
+ "name": "DropdownMenu",
545
+ "group": "Overlays",
546
+ "summary": "A menu of actions.",
547
+ "when": "Actions. Items that navigate belong in a nav; items that set a value are a Select or a RadioGroup.",
548
+ "accessibility": [
549
+ "Inside a bounded frame — a device preview, an embedded console — wrap the subtree in `<OverlayContainer container={el}>`. The panel then renders into that element and collides with its edges instead of the viewport’s, and inherits the `dir` and `data-density` set there.",
550
+ "Highlight is driven by data-highlighted, which covers hover AND keyboard focus — styling :hover alone leaves the keyboard user unable to see where they are."
551
+ ],
552
+ "keyboard": [
553
+ {
554
+ "keys": [
555
+ "Enter",
556
+ "Space",
557
+ "↓"
558
+ ],
559
+ "does": "Opens the menu and lands on the first item."
560
+ },
561
+ {
562
+ "keys": [
563
+ "↑",
564
+ "↓"
565
+ ],
566
+ "does": "Moves between items."
567
+ },
568
+ {
569
+ "keys": [
570
+ "a–z"
571
+ ],
572
+ "does": "Jumps to the next item starting with that letter."
573
+ },
574
+ {
575
+ "keys": [
576
+ "Escape"
577
+ ],
578
+ "does": "Closes the menu and returns focus to the trigger."
579
+ }
580
+ ],
581
+ "related": [
582
+ "dialog",
583
+ "select"
584
+ ]
585
+ },
586
+ {
587
+ "slug": "tooltip",
588
+ "entry": "@misoto22/design",
589
+ "name": "Tooltip",
590
+ "group": "Overlays",
591
+ "summary": "A short label on hover and on focus.",
592
+ "when": "Never for anything the reader NEEDS: a tooltip is unreachable on touch and invisible while scanning.",
593
+ "accessibility": [
594
+ "Inside a bounded frame — a device preview, an embedded console — wrap the subtree in `<OverlayContainer container={el}>`. The panel then renders into that element and collides with its edges instead of the viewport’s, and inherits the `dir` and `data-density` set there.",
595
+ "The trigger is asChild, so the child must be focusable — a div trigger simply has no keyboard tooltip, which this API shape makes obvious rather than silent.",
596
+ "Not an accessible name. An icon-only button still needs its own aria-label."
597
+ ],
598
+ "keyboard": [
599
+ {
600
+ "keys": [
601
+ "Tab"
602
+ ],
603
+ "does": "Shows the tip — focus reveals it, not only hover."
604
+ },
605
+ {
606
+ "keys": [
607
+ "Escape"
608
+ ],
609
+ "does": "Dismisses it."
610
+ }
611
+ ],
612
+ "related": [
613
+ "dialog"
614
+ ]
615
+ },
616
+ {
617
+ "slug": "tabs",
618
+ "entry": "@misoto22/design",
619
+ "name": "Tabs",
620
+ "group": "Navigation",
621
+ "summary": "One strip, several panels.",
622
+ "accessibility": [
623
+ "The strip scrolls rather than wrapping: a wrapped second row moves every tab below it and the reader loses the one they were about to click.",
624
+ "44px tall, because a tab is a pointer target like any other."
625
+ ],
626
+ "keyboard": [
627
+ {
628
+ "keys": [
629
+ "Tab"
630
+ ],
631
+ "does": "Moves into the strip, and out of it — the whole strip is one stop."
632
+ },
633
+ {
634
+ "keys": [
635
+ "←",
636
+ "→"
637
+ ],
638
+ "does": "Moves between tabs and switches the panel with them."
639
+ },
640
+ {
641
+ "keys": [
642
+ "Home",
643
+ "End"
644
+ ],
645
+ "does": "Jumps to the first or last tab."
646
+ }
647
+ ],
648
+ "related": [
649
+ "accordion"
650
+ ]
651
+ },
652
+ {
653
+ "slug": "accordion",
654
+ "entry": "@misoto22/design",
655
+ "name": "Accordion",
656
+ "group": "Navigation",
657
+ "summary": "Disclosure rows that open in place.",
658
+ "when": "The marker is a plus, not a chevron: a plus says “this opens”, a chevron says “there is more below”.",
659
+ "keyboard": [
660
+ {
661
+ "keys": [
662
+ "Tab"
663
+ ],
664
+ "does": "Moves between rows."
665
+ },
666
+ {
667
+ "keys": [
668
+ "Enter",
669
+ "Space"
670
+ ],
671
+ "does": "Opens or closes the focused row."
672
+ }
673
+ ],
674
+ "related": [
675
+ "tabs"
676
+ ]
677
+ },
678
+ {
679
+ "slug": "breadcrumb",
680
+ "entry": "@misoto22/design",
681
+ "name": "Breadcrumb",
682
+ "group": "Navigation",
683
+ "summary": "Where you are, as a path.",
684
+ "accessibility": [
685
+ "The last crumb is text with aria-current=\"page\", never a link to itself.",
686
+ "Separators are aria-hidden, so the trail is not read as “home slash work slash”."
687
+ ],
688
+ "related": [
689
+ "pagination"
690
+ ]
691
+ },
692
+ {
693
+ "slug": "pagination",
694
+ "entry": "@misoto22/design",
695
+ "name": "Pagination",
696
+ "group": "Navigation",
697
+ "summary": "Numbered pages, with the middle elided.",
698
+ "accessibility": [
699
+ "The current page is a button with aria-current, not a styled span — a reader jumping by control needs to find it.",
700
+ "Renders nothing at one page. A pager for a single page is furniture."
701
+ ],
702
+ "keyboard": [
703
+ {
704
+ "keys": [
705
+ "Tab"
706
+ ],
707
+ "does": "Reaches every control, including the current page."
708
+ },
709
+ {
710
+ "keys": [
711
+ "Enter",
712
+ "Space"
713
+ ],
714
+ "does": "Goes to that page."
715
+ }
716
+ ],
717
+ "related": [
718
+ "breadcrumb"
719
+ ]
720
+ },
721
+ {
722
+ "slug": "nav-item",
723
+ "entry": "@misoto22/design",
724
+ "name": "NavItem",
725
+ "group": "Navigation",
726
+ "summary": "A row in a sidebar.",
727
+ "accessibility": [
728
+ "aria-current=\"page\" and not only a colour: the active row is also carried by weight and a filled ground."
729
+ ],
730
+ "related": [
731
+ "app-shell"
732
+ ]
733
+ },
734
+ {
735
+ "slug": "article",
736
+ "entry": "@misoto22/design",
737
+ "name": "Article",
738
+ "group": "Surfaces",
739
+ "summary": "The long-form reading surface — everything a Markdown pipeline emits, in this system’s type.",
740
+ "when": "A post, a changelog entry, a document. Not for interface copy: a paragraph inside a card is a paragraph, and this is a whole reading column with its own rhythm.",
741
+ "accessibility": [
742
+ "An <article> by default, so the piece is a landmark a reader can jump to.",
743
+ "Every heading carries scroll-margin, so an anchored link does not park the heading under a fixed masthead.",
744
+ "The styles are element selectors at low specificity, so a component dropped inside keeps its own."
745
+ ],
746
+ "related": [
747
+ "diagram",
748
+ "card"
749
+ ]
750
+ },
751
+ {
752
+ "slug": "card",
753
+ "entry": "@misoto22/design",
754
+ "name": "Card",
755
+ "group": "Surfaces",
756
+ "summary": "A bounded surface, with no shadow under it.",
757
+ "when": "A card that needs to read as raised is a plate, which separates by reversal instead of by blur.",
758
+ "related": [
759
+ "table",
760
+ "figure-band"
761
+ ]
762
+ },
763
+ {
764
+ "slug": "table",
765
+ "entry": "@misoto22/design",
766
+ "name": "Table",
767
+ "group": "Data",
768
+ "summary": "A ruled data table — alignment, sorting and rules all per column.",
769
+ "when": "Alignment is per column and numbers belong at the end edge, so digits line up. Sorting is opt-in per column: a table where every header is a button invites sorting a column the data cannot be ordered by.",
770
+ "accessibility": [
771
+ "caption is required: an unnamed table on a page with three tables is unnavigable.",
772
+ "Column labels are <th scope=\"col\">, so a cell can be traced back to its heading.",
773
+ "A sortable header is a button INSIDE the th, not a click handler on the cell — a cell with an onClick is not focusable and not announced, so the sort would exist only for a mouse.",
774
+ "aria-sort is set from sortDirection, which is the only way a screen reader learns the table is ordered at all.",
775
+ "No zebra striping at any border setting: in a monochrome system a striped row is a second surface competing with the page ground."
776
+ ],
777
+ "keyboard": [
778
+ {
779
+ "keys": [
780
+ "Tab"
781
+ ],
782
+ "does": "Reaches the scroll region, and each sortable column header."
783
+ },
784
+ {
785
+ "keys": [
786
+ "←",
787
+ "→"
788
+ ],
789
+ "does": "Scrolls the table sideways once the region has focus."
790
+ }
791
+ ],
792
+ "related": [
793
+ "card",
794
+ "figure-band"
795
+ ]
796
+ },
797
+ {
798
+ "slug": "app-shell",
799
+ "entry": "@misoto22/design",
800
+ "name": "AppShell",
801
+ "group": "Surfaces",
802
+ "summary": "Two columns on a desktop, a drawer on a phone.",
803
+ "accessibility": [
804
+ "The drawer closes on Escape as well as on the scrim, so a keyboard user is not stranded inside it.",
805
+ "The scrim is a <button>, because a div with an onClick is neither reachable nor announced."
806
+ ],
807
+ "related": [
808
+ "nav-item"
809
+ ]
810
+ },
811
+ {
812
+ "slug": "combobox",
813
+ "entry": "@misoto22/design",
814
+ "name": "Combobox",
815
+ "group": "Forms",
816
+ "summary": "A select you can type into.",
817
+ "when": "Past roughly a dozen options. Below that a native Select is better: the platform picker on a phone, typeahead for free, no JavaScript.",
818
+ "accessibility": [
819
+ "The highlight moves through aria-activedescendant while focus stays in the input — the ARIA combobox pattern. Hand-rolled comboboxes move focus into the list, and the typed text stops being editable.",
820
+ "label is required: the trigger prints a value, and a value is not a name."
821
+ ],
822
+ "keyboard": [
823
+ {
824
+ "keys": [
825
+ "Enter",
826
+ "Space",
827
+ "↓"
828
+ ],
829
+ "does": "Opens the list."
830
+ },
831
+ {
832
+ "keys": [
833
+ "↑",
834
+ "↓"
835
+ ],
836
+ "does": "Moves the highlight while focus stays in the filter."
837
+ },
838
+ {
839
+ "keys": [
840
+ "Enter"
841
+ ],
842
+ "does": "Chooses the highlighted option; choosing the current one clears it."
843
+ },
844
+ {
845
+ "keys": [
846
+ "Escape"
847
+ ],
848
+ "does": "Closes without choosing."
849
+ }
850
+ ],
851
+ "related": [
852
+ "select",
853
+ "command"
854
+ ]
855
+ },
856
+ {
857
+ "slug": "date-picker",
858
+ "entry": "@misoto22/design",
859
+ "name": "DatePicker",
860
+ "group": "Forms",
861
+ "summary": "A date — or a span of them — chosen from a calendar.",
862
+ "when": "Deliberately not a text input with a calendar attached: parsing a typed date needs a format, and 03/04 is March the fourth in one country and the third of April in the next. When the date is a long way back, the calendar’s month and year are dropdowns.",
863
+ "accessibility": [
864
+ "The trigger prints the date in the visitor’s own locale, not a fixed dd/mm/yyyy.",
865
+ "DateRangePicker keeps the panel open until both ends are chosen — a range is not a value until it has a second date.",
866
+ "The shortcut rail is plain buttons, not a menu: they set the same value the grid beside them sets, so they belong to one control and Tab in the same pass.",
867
+ "Presets are computed on click, so “today” means today even on a tab left open overnight."
868
+ ],
869
+ "keyboard": [
870
+ {
871
+ "keys": [
872
+ "Enter",
873
+ "Space"
874
+ ],
875
+ "does": "Opens the calendar."
876
+ },
877
+ {
878
+ "keys": [
879
+ "Escape"
880
+ ],
881
+ "does": "Closes it without choosing."
882
+ }
883
+ ],
884
+ "related": [
885
+ "calendar",
886
+ "field"
887
+ ]
888
+ },
889
+ {
890
+ "slug": "slider",
891
+ "entry": "@misoto22/design",
892
+ "name": "Slider",
893
+ "group": "Forms",
894
+ "summary": "A value chosen along a range.",
895
+ "accessibility": [
896
+ "label is required. A thumb that announces \"42\" and nothing else leaves a screen reader user with a number and no idea what it measures.",
897
+ "A 44px hit area sits invisibly around the 16px thumb.",
898
+ "Arrows step, Page keys jump, Home and End reach the ends."
899
+ ],
900
+ "keyboard": [
901
+ {
902
+ "keys": [
903
+ "←",
904
+ "→"
905
+ ],
906
+ "does": "Moves by one step."
907
+ },
908
+ {
909
+ "keys": [
910
+ "Page Up",
911
+ "Page Down"
912
+ ],
913
+ "does": "Moves by a larger step."
914
+ },
915
+ {
916
+ "keys": [
917
+ "Home",
918
+ "End"
919
+ ],
920
+ "does": "Jumps to the minimum or maximum."
921
+ }
922
+ ],
923
+ "related": [
924
+ "progress"
925
+ ]
926
+ },
927
+ {
928
+ "slug": "toggle-group",
929
+ "entry": "@misoto22/design",
930
+ "name": "ToggleGroup",
931
+ "group": "Forms",
932
+ "summary": "A segmented control: several options, one strip.",
933
+ "when": "It changes a VALUE. Something that switches panels is Tabs.",
934
+ "accessibility": [
935
+ "type=\"single\" gets radio semantics; type=\"multiple\" gets independent toggles. Choosing wrong tells a screen reader that picking one option unpicks the others."
936
+ ],
937
+ "keyboard": [
938
+ {
939
+ "keys": [
940
+ "Tab"
941
+ ],
942
+ "does": "Moves into the strip — one stop for the group."
943
+ },
944
+ {
945
+ "keys": [
946
+ "←",
947
+ "→"
948
+ ],
949
+ "does": "Moves between segments."
950
+ },
951
+ {
952
+ "keys": [
953
+ "Enter",
954
+ "Space"
955
+ ],
956
+ "does": "Toggles the focused segment."
957
+ }
958
+ ],
959
+ "related": [
960
+ "tabs",
961
+ "radio-group"
962
+ ]
963
+ },
964
+ {
965
+ "slug": "popover",
966
+ "entry": "@misoto22/design",
967
+ "name": "Popover",
968
+ "group": "Overlays",
969
+ "summary": "A panel anchored to a control, holding content you can interact with.",
970
+ "when": "Anything with a link, a field or a button in it. A tooltip describes and cannot be entered — put a control inside one and it becomes unreachable.",
971
+ "accessibility": [
972
+ "Inside a bounded frame — a device preview, an embedded console — wrap the subtree in `<OverlayContainer container={el}>`. The panel then renders into that element and collides with its edges instead of the viewport’s, and inherits the `dir` and `data-density` set there.",
973
+ "label is required: a popover is a dialog, and an unnamed one announces nothing.",
974
+ "Its contents Tab like the rest of the page, unlike a menu’s arrow-key list."
975
+ ],
976
+ "keyboard": [
977
+ {
978
+ "keys": [
979
+ "Enter",
980
+ "Space"
981
+ ],
982
+ "does": "Opens it."
983
+ },
984
+ {
985
+ "keys": [
986
+ "Tab"
987
+ ],
988
+ "does": "Moves through its contents like the rest of the page."
989
+ },
990
+ {
991
+ "keys": [
992
+ "Escape"
993
+ ],
994
+ "does": "Closes it and returns focus to the trigger."
995
+ }
996
+ ],
997
+ "related": [
998
+ "tooltip",
999
+ "dropdown-menu"
1000
+ ]
1001
+ },
1002
+ {
1003
+ "slug": "sheet",
1004
+ "entry": "@misoto22/design",
1005
+ "name": "Sheet",
1006
+ "group": "Overlays",
1007
+ "summary": "A panel docked to an edge of the viewport.",
1008
+ "when": "A modal that needs room — a filter panel, a detail view. It IS a Dialog, docked; the sides are named in reading order, so `end` is the right in English and the left in Arabic.",
1009
+ "accessibility": [
1010
+ "Shares Dialog’s focus trap, Escape handling and scroll lock rather than reproducing them — a second focus trap is a second one to get wrong.",
1011
+ "The title is required, visible or not."
1012
+ ],
1013
+ "keyboard": [
1014
+ {
1015
+ "keys": [
1016
+ "Escape"
1017
+ ],
1018
+ "does": "Closes it, and focus returns to the trigger."
1019
+ },
1020
+ {
1021
+ "keys": [
1022
+ "Tab"
1023
+ ],
1024
+ "does": "Cycles inside the sheet."
1025
+ }
1026
+ ],
1027
+ "related": [
1028
+ "dialog",
1029
+ "popover"
1030
+ ]
1031
+ },
1032
+ {
1033
+ "slug": "context-menu",
1034
+ "entry": "@misoto22/design",
1035
+ "name": "ContextMenu",
1036
+ "group": "Overlays",
1037
+ "summary": "The menu a right-click opens.",
1038
+ "when": "Never as the only way to reach an action. Touch users, trackpad users and keyboard users may have no way to open it.",
1039
+ "keyboard": [
1040
+ {
1041
+ "keys": [
1042
+ "Shift",
1043
+ "F10"
1044
+ ],
1045
+ "does": "Opens the menu from the keyboard, where the platform supports it."
1046
+ },
1047
+ {
1048
+ "keys": [
1049
+ "↑",
1050
+ "↓"
1051
+ ],
1052
+ "does": "Moves between items."
1053
+ },
1054
+ {
1055
+ "keys": [
1056
+ "Escape"
1057
+ ],
1058
+ "does": "Closes it."
1059
+ }
1060
+ ],
1061
+ "related": [
1062
+ "dropdown-menu"
1063
+ ]
1064
+ },
1065
+ {
1066
+ "slug": "searchable-menu",
1067
+ "entry": "@misoto22/design",
1068
+ "name": "SearchableMenu",
1069
+ "group": "Overlays",
1070
+ "summary": "A menu of actions you can type into.",
1071
+ "when": "A DropdownMenu past about a dozen rows stops being scannable, and nesting submenus makes it worse. This is the same list with a filter over it. Not a Command palette: that is page-level and modal; this is anchored to a control.",
1072
+ "accessibility": [
1073
+ "Inside a bounded frame — a device preview, an embedded console — wrap the subtree in `<OverlayContainer container={el}>`. The panel then renders into that element and collides with its edges instead of the viewport’s, and inherits the `dir` and `data-density` set there.",
1074
+ "The rows are options inside a listbox rather than menuitems, because filtering requires it — the highlight moves through aria-activedescendant while focus stays in the input, and a menu cannot do that.",
1075
+ "The trade is deliberate: a menu that cannot be filtered is worse for the reader than a listbox that runs actions."
1076
+ ],
1077
+ "keyboard": [
1078
+ {
1079
+ "keys": [
1080
+ "Enter",
1081
+ "Space"
1082
+ ],
1083
+ "does": "Opens the menu."
1084
+ },
1085
+ {
1086
+ "keys": [
1087
+ "↑",
1088
+ "↓"
1089
+ ],
1090
+ "does": "Moves the highlight while focus stays in the filter."
1091
+ },
1092
+ {
1093
+ "keys": [
1094
+ "Enter"
1095
+ ],
1096
+ "does": "Runs the highlighted action."
1097
+ },
1098
+ {
1099
+ "keys": [
1100
+ "Escape"
1101
+ ],
1102
+ "does": "Closes without running anything."
1103
+ }
1104
+ ],
1105
+ "related": [
1106
+ "dropdown-menu",
1107
+ "command",
1108
+ "combobox"
1109
+ ]
1110
+ },
1111
+ {
1112
+ "slug": "command",
1113
+ "entry": "@misoto22/design",
1114
+ "name": "Command",
1115
+ "group": "Overlays",
1116
+ "summary": "A filterable list of actions — the ⌘K surface.",
1117
+ "accessibility": [
1118
+ "The list filters as you type, the highlight moves with the arrow keys, and focus stays in the input. That last part is the ARIA combobox pattern and the part a home-made palette gets wrong."
1119
+ ],
1120
+ "keyboard": [
1121
+ {
1122
+ "keys": [
1123
+ "↑",
1124
+ "↓"
1125
+ ],
1126
+ "does": "Moves the highlight. Focus stays in the input, so what you typed stays editable."
1127
+ },
1128
+ {
1129
+ "keys": [
1130
+ "Enter"
1131
+ ],
1132
+ "does": "Runs the highlighted item."
1133
+ },
1134
+ {
1135
+ "keys": [
1136
+ "Escape"
1137
+ ],
1138
+ "does": "Closes the palette."
1139
+ }
1140
+ ],
1141
+ "related": [
1142
+ "combobox",
1143
+ "dialog"
1144
+ ]
1145
+ },
1146
+ {
1147
+ "slug": "collapsible",
1148
+ "entry": "@misoto22/design",
1149
+ "name": "Collapsible",
1150
+ "group": "Navigation",
1151
+ "summary": "One thing that opens, on its own.",
1152
+ "when": "The difference from Accordion is arithmetic: an accordion is a SET and can coordinate. An accordion of one manages a value nobody reads.",
1153
+ "keyboard": [
1154
+ {
1155
+ "keys": [
1156
+ "Enter",
1157
+ "Space"
1158
+ ],
1159
+ "does": "Opens or closes it."
1160
+ }
1161
+ ],
1162
+ "related": [
1163
+ "accordion"
1164
+ ]
1165
+ },
1166
+ {
1167
+ "slug": "calendar",
1168
+ "entry": "@misoto22/design",
1169
+ "name": "Calendar",
1170
+ "group": "Surfaces",
1171
+ "summary": "A month, as a grid of days.",
1172
+ "when": "On its own for a range view or an availability grid; inside a DatePicker for choosing one.",
1173
+ "accessibility": [
1174
+ "Arrows move a day, Page keys move a month, Home and End reach the week’s ends.",
1175
+ "“Today” is an outline and “selected” is a fill — one is a fact about the calendar, the other a choice the reader made, and they must not look alike.",
1176
+ "Month and year are the system’s own Select, not the platform’s: a native list of a hundred years is a scroll rather than a choice, and it arrives styled by the operating system.",
1177
+ "The default span is ten years either side. A birth date needs a wider one, and asks for it with startMonth."
1178
+ ],
1179
+ "keyboard": [
1180
+ {
1181
+ "keys": [
1182
+ "←",
1183
+ "→"
1184
+ ],
1185
+ "does": "Moves by a day."
1186
+ },
1187
+ {
1188
+ "keys": [
1189
+ "↑",
1190
+ "↓"
1191
+ ],
1192
+ "does": "Moves by a week."
1193
+ },
1194
+ {
1195
+ "keys": [
1196
+ "Page Up",
1197
+ "Page Down"
1198
+ ],
1199
+ "does": "Moves by a month."
1200
+ },
1201
+ {
1202
+ "keys": [
1203
+ "Home",
1204
+ "End"
1205
+ ],
1206
+ "does": "Jumps to the week's first or last day."
1207
+ },
1208
+ {
1209
+ "keys": [
1210
+ "Enter",
1211
+ "Space"
1212
+ ],
1213
+ "does": "Chooses the focused day."
1214
+ }
1215
+ ],
1216
+ "related": [
1217
+ "date-picker"
1218
+ ]
1219
+ },
1220
+ {
1221
+ "slug": "scroll-area",
1222
+ "entry": "@misoto22/design",
1223
+ "name": "ScrollArea",
1224
+ "group": "Surfaces",
1225
+ "summary": "A box that scrolls, with a scrollbar that looks the same everywhere.",
1226
+ "when": "A bounded panel — a long option list, a log. For page-level or prose scroll the scroll-slim utility is lighter and needs no component.",
1227
+ "accessibility": [
1228
+ "The viewport stays focusable. A scrollable region whose contents are not focusable has nothing to Tab to, so everything past the fold does not exist without a mouse.",
1229
+ "label is required, because an unnamed keyboard stop announces \"group\" and nothing else."
1230
+ ],
1231
+ "keyboard": [
1232
+ {
1233
+ "keys": [
1234
+ "Tab"
1235
+ ],
1236
+ "does": "Moves focus into the region, which is what makes it scrollable at all without a mouse."
1237
+ },
1238
+ {
1239
+ "keys": [
1240
+ "↑",
1241
+ "↓",
1242
+ "Page Up",
1243
+ "Page Down"
1244
+ ],
1245
+ "does": "Scrolls it."
1246
+ }
1247
+ ],
1248
+ "related": [
1249
+ "table"
1250
+ ]
1251
+ },
1252
+ {
1253
+ "slug": "heatmap",
1254
+ "entry": "@misoto22/design/charts",
1255
+ "name": "Heatmap",
1256
+ "group": "Data",
1257
+ "summary": "A grid of values read by weight.",
1258
+ "when": "A calendar of activity, a confusion matrix, an hour-by-weekday load. The one form a monochrome system renders better than a chromatic one.",
1259
+ "accessibility": [
1260
+ "A real <table>, not an SVG: the structure a screen reader walks is the structure the eye reads, and every cell announces its own row, column and value.",
1261
+ "Lightness is the only channel that is unambiguously ordered, which is why the standing advice everywhere else is “one hue, light to dark”. Here there is no hue left to get wrong.",
1262
+ "A null is drawn as a dashed outline, never as the palest cell — a missing reading is not a zero.",
1263
+ "Pin domain whenever two grids are compared: on independent domains they look alike and mean different things, which is the one failure a shared legend cannot fix."
1264
+ ],
1265
+ "related": [
1266
+ "table",
1267
+ "scatter-chart"
1268
+ ]
1269
+ },
1270
+ {
1271
+ "slug": "sparkline",
1272
+ "entry": "@misoto22/design/charts",
1273
+ "name": "Sparkline",
1274
+ "group": "Data",
1275
+ "summary": "A run of numbers at the size of a word.",
1276
+ "when": "In a table cell, beside a figure, at the end of a row. When the trend needs reading precisely it wants a LineChart and its own space.",
1277
+ "accessibility": [
1278
+ "label is required and is the whole accessible name: a sparkline has no axes and no legend, so nothing else describes it.",
1279
+ "Axis-less by design. Every piece of chrome that would let it answer “what value exactly” also makes it too big to sit inline, which was the only reason to reach for it.",
1280
+ "Pin domain for a column of them: on independent domains every row peaks and troughs identically, which is how a table of sparklines becomes actively misleading.",
1281
+ "One path, no rendering engine — so a hundred of them in a table cost nothing."
1282
+ ],
1283
+ "related": [
1284
+ "line-chart",
1285
+ "table"
1286
+ ]
1287
+ },
1288
+ {
1289
+ "slug": "bar-list",
1290
+ "entry": "@misoto22/design/charts",
1291
+ "name": "BarList",
1292
+ "group": "Data",
1293
+ "summary": "A ranked list, with the bar behind the name rather than beside it.",
1294
+ "when": "Top referrers, slowest endpoints, biggest accounts. A horizontal BarChart spends a third of its width on an axis repeating labels the rows could simply contain.",
1295
+ "accessibility": [
1296
+ "A real <table> with two columns and one row per thing, because that is what a ranked list is. The bar is a background on the name cell, so it is never a second element a screen reader has to walk past.",
1297
+ "limit sums the tail into an “Other” row rather than dropping it — a top five that silently discards the other forty misstates the whole, and the reader has no way to tell.",
1298
+ "Pin max to compare two lists side by side: on independent scales the leading row of each fills its track, and two very different numbers look identical."
1299
+ ],
1300
+ "related": [
1301
+ "bar-chart",
1302
+ "table"
1303
+ ]
1304
+ },
1305
+ {
1306
+ "slug": "big-number",
1307
+ "entry": "@misoto22/design/charts",
1308
+ "name": "BigNumber",
1309
+ "group": "Data",
1310
+ "summary": "One number, at the size of a headline.",
1311
+ "when": "There is exactly one figure to report. A plot of a single value is a plot whose shape carries nothing, and the reader has to decode an axis to recover a number that could simply have been printed.",
1312
+ "accessibility": [
1313
+ "The delta’s direction is stated by the call site through intent, never inferred from the sign: “errors down 12%” is good news and “revenue down 12%” is not, and no component can tell which it is holding.",
1314
+ "The arrow and the words carry the direction; the status tint is the third signal, never the only one — so the reading survives greyscale, forced colours and colour blindness.",
1315
+ "value is taken already formatted. The component does not guess a unit, a currency or a locale."
1316
+ ],
1317
+ "related": [
1318
+ "sparkline",
1319
+ "figure-band"
1320
+ ]
1321
+ },
1322
+ {
1323
+ "slug": "bullet-chart",
1324
+ "entry": "@misoto22/design/charts",
1325
+ "name": "BulletChart",
1326
+ "group": "Data",
1327
+ "summary": "A measure, its target, and the bands that say whether it is any good.",
1328
+ "when": "A status page of ten tracked numbers. Stephen Few designed it to replace the dashboard gauge, which spends a whole card saying one number badly.",
1329
+ "accessibility": [
1330
+ "Plain HTML with logical properties — no rendering engine, server-renderable, and correct in a right-to-left document. Usable with recharts absent.",
1331
+ "The bands are a JUDGEMENT drawn in the same ink as the measurement, so the page has to say where they came from. Ranges that encode nothing but thirds make the chart look evaluated when it is not.",
1332
+ "It shows one instant and no change over time; target is the only comparison it carries. “How did we get here” wants a LineChart.",
1333
+ "Shared bands only mean something when the measures share a scale — a latency beside a conversion rate needs ranges and domain per measure."
1334
+ ],
1335
+ "related": [
1336
+ "bar-list",
1337
+ "big-number"
1338
+ ]
1339
+ },
1340
+ {
1341
+ "slug": "area-chart",
1342
+ "entry": "@misoto22/design/charts",
1343
+ "name": "AreaChart",
1344
+ "group": "Charts",
1345
+ "summary": "A filled series over a continuous axis, where the area means something.",
1346
+ "when": "Reading one magnitude over time. Comparing several series against each other is a LineChart — four translucent fills stacked on each other answer neither question.",
1347
+ "accessibility": [
1348
+ "title is required and becomes the figure’s accessible name, printed or not.",
1349
+ "The rows are rendered again as a visually hidden table, so the numbers are reachable rather than only drawn. hideDataTable opts out when the page already prints them.",
1350
+ "Six fill variants exist because in the monochrome default TEXTURE is the primary carrier of identity and the grey ramp is the second — which is also what keeps two series apart in greyscale print and under forced colours.",
1351
+ "The intro reveal is a per-frame SVG mask and is dropped entirely under prefers-reduced-motion, as is the crawling dash."
1352
+ ],
1353
+ "keyboard": [
1354
+ {
1355
+ "keys": [
1356
+ "Tab"
1357
+ ],
1358
+ "does": "Reaches the plot, which Recharts’ accessibility layer makes navigable."
1359
+ },
1360
+ {
1361
+ "keys": [
1362
+ "←",
1363
+ "→"
1364
+ ],
1365
+ "does": "Moves the cursor between points, announcing each."
1366
+ }
1367
+ ],
1368
+ "related": [
1369
+ "line-chart",
1370
+ "bar-chart",
1371
+ "composed-chart"
1372
+ ]
1373
+ },
1374
+ {
1375
+ "slug": "bar-chart",
1376
+ "entry": "@misoto22/design/charts",
1377
+ "name": "BarChart",
1378
+ "group": "Charts",
1379
+ "summary": "Discrete categories compared by length.",
1380
+ "when": "The categories are buckets rather than a continuum. If the axis is time and the reader is following a trend, an AreaChart or LineChart reads it faster.",
1381
+ "accessibility": [
1382
+ "title is required; the rows are also rendered as a visually hidden table.",
1383
+ "Every bar carries an invisible full-height hit rectangle, so a 3px bar at the bottom of the scale is as easy to hit as a full-height one.",
1384
+ "A clickable legend entry is a real button with aria-pressed, not a div with a click handler.",
1385
+ "The staggered grow-in is anchored to the chart’s own start rather than to each bar’s mount, so a hover cannot replay it — and reduce-motion drops it entirely."
1386
+ ],
1387
+ "related": [
1388
+ "area-chart",
1389
+ "composed-chart",
1390
+ "radial-chart"
1391
+ ]
1392
+ },
1393
+ {
1394
+ "slug": "line-chart",
1395
+ "entry": "@misoto22/design/charts",
1396
+ "name": "LineChart",
1397
+ "group": "Charts",
1398
+ "summary": "Several series compared over a continuous axis.",
1399
+ "when": "The reader is comparing series against each other. When the area under one line is the point, fill it — that is an AreaChart.",
1400
+ "accessibility": [
1401
+ "title is required; the rows are also rendered as a visually hidden table.",
1402
+ "A clickable line gets a 15px transparent line underneath it, because a 1.6px stroke is not a pointer target.",
1403
+ "buffer draws the last segment dashed by measuring the real path length, so a projection is visibly a different kind of fact at any curve type."
1404
+ ],
1405
+ "related": [
1406
+ "area-chart",
1407
+ "composed-chart"
1408
+ ]
1409
+ },
1410
+ {
1411
+ "slug": "composed-chart",
1412
+ "entry": "@misoto22/design/charts",
1413
+ "name": "ComposedChart",
1414
+ "group": "Charts",
1415
+ "summary": "Bars and lines over one axis — the volume, and the rate it moved at.",
1416
+ "when": "Two measures that share a scale. Two that do NOT share one belong in two charts or indexed to a common base: there is no second y-axis here, on purpose.",
1417
+ "accessibility": [
1418
+ "title is required; the rows are also rendered as a visually hidden table.",
1419
+ "One value axis only. A dual-axis chart lets its author choose where the lines cross, which is the single most misleading thing a chart can do.",
1420
+ "enableHoverHighlight dims every bar outside the hovered column, driven by the chart’s own tooltip index."
1421
+ ],
1422
+ "related": [
1423
+ "bar-chart",
1424
+ "line-chart"
1425
+ ]
1426
+ },
1427
+ {
1428
+ "slug": "pie-chart",
1429
+ "entry": "@misoto22/design/charts",
1430
+ "name": "PieChart",
1431
+ "group": "Charts",
1432
+ "summary": "Parts of one whole.",
1433
+ "when": "Roughly what share, and nothing more precise. Ranking or comparing wedges — especially across two pies — is a BarChart’s job.",
1434
+ "accessibility": [
1435
+ "title is required; the rows are also rendered as a visually hidden table.",
1436
+ "The legend sits under the pie by default, because a pie has no category axis naming its sectors.",
1437
+ "Compose a Label to print the numbers on the wedges: a pie’s weakness is that an angle is hard to read, and a printed number removes the guess.",
1438
+ "One fill variant, deliberately. A wedge is small and awkwardly shaped, and a texture inside one reads as noise."
1439
+ ],
1440
+ "related": [
1441
+ "radial-chart",
1442
+ "bar-chart"
1443
+ ]
1444
+ },
1445
+ {
1446
+ "slug": "radar-chart",
1447
+ "entry": "@misoto22/design/charts",
1448
+ "name": "RadarChart",
1449
+ "group": "Charts",
1450
+ "summary": "A profile across several named dimensions.",
1451
+ "when": "Recognising a silhouette. The area a radar encloses depends on the order its spokes happen to be in, so it is the wrong chart for comparing magnitudes.",
1452
+ "accessibility": [
1453
+ "title is required; the rows are also rendered as a visually hidden table.",
1454
+ "Two or three series at most: filled polygons overlap, and judging areas through two layers of translucency is what a radar is worst at. Past that, variant=\"lines\"."
1455
+ ],
1456
+ "related": [
1457
+ "line-chart",
1458
+ "pie-chart"
1459
+ ]
1460
+ },
1461
+ {
1462
+ "slug": "radial-chart",
1463
+ "entry": "@misoto22/design/charts",
1464
+ "name": "RadialChart",
1465
+ "group": "Charts",
1466
+ "summary": "Values on an arc — a gauge, or a few totals against one scale.",
1467
+ "when": "A single value against a fixed total. Past about four bars a BarChart is the honest choice, because a radial bar’s radius is not its value.",
1468
+ "accessibility": [
1469
+ "title is required; pass valueKey and the rows are also rendered as a visually hidden table.",
1470
+ "Set max or the scale comes from the data and the largest bar always fills the arc — which makes 62% and 98% look identical.",
1471
+ "showTrack draws the unfilled remainder, which is what makes a gauge readable at all."
1472
+ ],
1473
+ "related": [
1474
+ "pie-chart",
1475
+ "bar-chart"
1476
+ ]
1477
+ },
1478
+ {
1479
+ "slug": "sankey-chart",
1480
+ "entry": "@misoto22/design/charts",
1481
+ "name": "SankeyChart",
1482
+ "group": "Charts",
1483
+ "summary": "Where a quantity goes as it moves through stages.",
1484
+ "when": "A funnel, a budget, an energy or traffic breakdown. The only chart here whose data is a graph rather than a table.",
1485
+ "accessibility": [
1486
+ "title is required. The hidden table lists the FLOWS rather than the nodes — a table of node totals would lose every “from → to” the diagram exists to show.",
1487
+ "Four link variants: gradient reads as flow, source and target attribute a band to one end, solid gives up colour and lets the nodes carry identity."
1488
+ ],
1489
+ "related": [
1490
+ "bar-chart"
1491
+ ]
1492
+ },
1493
+ {
1494
+ "slug": "scatter-chart",
1495
+ "entry": "@misoto22/design/charts",
1496
+ "name": "ScatterChart",
1497
+ "group": "Charts",
1498
+ "summary": "Two measures against each other, one mark per observation.",
1499
+ "when": "Correlation, clustering, outliers — the questions that do not survive being bucketed into a bar. The only chart here whose x axis is a number rather than a category.",
1500
+ "accessibility": [
1501
+ "title is required. The table view is declared rather than inferred: scatter data lives on each series, so there is no single set of rows to read off the root.",
1502
+ "Shape does the work hue does elsewhere. Two overlapping clouds separate far better by circle-versus-cross than by two steps of grey — and shape survives overprinting, which a lightness step does not.",
1503
+ "A solid mark carries a surface-coloured ring, so two observations that land on top of each other stay countable.",
1504
+ "ZAxis maps its measure to a mark’s AREA, not its radius: doubling a radius quadruples the ink, which is the most common way a bubble chart lies."
1505
+ ],
1506
+ "related": [
1507
+ "line-chart",
1508
+ "heatmap"
1509
+ ]
1510
+ },
1511
+ {
1512
+ "slug": "funnel-chart",
1513
+ "entry": "@misoto22/design/charts",
1514
+ "name": "FunnelChart",
1515
+ "group": "Charts",
1516
+ "summary": "Stages that only ever narrow.",
1517
+ "when": "A signup flow, a hiring pipeline, a checkout. When the flow can SPLIT rather than only shrink, it is a SankeyChart — a funnel has one path through it by construction.",
1518
+ "accessibility": [
1519
+ "title is required; the stages are also rendered as a visually hidden table.",
1520
+ "The taper encodes a ratio between neighbouring stages and the eye reads the enclosed area, so a funnel exaggerates a shallow drop. Compose a Label to print the numbers — that is the relief.",
1521
+ "The default variant holds one fill for every stage and lets the shape carry the drop. A ramp that also darkens each stage encodes the same fact twice."
1522
+ ],
1523
+ "related": [
1524
+ "sankey-chart",
1525
+ "bar-chart"
1526
+ ]
1527
+ },
1528
+ {
1529
+ "slug": "treemap-chart",
1530
+ "entry": "@misoto22/design/charts",
1531
+ "name": "TreemapChart",
1532
+ "group": "Charts",
1533
+ "summary": "Part of a whole, when the whole has too many parts for a pie — and the parts nest.",
1534
+ "when": "Fifty items where a pie fails at six. Under a dozen items with a ranking to read, a BarChart’s length is the more precise encoding.",
1535
+ "accessibility": [
1536
+ "title is required. The table view lists the LEAVES with the path that names them: a nested tree read row by row is not something anyone can follow.",
1537
+ "Area is the encoding, so the data must be non-negative and must sum to something the reader recognises as the whole.",
1538
+ "The gap between tiles is a surface-coloured stroke rather than a smaller rect — a treemap whose parts do not touch stops reading as a partition."
1539
+ ],
1540
+ "related": [
1541
+ "pie-chart",
1542
+ "bar-chart"
1543
+ ]
1544
+ },
1545
+ {
1546
+ "slug": "box-plot",
1547
+ "entry": "@misoto22/design/charts",
1548
+ "name": "BoxPlot",
1549
+ "group": "Charts",
1550
+ "summary": "The spread of a measurement, per category.",
1551
+ "when": "How variable is this, across six things at once. When the shape of ONE distribution is the question it wants a Histogram; when there are few enough observations to draw them all, a ScatterChart.",
1552
+ "accessibility": [
1553
+ "A box is five numbers, and five numbers cannot tell one hump from two. A bimodal distribution draws exactly the same box as a smooth one centred in the same place — the component says so in its own description rather than in a footnote.",
1554
+ "It also hides sample size: a box over six points and a box over six thousand are drawn identically. Carry count, and turn on notched whenever medians are being compared.",
1555
+ "Raw values are summarised with Tukey’s fences, which is stated on the page rather than assumed — a different fence rule draws different outliers from the same data.",
1556
+ "The hidden data table carries all five numbers per category, so the figure is readable without seeing the glyph."
1557
+ ],
1558
+ "related": [
1559
+ "histogram",
1560
+ "scatter-chart"
1561
+ ]
1562
+ },
1563
+ {
1564
+ "slug": "histogram",
1565
+ "entry": "@misoto22/design/charts",
1566
+ "name": "Histogram",
1567
+ "group": "Charts",
1568
+ "summary": "The shape of one distribution.",
1569
+ "when": "A single distribution has to be understood — two clusters, a hard floor, a pile-up at a timeout. Several distributions side by side want a BoxPlot.",
1570
+ "accessibility": [
1571
+ "The shape is a property of the bin width, not only of the data: the same numbers cut into eight buckets and into eighty are two different pictures. The rule that drew it — Freedman–Diaconis by default — is named on the page.",
1572
+ "The x axis is numeric and every bar is drawn from its own two edges, so an uneven bucket is as wide as it really is rather than flattened into an equal slot.",
1573
+ "mode=\"density\" corrects the trap uneven buckets create: under frequency a bucket twice as wide stands twice as tall at the same underlying rate.",
1574
+ "The hidden data table prints each bucket’s two edges and its count, which is the only exact reading a binned chart can offer."
1575
+ ],
1576
+ "related": [
1577
+ "box-plot",
1578
+ "bar-chart"
1579
+ ]
1580
+ },
1581
+ {
1582
+ "slug": "waterfall-chart",
1583
+ "entry": "@misoto22/design/charts",
1584
+ "name": "WaterfallChart",
1585
+ "group": "Charts",
1586
+ "summary": "How a total got from one figure to another.",
1587
+ "when": "“Why did this change”, where the contributions can be negative. A pie cannot hold a negative slice; a BarChart is right when the parts need not add up to the gap between two totals.",
1588
+ "accessibility": [
1589
+ "The connectors draw the steps as a sequence, and most breakdowns are not sequential — churn and expansion in the same month are simultaneous, and a reader takes the leftmost bar as the first cause. Where the order is arbitrary, say so in description.",
1590
+ "Intermediate bars are floating lengths read against no baseline, so a small step high up the cascade is hard to compare with a large one near zero. Total bars sit on the axis and are the only ones a reader can read absolutely.",
1591
+ "Direction is carried by the label’s sign and the bar’s texture as well as its position, so the reading survives greyscale and forced colours.",
1592
+ "A closing bar with no value is computed from the deltas, which keeps the arithmetic in the data rather than in the caller’s head."
1593
+ ],
1594
+ "related": [
1595
+ "bar-chart",
1596
+ "funnel-chart"
1597
+ ]
1598
+ },
1599
+ {
1600
+ "slug": "facet",
1601
+ "entry": "@misoto22/design/charts",
1602
+ "name": "Facet",
1603
+ "group": "Charts",
1604
+ "summary": "The same chart once per group, on one shared scale.",
1605
+ "when": "Eight series overplot into a hairball in one frame. Two or three series that genuinely need comparing point-for-point still belong in one chart.",
1606
+ "accessibility": [
1607
+ "The shared domain is the default and the whole point: on independent scales a group peaking at 40 and one peaking at 4,000 draw the same shape, and the comparison the reader came for is not merely lost but inverted.",
1608
+ "Every panel is a figure with its own accessible name, so a screen reader walks eight named charts rather than one unnamed grid.",
1609
+ "Panels beyond max fold into a stated overflow rather than being dropped, and the count is printed — a grid silently missing four groups is not something a reader can detect.",
1610
+ "Panel order is a choice the call site makes explicitly through sort, because reading order is what a reader takes as ranking."
1611
+ ],
1612
+ "related": [
1613
+ "line-chart",
1614
+ "sparkline"
1615
+ ]
1616
+ }
1617
+ ],
1618
+ "exports": {
1619
+ "Accordion": "Accordion",
1620
+ "AccordionItem": "Accordion",
1621
+ "Alert": "Alert",
1622
+ "AlertTone": "Alert",
1623
+ "AppShell": "AppShell",
1624
+ "Article": "Article",
1625
+ "Avatar": "Avatar",
1626
+ "Badge": "Badge",
1627
+ "BadgeTone": "Badge",
1628
+ "Breadcrumb": "Breadcrumb",
1629
+ "Button": "Button",
1630
+ "ButtonVariant": "Button",
1631
+ "ButtonSize": "Button",
1632
+ "Calendar": "Calendar",
1633
+ "Card": "Card",
1634
+ "CardHeader": "Card",
1635
+ "CardTitle": "Card",
1636
+ "CardBody": "Card",
1637
+ "CardFooter": "Card",
1638
+ "Checkbox": "Checkbox",
1639
+ "Collapsible": "Collapsible",
1640
+ "CollapsibleTrigger": "Collapsible",
1641
+ "CollapsibleContent": "Collapsible",
1642
+ "CollapsibleSection": "Collapsible",
1643
+ "Combobox": "Combobox",
1644
+ "Command": "Command",
1645
+ "CommandInput": "Command",
1646
+ "CommandList": "Command",
1647
+ "CommandEmpty": "Command",
1648
+ "CommandFooter": "Command",
1649
+ "CommandHint": "Command",
1650
+ "CommandGroup": "Command",
1651
+ "CommandSeparator": "Command",
1652
+ "CommandItem": "Command",
1653
+ "CommandDialog": "Command",
1654
+ "ContextMenu": "ContextMenu",
1655
+ "ContextMenuTrigger": "ContextMenu",
1656
+ "ContextMenuContent": "ContextMenu",
1657
+ "ContextMenuItem": "ContextMenu",
1658
+ "ContextMenuSeparator": "ContextMenu",
1659
+ "ContextMenuLabel": "ContextMenu",
1660
+ "RANGE_PRESETS": "DatePicker",
1661
+ "DATE_PRESETS": "DatePicker",
1662
+ "DatePicker": "DatePicker",
1663
+ "DateRangePicker": "DatePicker",
1664
+ "Diagram": "Diagram",
1665
+ "Dialog": "Dialog",
1666
+ "DialogTrigger": "Dialog",
1667
+ "DialogClose": "Dialog",
1668
+ "DialogContent": "Dialog",
1669
+ "DropdownMenu": "DropdownMenu",
1670
+ "DropdownMenuTrigger": "DropdownMenu",
1671
+ "DropdownMenuContent": "DropdownMenu",
1672
+ "DropdownMenuItem": "DropdownMenu",
1673
+ "DropdownMenuSeparator": "DropdownMenu",
1674
+ "DropdownMenuLabel": "DropdownMenu",
1675
+ "EmptyState": "EmptyState",
1676
+ "ERROR_ACTION_CLASS": "ErrorState",
1677
+ "ErrorState": "ErrorState",
1678
+ "Field": "Field",
1679
+ "FigureBand": "FigureBand",
1680
+ "FloatingIconButton": "FloatingIconButton",
1681
+ "Input": "Input",
1682
+ "Kbd": "Kbd",
1683
+ "EXTERNAL_LINK_ARROW": "LinkArrow",
1684
+ "LinkArrow": "LinkArrow",
1685
+ "NativeSelect": "NativeSelect",
1686
+ "NavItem": "NavItem",
1687
+ "paginationRange": "Pagination",
1688
+ "Pagination": "Pagination",
1689
+ "Popover": "Popover",
1690
+ "PopoverTrigger": "Popover",
1691
+ "PopoverAnchor": "Popover",
1692
+ "PopoverClose": "Popover",
1693
+ "PopoverContent": "Popover",
1694
+ "Progress": "Progress",
1695
+ "RadioGroup": "RadioGroup",
1696
+ "RadioGroupItem": "RadioGroup",
1697
+ "ScrollArea": "ScrollArea",
1698
+ "SearchableMenu": "SearchableMenu",
1699
+ "SelectRoot": "Select",
1700
+ "SelectGroup": "Select",
1701
+ "Select": "Select",
1702
+ "SelectItem": "Select",
1703
+ "SelectLabel": "Select",
1704
+ "SelectSeparator": "Select",
1705
+ "Separator": "Separator",
1706
+ "Sheet": "Sheet",
1707
+ "SheetTrigger": "Sheet",
1708
+ "SheetClose": "Sheet",
1709
+ "SheetContent": "Sheet",
1710
+ "SheetSide": "Sheet",
1711
+ "Skeleton": "Skeleton",
1712
+ "SkeletonLine": "Skeleton",
1713
+ "SkeletonBlock": "Skeleton",
1714
+ "SkeletonCircle": "Skeleton",
1715
+ "SkeletonText": "Skeleton",
1716
+ "SkeletonPage": "Skeleton",
1717
+ "Slider": "Slider",
1718
+ "Spinner": "Spinner",
1719
+ "StatusDot": "StatusDot",
1720
+ "StatusTone": "StatusDot",
1721
+ "StatusPill": "StatusPill",
1722
+ "Steps": "Steps",
1723
+ "Switch": "Switch",
1724
+ "Table": "Table",
1725
+ "THead": "Table",
1726
+ "TBody": "Table",
1727
+ "TR": "Table",
1728
+ "TH": "Table",
1729
+ "TD": "Table",
1730
+ "TableAlign": "Table",
1731
+ "TableBorders": "Table",
1732
+ "SortDirection": "Table",
1733
+ "Tabs": "Tabs",
1734
+ "TabsList": "Tabs",
1735
+ "TabsTrigger": "Tabs",
1736
+ "TabsContent": "Tabs",
1737
+ "Tag": "Tag",
1738
+ "Textarea": "Textarea",
1739
+ "Toaster": "Toast",
1740
+ "ToggleGroup": "ToggleGroup",
1741
+ "ToggleGroupItem": "ToggleGroup",
1742
+ "TooltipProvider": "Tooltip",
1743
+ "Tooltip": "Tooltip",
1744
+ "AreaChart": "AreaChart",
1745
+ "ChartCurveType": "AreaChart",
1746
+ "AreaVariant": "AreaChart",
1747
+ "AreaStrokeVariant": "AreaChart",
1748
+ "AreaStackType": "AreaChart",
1749
+ "BarChart": "BarChart",
1750
+ "BarVariant": "BarChart",
1751
+ "BarStackType": "BarChart",
1752
+ "BarOrientation": "BarChart",
1753
+ "BarList": "BarList",
1754
+ "BigNumber": "BigNumber",
1755
+ "DeltaIntent": "BigNumber",
1756
+ "BoxPlot": "BoxPlot",
1757
+ "BoxPlotOrientation": "BoxPlot",
1758
+ "BoxPlotDatum": "BoxPlot",
1759
+ "BulletChart": "BulletChart",
1760
+ "ComposedChart": "ComposedChart",
1761
+ "Facet": "Facet",
1762
+ "FunnelChart": "FunnelChart",
1763
+ "FunnelVariant": "FunnelChart",
1764
+ "Heatmap": "Heatmap",
1765
+ "HeatmapScale": "Heatmap",
1766
+ "Histogram": "Histogram",
1767
+ "HistogramMode": "Histogram",
1768
+ "LineChart": "LineChart",
1769
+ "LineStrokeVariant": "LineChart",
1770
+ "PieChart": "PieChart",
1771
+ "PieVariant": "PieChart",
1772
+ "RadarChart": "RadarChart",
1773
+ "RadarVariant": "RadarChart",
1774
+ "RadialChart": "RadialChart",
1775
+ "RadialVariant": "RadialChart",
1776
+ "SankeyChart": "SankeyChart",
1777
+ "SankeyLinkVariant": "SankeyChart",
1778
+ "SankeyLabelPosition": "SankeyChart",
1779
+ "ScatterChart": "ScatterChart",
1780
+ "ScatterShape": "ScatterChart",
1781
+ "ScatterVariant": "ScatterChart",
1782
+ "Sparkline": "Sparkline",
1783
+ "SparklineVariant": "Sparkline",
1784
+ "TreemapChart": "TreemapChart",
1785
+ "TreemapVariant": "TreemapChart",
1786
+ "TreemapExtras": "TreemapChart",
1787
+ "WaterfallChart": "WaterfallChart",
1788
+ "WaterfallStepType": "WaterfallChart",
1789
+ "WaterfallDirection": "WaterfallChart"
1790
+ },
1791
+ "themeAxes": [
1792
+ {
1793
+ "axis": "data-chart-palette",
1794
+ "values": [
1795
+ "chroma"
1796
+ ],
1797
+ "unset": "the neutral series ramp"
1798
+ },
1799
+ {
1800
+ "axis": "data-density",
1801
+ "values": [
1802
+ "compact"
1803
+ ],
1804
+ "unset": "comfortable"
1805
+ },
1806
+ {
1807
+ "axis": "data-mode",
1808
+ "values": [
1809
+ "dark",
1810
+ "light"
1811
+ ],
1812
+ "unset": "follows the app"
1813
+ },
1814
+ {
1815
+ "axis": "data-motion",
1816
+ "values": [
1817
+ "snappy",
1818
+ "still"
1819
+ ],
1820
+ "unset": "calm"
1821
+ },
1822
+ {
1823
+ "axis": "data-radius",
1824
+ "values": [
1825
+ "round",
1826
+ "sharp"
1827
+ ],
1828
+ "unset": "the default radius ladder"
1829
+ },
1830
+ {
1831
+ "axis": "data-rules",
1832
+ "values": [
1833
+ "firm",
1834
+ "quiet"
1835
+ ],
1836
+ "unset": "hairline"
1837
+ },
1838
+ {
1839
+ "axis": "data-surface",
1840
+ "values": [
1841
+ "cool",
1842
+ "glass",
1843
+ "warm"
1844
+ ],
1845
+ "unset": "paper"
1846
+ },
1847
+ {
1848
+ "axis": "data-table-density",
1849
+ "values": [
1850
+ "compact"
1851
+ ],
1852
+ "unset": "comfortable — whatever `data-density` is doing around it"
1853
+ },
1854
+ {
1855
+ "axis": "data-type",
1856
+ "values": [
1857
+ "bookish",
1858
+ "grotesk"
1859
+ ],
1860
+ "unset": "editorial"
1861
+ }
1862
+ ]
1863
+ }