@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
@@ -0,0 +1,37 @@
1
+ # Field
2
+
3
+ A labelled form row: label, control, and the one message below it.
4
+
5
+ - Group: Forms
6
+ - Import: `import { Field } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/field/
9
+ - Related: input, select
10
+
11
+ ## Accessibility
12
+
13
+ - Generates an id when none is given, so the label always points at something.
14
+ - Wires aria-describedby, aria-required and aria-invalid onto the control, so validation is announced and not merely drawn.
15
+ - hint and error are one slot: when a field is wrong, the thing to read is what is wrong with it.
16
+
17
+ ## Field
18
+
19
+ A labelled form row: label, control, and the one message below it. The visible message is only half of accessible validation — it must also reach the control. This wires `aria-describedby`, `aria-required` and `aria-invalid` onto the single control child so the requirement and the error are announced, not merely drawn (WCAG 1.3.1 / 3.3.1 / 4.1.2). An earlier version derived the message id from `htmlFor`, which meant a caller who left `htmlFor` off got a hint that was rendered and never announced — the failure was invisible in the browser and total for a screen reader. The id is now generated when it is not supplied. `hint` and `error` are one slot, not two stacked messages: when a field is wrong, the thing to read is what is wrong with it.
20
+
21
+ ### Props
22
+
23
+ - `label` — `ReactNode`. Visible label text; renders a `--danger` asterisk when `required`.
24
+ - `htmlFor` — `string`. The control's `id`. Optional: when omitted, the field generates one and puts it on the control child itself, so the label still points at something. Pass it explicitly when the id has to be stable across renders — a form library referencing it by name, say.
25
+ - `hint` — `ReactNode`. Helper copy shown below the control when there is no `error`.
26
+ - `error` — `ReactNode`. Validation message; takes precedence over `hint` when present.
27
+ - `required` — `boolean`.
28
+ - `children` (required) — `ReactNode`.
29
+
30
+ Also accepts: `HTMLAttributes<HTMLDivElement>`.
31
+
32
+ ## Examples
33
+
34
+ ```tsx
35
+ <Field label="Email" required hint="We never share it."><Input type="email" /></Field>
36
+ <Field label="Name" error="Name is required."><Input /></Field>
37
+ ```
@@ -0,0 +1,37 @@
1
+ # FigureBand
2
+
3
+ A row of counted facts, divided by hairlines and nothing else.
4
+
5
+ - Group: Display
6
+ - Import: `import { FigureBand } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/figure-band/
9
+ - Related: table
10
+
11
+ ## Accessibility
12
+
13
+ - A <dl>: each cell is a term and its value, which a grid of divs cannot express.
14
+
15
+ ## FigureBand
16
+
17
+ A row of counted facts, divided by hairlines and nothing else. A `<dl>`, because that is what this is: each cell is a term and its value, and a grid of `<div>`s tells a screen reader nothing about which number goes with which label. Each divider width names the cells that do NOT open a row rather than adding a rule and taking it back — an `undo` at equal specificity resolves on Tailwind's own sort order, which is not something a layout should depend on. Drawn this way, no edge is ever painted past the last column.
18
+
19
+ ### Props
20
+
21
+ - `figures` (required) — `Figure[]`.
22
+ - `scale` — `'lead' | 'sub'` default `'lead'`. How large the value is set. `lead` is for a band that is the point of its page — a stats headline, where the numbers ARE the content. `sub` is for a band that supports the page around it, and keeps the ladder honest: a supporting figure must not be set at the same size as the page's own subject.
23
+ - `label` — `string`. Names the band for assistive tech when it has no visible heading of its own.
24
+
25
+ Also accepts: `Omit<HTMLAttributes<HTMLDListElement>, 'children'>`.
26
+
27
+ ## Examples
28
+
29
+ ```tsx
30
+ <FigureBand
31
+ label="At a glance"
32
+ figures={[
33
+ { id: 'posts', label: 'Posts', value: '48', note: '+6 this year' },
34
+ { id: 'photos', label: 'Frames', value: '1,204' },
35
+ ]}
36
+ />
37
+ ```
@@ -0,0 +1,38 @@
1
+ # FloatingIconButton
2
+
3
+ A round action pinned to a screen corner.
4
+
5
+ - Group: Actions
6
+ - Import: `import { FloatingIconButton } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/floating-icon-button/
9
+ - Related: button
10
+
11
+ ## When to reach for it
12
+
13
+ A page-level affordance that must stay reachable while the reader scrolls — back to top, a mobile table of contents.
14
+
15
+ ## Accessibility
16
+
17
+ - label is the only name the control has; it is required rather than optional.
18
+ - 44px square, which is the pointer-target floor (WCAG 2.5.8).
19
+
20
+ ## FloatingIconButton
21
+
22
+ A round action pinned to a screen corner. A translucent paper ground with a backdrop blur rather than a drop shadow — the White Reset has no elevation ramp, so what separates the control from the page under it is the blur and the hairline, not a glow.
23
+
24
+ ### Props
25
+
26
+ - `position` (required) — `'start' | 'end'`. Which bottom corner the control is pinned to, in READING order — `end` is the right in English and the left in Arabic. Naming the sides `left`/`right` would have hard-coded one script's layout into the API.
27
+ - `label` (required) — `string`. Accessible name — the button has no visible text, so this is its only name.
28
+ - `children` (required) — `ReactNode`.
29
+
30
+ Also accepts: `Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'>`.
31
+
32
+ ## Examples
33
+
34
+ ```tsx
35
+ <FloatingIconButton position="right" label="Back to top" onClick={scrollUp}>
36
+ <ArrowUp size={16} />
37
+ </FloatingIconButton>
38
+ ```
@@ -0,0 +1,52 @@
1
+ # FunnelChart
2
+
3
+ Stages that only ever narrow.
4
+
5
+ - Group: Charts
6
+ - Import: `import { FunnelChart } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/funnel-chart/
9
+ - Related: sankey-chart, bar-chart
10
+
11
+ ## When to reach for it
12
+
13
+ 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.
14
+
15
+ ## Accessibility
16
+
17
+ - title is required; the stages are also rendered as a visually hidden table.
18
+ - 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.
19
+ - 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.
20
+
21
+ ## FunnelChart
22
+
23
+ Stages that only ever narrow — a signup flow, a hiring pipeline, a checkout. The caveat is the same one every funnel has: the taper encodes a RATIO between neighbouring stages, and the eye reads the enclosed area, so a funnel exaggerates a shallow drop and flattens a steep one. Where the exact fall-off is the point, put the percentages on the stages — `<Funnel.Label>` does — or use a `<BarChart>`, which encodes each stage on one honest scale. Reach for `<SankeyChart>` instead when the flow can SPLIT rather than only shrink: a funnel has one path through it by construction.
24
+
25
+ ### Props
26
+
27
+ - `config` (required) — `ChartConfig`. Stage names → their label and paint. Keys must match the `nameKey` values.
28
+ - `data` (required) — `TData[]`. The stages, widest first. Order is the funnel; it is not sorted for you.
29
+ - `dataKey` (required) — `keyof TData & string`. The row field holding each stage's number.
30
+ - `nameKey` (required) — `keyof TData & string`. The row field naming each stage.
31
+ - `title` (required) — `string`. What the chart shows, in a sentence a reader could act on. Required, and announced to a screen reader even when it is not printed.
32
+ - `showTitle` — `boolean`. Prints the title above the plot instead of hiding it from sight.
33
+ - `description` — `ReactNode`. A line under the title — the unit, the window, the caveat.
34
+ - `children` (required) — `ReactNode`. The composed parts — `<Funnel>`, `<Tooltip>`.
35
+ - `className` — `string`. Merged onto the figure, last, so a call site can size or space it.
36
+ - `chartProps` — `ComponentProps<typeof RechartsFunnelChart>`. Escape hatch onto the raw Recharts chart element.
37
+ - `hideDataTable` — `boolean` default `false`. Drops the hidden table view. Only correct when the page prints the data itself.
38
+
39
+ ## Types
40
+
41
+ - `FunnelVariant` = `'stepped' | 'ramp'`
42
+
43
+ ## Examples
44
+
45
+ ```tsx
46
+ <FunnelChart title="Signup funnel" config={config} data={stages} dataKey="people" nameKey="stage">
47
+ <FunnelChart.Funnel>
48
+ <FunnelChart.Label />
49
+ </FunnelChart.Funnel>
50
+ <FunnelChart.Tooltip />
51
+ </FunnelChart>
52
+ ```
@@ -0,0 +1,53 @@
1
+ # Heatmap
2
+
3
+ A grid of values read by weight.
4
+
5
+ - Group: Data
6
+ - Import: `import { Heatmap } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/heatmap/
9
+ - Related: table, scatter-chart
10
+
11
+ ## When to reach for it
12
+
13
+ A calendar of activity, a confusion matrix, an hour-by-weekday load. The one form a monochrome system renders better than a chromatic one.
14
+
15
+ ## Accessibility
16
+
17
+ - 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.
18
+ - 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.
19
+ - A null is drawn as a dashed outline, never as the palest cell — a missing reading is not a zero.
20
+ - 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.
21
+
22
+ ## Heatmap
23
+
24
+ A grid of values read by weight — a calendar of activity, a confusion matrix, an hour-by-weekday load. The one form in the set that a monochrome system renders BETTER than a chromatic one. A heatmap needs a scale whose order the eye can read without consulting a legend, and lightness is the only channel that is unambiguously ordered — which is why "one hue, light to dark" is the standing advice everywhere else, and why the rainbow heatmap is a perennial mistake. Here there is no hue left to get wrong. It is built as a real `<table>` rather than as an SVG, so the structure a screen reader walks is the structure the eye reads: a header row, a header column, and a cell that announces its own value. Nothing else in the package can say that, and nothing else needs to — which is also why this one takes no rendering engine at all.
25
+
26
+ ### Props
27
+
28
+ - `title` (required) — `string`. What the grid shows. Required, and it names the table.
29
+ - `showTitle` — `boolean` default `false`. Prints the title above the grid instead of hiding it from sight.
30
+ - `description` — `ReactNode`. A line under the title — the unit, the window, the caveat.
31
+ - `columns` (required) — `string[]`. Column headers, in the order they should appear.
32
+ - `rows` (required) — `string[]`. Row headers, in the order they should appear.
33
+ - `cells` (required) — `HeatmapCell[]`.
34
+ - `scale` — `HeatmapScale` default `'sequential'`.
35
+ - `domain` — `[number, number]`. The domain, as `[min, max]`. Derived from the data when omitted. Pin it whenever two grids are meant to be compared: two heatmaps on independent domains look alike and mean different things, which is the one failure a shared legend cannot fix.
36
+ - `formatValue` — `(value: number) => string` default `(value) => value.toLocaleString()`. Formats a value for the cell's announcement and its printed label.
37
+ - `showValues` — `boolean` default `false`. Prints the number inside each cell. Only legible on a coarse grid.
38
+ - `className` — `string`.
39
+
40
+ ## Types
41
+
42
+ - `HeatmapScale` = `'sequential' | 'diverging'`
43
+
44
+ ## Examples
45
+
46
+ ```tsx
47
+ <Heatmap
48
+ title="Commits by weekday and hour"
49
+ columns={hours}
50
+ rows={weekdays}
51
+ cells={cells}
52
+ />
53
+ ```
@@ -0,0 +1,63 @@
1
+ # Histogram
2
+
3
+ The shape of one distribution.
4
+
5
+ - Group: Charts
6
+ - Import: `import { Histogram } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/histogram/
9
+ - Related: box-plot, bar-chart
10
+
11
+ ## When to reach for it
12
+
13
+ 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.
14
+
15
+ ## Accessibility
16
+
17
+ - 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.
18
+ - 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.
19
+ - mode="density" corrects the trap uneven buckets create: under frequency a bucket twice as wide stands twice as tall at the same underlying rate.
20
+ - The hidden data table prints each bucket’s two edges and its count, which is the only exact reading a binned chart can offer.
21
+
22
+ ## Histogram
23
+
24
+ The shape of one distribution — where the mass sits, how it leans, whether there is more than one hump in it. The form that answers what a `<BoxPlot>` structurally cannot: two clusters, a hard floor, a pile-up at a timeout value. Reach for the box plot when several distributions have to be compared side by side, and for this one when a single distribution has to be understood. **A histogram's shape is a property of its bin width, not only of its data.** The same numbers cut into eight buckets and into eighty are two different pictures, and a gap between two humps can be created or erased by moving a bin edge. That is not a defect to be fixed, it is what binning IS, and the defence is to say which rule drew the picture — the default here is Freedman–Diaconis — and to look at more than one width before believing a feature. Uneven buckets add a second trap: under `frequency` a bucket twice as wide stands twice as tall at the same underlying rate, which is what `mode="density"` exists to correct. Recharts earns its place here for the axes, the grid and the tooltip, but not for the bars: a bar chart's bars are positioned by CATEGORY and a histogram's are positioned and SIZED by a continuous measurement. So the x axis is numeric and each bar is drawn from its own two edges — which is what lets an uneven bucket be as wide as it really is instead of being flattened into an equal slot beside its neighbours.
25
+
26
+ ### Props
27
+
28
+ - `config` — `ChartConfig` default `DEFAULT_CONFIG`. The single series — its label and its paint. Only the FIRST entry is read; a histogram has one distribution and as many bars as it has buckets.
29
+ - `values` — `number[]`. The raw observations, in any order. Binned for you by `bins`. Give this OR `data`, not both — `data` wins if both arrive.
30
+ - `data` — `HistogramBin[]`. Buckets that were counted somewhere else — by a database, by a sketch, by a metrics backend that only ever ships histograms. Uneven bucket widths are drawn at their real widths, which is the whole reason this takes edges rather than labels. Set `mode="density"` when they are uneven, or the wide buckets will read as tall ones.
31
+ - `bins` — `number | number[]`. How to cut `values` up: a number of equal-width bins, or the explicit edges. Defaults to Freedman–Diaconis (`2 × IQR × n^(-1/3)`), falling back to Sturges when the interquartile range is zero.
32
+ - `mode` — `HistogramMode` default `'frequency'`. What the bar heights mean. `frequency` is the count in each bucket and is what a reader assumes. `density` is `count / (n × bin width)`, so the total area is 1 — which is what makes two histograms of different sample sizes comparable, and what makes uneven buckets honest.
33
+ - `title` (required) — `string`. What the chart shows, in a sentence a reader could act on. Required, and announced to a screen reader even when it is not printed.
34
+ - `showTitle` — `boolean`. Prints the title above the plot instead of hiding it from sight.
35
+ - `description` — `ReactNode`. A line under the title — the unit, the window, the caveat.
36
+ - `children` (required) — `ReactNode`. The composed parts — axes, grid, tooltip, and `<Histogram.Bars>`.
37
+ - `className` — `string`. Merged onto the figure, last, so a call site can size or space it.
38
+ - `chartProps` — `ComponentProps<typeof RechartsBarChart>`. Escape hatch onto the raw Recharts chart element.
39
+ - `formatValue` — `(value: number) => string` default `defaultTick`. Formats the measured values — bin edges, ticks, the tooltip's heading.
40
+ - `hideDataTable` — `boolean` default `false`. Drops the hidden table view. Only correct when the page prints the data itself.
41
+ - `empty` — `ChartEmptyProps | false`. What the chart shows when it has nothing to draw. `false` keeps the axes, for a chart whose emptiness is itself the reading.
42
+
43
+ ## Types
44
+
45
+ - `HistogramMode` = `'frequency' | 'density'`
46
+
47
+ ## Examples
48
+
49
+ ```tsx
50
+ <Histogram title="Response times" values={samples} bins={20}>
51
+ <Histogram.Grid />
52
+ <Histogram.XAxis label="ms" />
53
+ <Histogram.YAxis />
54
+ <Histogram.Tooltip />
55
+ <Histogram.Bars />
56
+ </Histogram>
57
+ // Buckets that arrived already counted, with uneven widths.
58
+ <Histogram title="Payload size" data={buckets} mode="density">
59
+ <Histogram.XAxis />
60
+ <Histogram.YAxis />
61
+ <Histogram.Bars />
62
+ </Histogram>
63
+ ```
@@ -0,0 +1,30 @@
1
+ # Input
2
+
3
+ A single line of text entry.
4
+
5
+ - Group: Forms
6
+ - Import: `import { Input } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/input/
9
+ - Related: field, textarea
10
+
11
+ ## Accessibility
12
+
13
+ - A placeholder is not a label — it disappears the moment anyone types. Pair with Field.
14
+
15
+ ## Input
16
+
17
+ A single line of text entry. Shares `CONTROL_BASE` with Textarea and Select, so the three cannot drift apart. Pair with `Field` for the label, hint and error — an input with a placeholder and no label is not labelled, because the placeholder disappears the moment anyone types.
18
+
19
+ ### Props
20
+
21
+ - `invalid` — `boolean`. Paints the resting border with `--danger` and reflects `aria-invalid`.
22
+ - `ref` — `Ref<HTMLInputElement>`.
23
+
24
+ Also accepts: `InputHTMLAttributes<HTMLInputElement>`.
25
+
26
+ ## Examples
27
+
28
+ ```tsx
29
+ <Field label="Email" htmlFor="email"><Input id="email" type="email" /></Field>
30
+ ```
@@ -0,0 +1,29 @@
1
+ # Kbd
2
+
3
+ A key on a keyboard, set as one.
4
+
5
+ - Group: Display
6
+ - Import: `import { Kbd } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/kbd/
9
+ - Related: badge
10
+
11
+ ## Accessibility
12
+
13
+ - Renders <kbd>, which carries the meaning a styled <span> does not.
14
+
15
+ ## Kbd
16
+
17
+ A key on a keyboard, set as one. Renders a `<kbd>`, which is the element that means this — a `<span>` styled to look like a key tells a screen reader nothing. Sized in `em` so it tracks whatever type it sits beside rather than fixing itself at one px value, which is how the same shortcut ended up three different sizes across a page.
18
+
19
+ ### Props
20
+
21
+ - `children` (required) — `ReactNode`.
22
+
23
+ Also accepts: `HTMLAttributes<HTMLElement>`.
24
+
25
+ ## Examples
26
+
27
+ ```tsx
28
+ Press <Kbd>⌘</Kbd> <Kbd>K</Kbd> to open the palette.
29
+ ```
@@ -0,0 +1,60 @@
1
+ # LineChart
2
+
3
+ Several series compared over a continuous axis.
4
+
5
+ - Group: Charts
6
+ - Import: `import { LineChart } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/line-chart/
9
+ - Related: area-chart, composed-chart
10
+
11
+ ## When to reach for it
12
+
13
+ The reader is comparing series against each other. When the area under one line is the point, fill it — that is an AreaChart.
14
+
15
+ ## Accessibility
16
+
17
+ - title is required; the rows are also rendered as a visually hidden table.
18
+ - A clickable line gets a 15px transparent line underneath it, because a 1.6px stroke is not a pointer target.
19
+ - 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.
20
+
21
+ ## LineChart
22
+
23
+ Several series compared over a continuous axis — the shape for "which of these is going where". The difference from `<AreaChart>` is what the reader is asked to do: an area says "read the magnitude under this", a line says "compare these against each other". Filling four overlapping series makes the second question unanswerable, which is why a line chart has no fill variant to offer.
24
+
25
+ ### Props
26
+
27
+ - `config` (required) — `TConfig & ValidateKeys<TData, TConfig>`.
28
+ - `data` (required) — `TData[]`. The rows the chart draws. One entry per point, bar or category.
29
+ - `title` (required) — `string`. What the chart shows, in a sentence a reader could act on. Required, and announced to a screen reader even when it is not printed.
30
+ - `showTitle` — `boolean`. Prints the title above the plot instead of hiding it from sight.
31
+ - `description` — `ReactNode`. A line under the title — the unit, the window, the caveat.
32
+ - `children` (required) — `ReactNode`. The composed parts — axes, grid, tooltip, legend, and the marks themselves.
33
+ - `className` — `string`. Merged onto the figure, last, so a call site can size or space it.
34
+ - `chartProps` — `ComponentProps<typeof RechartsLineChart>`. Escape hatch onto the raw Recharts chart element.
35
+ - `curveType` — `ChartCurveType` default `'linear'`. How the line between two points is interpolated. Every mark inherits it unless it says otherwise.
36
+ - `animationType` — `ChartRevealType` default `'forward'`.
37
+ - `defaultSelectedDataKey` — `string | null` default `null`. The series lit on first render. Selection dims every other series.
38
+ - `onSelectionChange` — `(selectedDataKey: string | null) => void`. Fires when the selection changes, and with null when it is cleared.
39
+ - `isLoading` — `boolean` default `false`. Swaps the marks for an animated skeleton, keeping the measured height so the page does not jump when the data lands.
40
+ - `loadingPoints` — `number`. How many points the skeleton draws.
41
+ - `xDataKey` — `keyof TData & string`. The row field on the category axis. Needed by the brush and by the table view.
42
+ - `hideDataTable` — `boolean` default `false`. Drops the hidden table view. Only correct when the page prints the data itself.
43
+ - `empty` — `ChartEmptyProps | false`. What the chart shows when it has nothing to draw. Rendered instead of the plot whenever `data` is empty and the chart is not loading — the state a real dashboard reaches within a week, and the one an empty pair of axes is indistinguishable from a failed load. `false` keeps the axes, for a chart whose emptiness is itself the reading.
44
+
45
+ ## Types
46
+
47
+ - `LineStrokeVariant` = `AreaStrokeVariant`
48
+
49
+ ## Examples
50
+
51
+ ```tsx
52
+ <LineChart title="Visitors per month" config={config} data={data}>
53
+ <LineChart.Grid />
54
+ <LineChart.XAxis dataKey="month" />
55
+ <LineChart.Tooltip />
56
+ <LineChart.Line dataKey="desktop">
57
+ <LineChart.Dot variant="border" />
58
+ </LineChart.Line>
59
+ </LineChart>
60
+ ```
@@ -0,0 +1,29 @@
1
+ # LinkArrow
2
+
3
+ The mark on a link that leaves the page.
4
+
5
+ - Group: Display
6
+ - Import: `import { LinkArrow } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/link-arrow/
9
+
10
+ ## Accessibility
11
+
12
+ - aria-hidden, so it is not read as “north east arrow” in the middle of a sentence.
13
+ - Sized in em, so it tracks whatever type it sits beside instead of competing with it.
14
+
15
+ ## EXTERNAL_LINK_ARROW
16
+
17
+ The glyph itself, exported so a non-React surface can use the same mark.
18
+
19
+ ## LinkArrow
20
+
21
+ The mark on a link that leaves the page — outbound, or on to a full index. Call sites used to write a bare `↗` inside the link text, which inherited the link's own size (a 17px arrow beside a 17px word, competing with it) and was read aloud as "north east arrow" because nothing hid it. `inline-block` is load-bearing twice over: it stops an underlined parent drawing its rule through the glyph, and it is what `align` is measured against. Sized in `em`, so it tracks whatever type it sits beside; coloured against paper, so a call site on a reversed plate passes its own colour.
22
+
23
+ Also accepts: `HTMLAttributes<HTMLSpanElement>`.
24
+
25
+ ## Examples
26
+
27
+ ```tsx
28
+ <a href="https://example.com">Read the paper<LinkArrow /></a>
29
+ ```
@@ -0,0 +1,40 @@
1
+ # NativeSelect
2
+
3
+ The platform’s own picker, restyled where it can be.
4
+
5
+ - Group: Forms
6
+ - Import: `import { NativeSelect } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/native-select/
9
+ - Related: select, field
10
+
11
+ ## When to reach for it
12
+
13
+ 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.
14
+
15
+ ## Accessibility
16
+
17
+ - Typeahead and the mobile wheel come free, from the browser.
18
+ - 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.
19
+
20
+ ## Keyboard
21
+
22
+ - Space / ↓ — Opens the platform picker.
23
+ - a–z — Typeahead, from the browser’s own implementation.
24
+
25
+ ## NativeSelect
26
+
27
+ A native `<select>`, restyled. The escape hatch, not the default — `Select` is the styled one. Reach for this where the platform's own picker is genuinely better: a very long list on a phone, a form that must work without JavaScript, a page where the last kilobyte matters. The browser gives typeahead and the mobile wheel for free, and those are real. What it cannot do is look like the rest of the system once open. The option list is drawn by the operating system, so it carries none of these tokens — which is exactly why it stopped being the default.
28
+
29
+ ### Props
30
+
31
+ - `invalid` — `boolean`. Paints the resting border with `--danger` and reflects `aria-invalid`.
32
+ - `ref` — `Ref<HTMLSelectElement>`.
33
+
34
+ Also accepts: `SelectHTMLAttributes<HTMLSelectElement>`.
35
+
36
+ ## Examples
37
+
38
+ ```tsx
39
+ <NativeSelect defaultValue="au"><option value="au">Australia</option></NativeSelect>
40
+ ```
@@ -0,0 +1,35 @@
1
+ # NavItem
2
+
3
+ A row in a sidebar.
4
+
5
+ - Group: Navigation
6
+ - Import: `import { NavItem } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/nav-item/
9
+ - Related: app-shell
10
+
11
+ ## Accessibility
12
+
13
+ - aria-current="page" and not only a colour: the active row is also carried by weight and a filled ground.
14
+
15
+ ## NavItem
16
+
17
+ A row in a sidebar. `aria-current="page"` and not only a colour: the active row has to be identifiable to a reader who cannot see that it is darker. In this system it is also carried by weight and by a filled ground, so it survives monochrome printing and low contrast. Framework-agnostic. `asChild` is how a Next or React Router app gets client-side navigation without this package importing either.
18
+
19
+ ### Props
20
+
21
+ - `href` (required) — `string`.
22
+ - `icon` — `LucideIcon`. Optional leading icon (a lucide-react component, rendered at 18px).
23
+ - `active` — `boolean` default `false`. Marks the current route. Also sets `aria-current="page"`.
24
+ - `asChild` — `boolean` default `false`. Hand the styling to a router's own `Link` instead of a native `<a>`. The slotted child receives the classes and `aria-current`, and becomes the row — so `icon` is not rendered in this mode; put it inside the child.
25
+ - `children` (required) — `ReactNode`.
26
+ - `className` — `string`.
27
+
28
+ Also accepts: `Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'className' | 'children'>`.
29
+
30
+ ## Examples
31
+
32
+ ```tsx
33
+ <NavItem href="/components/button" icon={Square} active>Button</NavItem>
34
+ <NavItem asChild href="/work"><Link href="/work">Work</Link></NavItem>
35
+ ```
@@ -0,0 +1,43 @@
1
+ # Pagination
2
+
3
+ Numbered pages, with the middle elided.
4
+
5
+ - Group: Navigation
6
+ - Import: `import { Pagination } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/pagination/
9
+ - Related: breadcrumb
10
+
11
+ ## Accessibility
12
+
13
+ - The current page is a button with aria-current, not a styled span — a reader jumping by control needs to find it.
14
+ - Renders nothing at one page. A pager for a single page is furniture.
15
+
16
+ ## Keyboard
17
+
18
+ - Tab — Reaches every control, including the current page.
19
+ - Enter / Space — Goes to that page.
20
+
21
+ ## paginationRange
22
+
23
+ Builds the visible page list: always the first and last page, a window around the current one, and an ellipsis wherever the sequence skips. Returned as numbers and a literal ellipsis rather than as pre-rendered nodes, so the shape is testable without a DOM — the off-by-one at the window edges is the whole difficulty of this component.
24
+
25
+ ## Pagination
26
+
27
+ Numbered pagination. The current page is marked by one filled pill that TRAVELS between the numbers rather than by a background switching off on one and on on another. Two backgrounds cross-fading reads as two things changing; a shape moving reads as the one thing that actually did. A `<nav>` wrapping a list, and the current page is a `<button aria-current>` rather than a styled `<span>` — a reader jumping by landmark needs to find the control, and a reader on the current page needs to be told they are already there. Renders nothing at one page or fewer. A pager for a single page is furniture.
28
+
29
+ ### Props
30
+
31
+ - `page` (required) — `number`. 1-based.
32
+ - `pageCount` (required) — `number`. Total pages. A value of 1 or less renders nothing.
33
+ - `onPageChange` (required) — `(page: number) => void`.
34
+ - `siblings` — `number` default `1`. How many numbered pages sit either side of the current one.
35
+ - `label` — `string` default `'Pagination'`.
36
+
37
+ Also accepts: `Omit<HTMLAttributes<HTMLElement>, 'onChange'>`.
38
+
39
+ ## Examples
40
+
41
+ ```tsx
42
+ <Pagination page={page} pageCount={12} onPageChange={setPage} />
43
+ ```
@@ -0,0 +1,55 @@
1
+ # PieChart
2
+
3
+ Parts of one whole.
4
+
5
+ - Group: Charts
6
+ - Import: `import { PieChart } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/pie-chart/
9
+ - Related: radial-chart, bar-chart
10
+
11
+ ## When to reach for it
12
+
13
+ Roughly what share, and nothing more precise. Ranking or comparing wedges — especially across two pies — is a BarChart’s job.
14
+
15
+ ## Accessibility
16
+
17
+ - title is required; the rows are also rendered as a visually hidden table.
18
+ - The legend sits under the pie by default, because a pie has no category axis naming its sectors.
19
+ - 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.
20
+ - One fill variant, deliberately. A wedge is small and awkwardly shaped, and a texture inside one reads as noise.
21
+
22
+ ## PieChart
23
+
24
+ Parts of one whole. Worth saying plainly: a pie answers "roughly what share" and nothing more precise. Comparing two adjacent wedges by eye is unreliable past about five of them, and comparing a wedge across two pies is worse. When the reader needs to rank or compare, a `<BarChart>` answers the same question better.
25
+
26
+ ### Props
27
+
28
+ - `config` (required) — `ChartConfig`. Sector names → their label and paint. Keys must match the `nameKey` values.
29
+ - `data` (required) — `TData[]`. The rows the chart draws. One entry per point, bar or category.
30
+ - `dataKey` (required) — `keyof TData & string`. The row field holding each sector's number.
31
+ - `nameKey` (required) — `keyof TData & string`. The row field holding each sector's name.
32
+ - `title` (required) — `string`. What the chart shows, in a sentence a reader could act on. Required, and announced to a screen reader even when it is not printed.
33
+ - `showTitle` — `boolean`. Prints the title above the plot instead of hiding it from sight.
34
+ - `description` — `ReactNode`. A line under the title — the unit, the window, the caveat.
35
+ - `children` (required) — `ReactNode`. The composed parts — axes, grid, tooltip, legend, and the marks themselves.
36
+ - `className` — `string`. Merged onto the figure, last, so a call site can size or space it.
37
+ - `chartProps` — `ComponentProps<typeof RechartsPieChart>`. Escape hatch onto the raw Recharts chart element.
38
+ - `defaultSelectedSector` — `string | null` default `null`. The sector lit on first render.
39
+ - `onSelectionChange` — `(selection: { name: string; value: number } | null) => void`. Fires when the selection changes, and with null when it is cleared.
40
+ - `isLoading` — `boolean` default `false`. Swaps the marks for an animated skeleton, keeping the measured height so the page does not jump when the data lands.
41
+ - `hideDataTable` — `boolean` default `false`. Drops the hidden table view. Only correct when the page prints the data itself.
42
+
43
+ ## Types
44
+
45
+ - `PieVariant` = `'gradient'`
46
+
47
+ ## Examples
48
+
49
+ ```tsx
50
+ <PieChart title="Visitors by browser" config={config} data={data} dataKey="visitors" nameKey="browser">
51
+ <PieChart.Pie innerRadius="55%" />
52
+ <PieChart.Tooltip />
53
+ <PieChart.Legend />
54
+ </PieChart>
55
+ ```