@misoto22/design 0.5.0 → 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 (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 +1791 -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 +171 -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,65 @@
1
+ # BarChart
2
+
3
+ Discrete categories compared by length.
4
+
5
+ - Group: Charts
6
+ - Import: `import { BarChart } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/bar-chart/
9
+ - Related: area-chart, composed-chart, radial-chart
10
+
11
+ ## When to reach for it
12
+
13
+ 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.
14
+
15
+ ## Accessibility
16
+
17
+ - title is required; the rows are also rendered as a visually hidden table.
18
+ - 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.
19
+ - A clickable legend entry is a real button with aria-pressed, not a div with a click handler.
20
+ - 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.
21
+
22
+ ## BarChart
23
+
24
+ Discrete categories compared by length — the shape for "how much, per thing". Reach for `<AreaChart>` or `<LineChart>` when the axis is continuous and the reader is following a trend rather than comparing buckets.
25
+
26
+ ### Props
27
+
28
+ - `config` (required) — `TConfig & ValidateKeys<TData, TConfig>`.
29
+ - `data` (required) — `TData[]`. The rows the chart draws. One entry per point, bar or category.
30
+ - `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.
31
+ - `showTitle` — `boolean`. Prints the title above the plot instead of hiding it from sight.
32
+ - `description` — `ReactNode`. A line under the title — the unit, the window, the caveat.
33
+ - `children` (required) — `ReactNode`. The composed parts — axes, grid, tooltip, legend, and the marks themselves.
34
+ - `className` — `string`. Merged onto the figure, last, so a call site can size or space it.
35
+ - `chartProps` — `ComponentProps<typeof RechartsBarChart>`. Escape hatch onto the raw Recharts chart element.
36
+ - `stackType` — `BarStackType` default `'default'`. How several marks combine: side by side, stacked, or normalised to 100%.
37
+ - `orientation` — `BarOrientation` default `'vertical'`. Which way the bars run. Reach for `horizontal` when the category names are long enough to need rotating under a column.
38
+ - `barRadius` — `number` default `BAR_RADIUS`. The corner every `<BarChart.Bar>` inherits.
39
+ - `animationType` — `ChartRevealType` default `'forward'`. The grow-in order every `<BarChart.Bar>` inherits.
40
+ - `barGap` — `number`. Gap between bars inside one category.
41
+ - `barCategoryGap` — `number`. Gap between categories.
42
+ - `defaultSelectedDataKey` — `string | null` default `null`. The series lit on first render. Selection dims every other series.
43
+ - `onSelectionChange` — `(selectedDataKey: string | null) => void`. Fires when the selection changes, and with null when it is cleared.
44
+ - `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.
45
+ - `loadingBars` — `number`. How many bars the skeleton draws.
46
+ - `xDataKey` — `keyof TData & string`. The row field on the category axis. Needed by the brush and by the table view.
47
+ - `hideDataTable` — `boolean` default `false`. Drops the hidden table view. Only correct when the page prints the data itself.
48
+ - `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.
49
+
50
+ ## Types
51
+
52
+ - `BarVariant` = `'default' | 'hatched' | 'duotone' | 'duotone-reverse' | 'gradient' | 'stripped'`
53
+ - `BarStackType` = `'default' | 'stacked' | 'percent'`
54
+ - `BarOrientation` = `'vertical' | 'horizontal'`
55
+
56
+ ## Examples
57
+
58
+ ```tsx
59
+ <BarChart title="Visitors by month" config={config} data={data} xDataKey="month">
60
+ <BarChart.Grid />
61
+ <BarChart.XAxis dataKey="month" />
62
+ <BarChart.Tooltip />
63
+ <BarChart.Bar dataKey="desktop" variant="duotone" />
64
+ </BarChart>
65
+ ```
@@ -0,0 +1,40 @@
1
+ # BarList
2
+
3
+ A ranked list, with the bar behind the name rather than beside it.
4
+
5
+ - Group: Data
6
+ - Import: `import { BarList } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/bar-list/
9
+ - Related: bar-chart, table
10
+
11
+ ## When to reach for it
12
+
13
+ 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.
14
+
15
+ ## Accessibility
16
+
17
+ - 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.
18
+ - 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.
19
+ - 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.
20
+
21
+ ## BarList
22
+
23
+ A ranked list, with the bar behind the name rather than beside it. The answer to "top referrers", "slowest endpoints", "biggest accounts" — and a better one than a horizontal bar chart, which spends a third of its width on a category axis repeating labels the rows could simply contain. Reading a name off a y-axis and matching it to a bar is two steps; reading it off the bar is none. It is a `<table>`, because that is what it is: two columns, a header, and one row per thing. The bar is a background on the name cell, so it never becomes a second element a screen reader has to walk past. Reach for `<BarChart orientation="horizontal">` instead when the categories are few and fixed and the axis is doing real work — a scale a reader needs to read values off, rather than a ranking they need to skim.
24
+
25
+ ### Props
26
+
27
+ - `label` (required) — `string`. What the list ranks. Required: it names the table for a screen reader.
28
+ - `showLabel` — `boolean` default `false`. Prints the label above the list instead of hiding it from sight.
29
+ - `items` (required) — `BarListItem[]`.
30
+ - `limit` — `number`. Keeps the top N and folds the rest into one "Other" row.
31
+ - `formatValue` — `(value: number) => string` default `defaultTick`. Formats each value. Defaults to the same compact form the axes use.
32
+ - `max` — `number`. The scale's ceiling. Derived from the largest row when omitted. Pin it 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.
33
+ - `sort` — `boolean` default `true`. Sorts descending before rendering.
34
+ - `className` — `string`.
35
+
36
+ ## Examples
37
+
38
+ ```tsx
39
+ <BarList label="Top referrers" items={referrers} limit={5} />
40
+ ```
@@ -0,0 +1,45 @@
1
+ # BigNumber
2
+
3
+ One number, at the size of a headline.
4
+
5
+ - Group: Data
6
+ - Import: `import { BigNumber } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/big-number/
9
+ - Related: sparkline, figure-band
10
+
11
+ ## When to reach for it
12
+
13
+ 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.
14
+
15
+ ## Accessibility
16
+
17
+ - 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.
18
+ - 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.
19
+ - value is taken already formatted. The component does not guess a unit, a currency or a locale.
20
+
21
+ ## BigNumber
22
+
23
+ One number, at the size of a headline. The form most dashboards need most often and most chart libraries do not ship, on the grounds that it is not a chart. It is the right answer whenever 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. The delta is where this earns its place over a `<p>`. Direction is stated by the CALL SITE (`intent`), never inferred: "errors down 12%" is good news and "revenue down 12%" is not, and no component can tell which it is holding. Where the direction is known, the arrow and the word carry it — the status colour is the third signal, never the only one.
24
+
25
+ ### Props
26
+
27
+ - `label` (required) — `ReactNode`. What the number counts.
28
+ - `value` (required) — `ReactNode`. The number, already formatted — this component does not guess a unit.
29
+ - `delta` — `BigNumberDelta`.
30
+ - `children` — `ReactNode`. A sparkline, a note, a caveat. Sits under the number.
31
+ - `className` — `string`.
32
+
33
+ ## Types
34
+
35
+ - `DeltaIntent` = `'up-is-good' | 'down-is-good' | 'neutral'`
36
+
37
+ ## Examples
38
+
39
+ ```tsx
40
+ <BigNumber
41
+ label="Monthly revenue"
42
+ value="$48,210"
43
+ delta={{ value: 0.124, label: 'vs last month', intent: 'up-is-good' }}
44
+ />
45
+ ```
@@ -0,0 +1,58 @@
1
+ # BoxPlot
2
+
3
+ The spread of a measurement, per category.
4
+
5
+ - Group: Charts
6
+ - Import: `import { BoxPlot } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/box-plot/
9
+ - Related: histogram, scatter-chart
10
+
11
+ ## When to reach for it
12
+
13
+ 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.
14
+
15
+ ## Accessibility
16
+
17
+ - 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.
18
+ - 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.
19
+ - 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.
20
+ - The hidden data table carries all five numbers per category, so the figure is readable without seeing the glyph.
21
+
22
+ ## BoxPlot
23
+
24
+ The spread of a measurement, per category — median, middle half, reach, and the points that sit outside it. The form to reach for when the question is "how variable is this", and the one that answers it in a tenth of the ink a histogram per category would take. Six response-time distributions fit across one screen as six boxes; as six histograms they do not fit at all. **What a box plot hides is multimodality.** A box is five numbers, and five numbers cannot tell a single hump from two. A bimodal distribution — a fast cache path and a slow database path, two cohorts inside one average — draws exactly the same box as a smooth one centred in the same place, and the reader has no way to tell from the picture that the middle of the box is a value almost nothing takes. It also hides sample size: a box over six points and a box over six thousand are drawn identically, which is why `count` is worth carrying and why a notch, which does read `count`, is worth turning on when medians are being compared. When the SHAPE of one distribution is the question, reach for `<Histogram>`; when there are few enough observations to draw them all, reach for `<ScatterChart>` and plot the points. Recharts earns its place here: the boxes need a shared value axis with real ticks, a category axis, a grid and a tooltip, which is most of a cartesian chart. What it does not have is a box mark, so each box is drawn as a custom shape over a range bar — the bar supplies the category band and the scale, and the glyph inside it is ours.
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 box plot has one measurement and as many categories as it has boxes.
29
+ - `data` (required) — `BoxPlotDatum[]`. One entry per category, as raw observations or as a summary.
30
+ - `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.
31
+ - `showTitle` — `boolean`. Prints the title above the plot instead of hiding it from sight.
32
+ - `description` — `ReactNode`. A line under the title — the unit, the window, the caveat.
33
+ - `children` (required) — `ReactNode`. The composed parts — axes, grid, tooltip, and `<BoxPlot.Boxes>`.
34
+ - `className` — `string`. Merged onto the figure, last, so a call site can size or space it.
35
+ - `chartProps` — `ComponentProps<typeof RechartsBarChart>`. Escape hatch onto the raw Recharts chart element.
36
+ - `orientation` — `BoxPlotOrientation` default `'vertical'`. Which way the boxes run. Reach for `horizontal` when the category names are long enough to need rotating under a column.
37
+ - `formatValue` — `(value: number) => string` default `defaultTick`. Formats every number the chart prints — ticks, tooltip, table.
38
+ - `hideDataTable` — `boolean` default `false`. Drops the hidden table view. Only correct when the page prints the data itself.
39
+ - `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.
40
+
41
+ ## Types
42
+
43
+ - `BoxPlotOrientation` = `'vertical' | 'horizontal'`
44
+ - `BoxPlotDatum` = `BoxPlotSample | (BoxPlotSummary & { values?: never })`
45
+
46
+ ## Examples
47
+
48
+ ```tsx
49
+ <BoxPlot title="Response time by region" data={regions}>
50
+ <BoxPlot.Grid />
51
+ <BoxPlot.XAxis />
52
+ <BoxPlot.YAxis label="ms" />
53
+ <BoxPlot.Tooltip />
54
+ <BoxPlot.Boxes showOutliers />
55
+ </BoxPlot>
56
+ // Raw observations, summarised for you with Tukey's fences.
57
+ const data = [{ name: 'Sydney', values: [180, 194, 210, 205, 640] }]
58
+ ```
@@ -0,0 +1,32 @@
1
+ # Breadcrumb
2
+
3
+ Where you are, as a path.
4
+
5
+ - Group: Navigation
6
+ - Import: `import { Breadcrumb } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/breadcrumb/
9
+ - Related: pagination
10
+
11
+ ## Accessibility
12
+
13
+ - The last crumb is text with aria-current="page", never a link to itself.
14
+ - Separators are aria-hidden, so the trail is not read as “home slash work slash”.
15
+
16
+ ## Breadcrumb
17
+
18
+ Where you are, as a path. The last crumb is plain text with `aria-current="page"` rather than a link to itself — a self-link is the most common breadcrumb bug, and it makes a screen reader offer a navigation that goes nowhere. Separators live in `<li aria-hidden>` so the trail is read as its items and not as "home slash work slash".
19
+
20
+ ### Props
21
+
22
+ - `items` (required) — `Crumb[]`.
23
+ - `label` — `string` default `'Breadcrumb'`. Names this trail when a page has more than one.
24
+ - `separator` — `ReactNode` default `'/'`. Rendered between crumbs. A slash by default; it is decorative either way.
25
+
26
+ Also accepts: `HTMLAttributes<HTMLElement>`.
27
+
28
+ ## Examples
29
+
30
+ ```tsx
31
+ <Breadcrumb items={[{ label: 'Components', href: '/components' }, { label: 'Button' }]} />
32
+ ```
@@ -0,0 +1,48 @@
1
+ # BulletChart
2
+
3
+ A measure, its target, and the bands that say whether it is any good.
4
+
5
+ - Group: Data
6
+ - Import: `import { BulletChart } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/bullet-chart/
9
+ - Related: bar-list, big-number
10
+
11
+ ## When to reach for it
12
+
13
+ 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.
14
+
15
+ ## Accessibility
16
+
17
+ - Plain HTML with logical properties — no rendering engine, server-renderable, and correct in a right-to-left document. Usable with recharts absent.
18
+ - 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.
19
+ - It shows one instant and no change over time; target is the only comparison it carries. “How did we get here” wants a LineChart.
20
+ - Shared bands only mean something when the measures share a scale — a latency beside a conversion rate needs ranges and domain per measure.
21
+
22
+ ## BulletChart
23
+
24
+ A measure, its target, and the bands that say whether the number is any good — one dense row per thing being tracked. Stephen Few designed this to replace the dashboard gauge, and the argument has held: a speedometer spends a whole card saying one number badly, where a bullet graph says the same number, its target, and the qualitative context around it in the height of a line of text. Ten of them stack into a status page a reader can scan in one pass. What it will not do is show change over time. A bullet graph is one instant, and `target` is the only comparison it carries; when the question is "how did we get here" it wants a `<LineChart>`, and when several measures have to be compared against each OTHER rather than each against its own target, a `<BarList>` ranks them and this does not. **The bands are the part to be careful with.** They are a judgement — someone decided that 80 is "good" — drawn in the same ink as the measurement, and a reader has no way to tell an agreed threshold from a number somebody typed. They also compress: a value near the top of the scale sits in the same band whether it cleared the boundary by a point or by thirty. The band answers "is this acceptable", never "by how much". No rendering engine, deliberately — this is the one chart in the set with nothing to compute. Each row is a single linear scale with no axis, no ticks and no shared plot area, so it is laid out as HTML: the bands and the bar are inline-axis offsets, which means the whole chart mirrors correctly in a right-to-left document, where an SVG drawn in user space would not.
25
+
26
+ ### Props
27
+
28
+ - `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.
29
+ - `showTitle` — `boolean`. Prints the title above the rows instead of hiding it from sight.
30
+ - `description` — `ReactNode`. A line under the title — the unit, the window, the caveat.
31
+ - `data` (required) — `BulletMeasure[]`. One entry per measure. Order is the reading order; it is not sorted.
32
+ - `ranges` — `number[]`. The bands every measure falls back to, as ascending upper bounds. Shared bands only mean something when the measures share a scale. Where they do not — a latency beside a conversion rate — put `ranges` and `domain` on each measure instead.
33
+ - `domain` — `[number, number]`. The scale every measure falls back to, as `[min, max]`.
34
+ - `formatValue` — `(value: number) => string` default `defaultTick`. Formats every number the chart prints.
35
+ - `showScale` — `boolean` default `false`. Prints the scale's two ends under each track.
36
+ - `className` — `string`. Merged onto the figure, last, so a call site can size or space it.
37
+ - `hideDataTable` — `boolean` default `false`. Drops the hidden table view. Only correct when the page prints the data itself.
38
+ - `empty` — `ChartEmptyProps`. What the chart shows when it has nothing to draw.
39
+
40
+ ## Examples
41
+
42
+ ```tsx
43
+ <BulletChart
44
+ title="Service levels against target"
45
+ data={[{ name: 'Uptime', value: 99.4, target: 99.9, ranges: [98, 99.5] }]}
46
+ domain={[95, 100]}
47
+ />
48
+ ```
@@ -0,0 +1,56 @@
1
+ # Button
2
+
3
+ The system’s action, on the same corner as the field beside it.
4
+
5
+ - Group: Actions
6
+ - Import: `import { Button } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/button/
9
+ - Related: floating-icon-button, spinner
10
+
11
+ ## When to reach for it
12
+
13
+ Anything that DOES something. If it navigates and looks like text, it is a link, not a ghost button.
14
+
15
+ ## Accessibility
16
+
17
+ - A native <button> by default, so Enter and Space both fire it.
18
+ - loading sets aria-busy and disables the control; the label stays, so the box does not collapse under the pointer that just clicked it.
19
+ - A link cannot be disabled, so href + loading sets aria-disabled and blocks pointer events instead.
20
+ - iconOnly has no text, so it requires aria-label — the single most common way a design system ships an unusable control.
21
+
22
+ ## Keyboard
23
+
24
+ - Enter — Activates the button.
25
+ - Space — Activates the button. A native <button> answers to both; a styled <div> answers to neither.
26
+
27
+ ## Button
28
+
29
+ The system's action. Renders a `<button>`, or an `<a>` when given `href`, or whatever you hand it via `asChild`. No router is imported, so the package stays framework-agnostic and a Next or React Router app wires its own `Link` at the call site. Server-component friendly: there is no client boundary here, so it renders in a static page as well as an interactive one.
30
+
31
+ ### Props
32
+
33
+ - `children` — `ReactNode`.
34
+ - `variant` — `ButtonVariant` default `'primary'`. Which action this is. `primary` is the one thing the screen wants you to do, so there is at most one per view; `danger` is reserved for destructive actions and is the only place chroma is allowed on a control.
35
+ - `size` — `ButtonSize` default `'md'`. 36 / 44 / 48px tall. `md` meets the pointer-target floor on its own.
36
+ - `keycap` — `string`. Optional mono keycap glyph rendered after the label (e.g. "P").
37
+ - `loading` — `boolean` default `false`. Swaps the leading content for a spinner and blocks interaction. The label stays put — a button that empties out while it works loses its width, and the page reflows under the pointer that just clicked it.
38
+ - `iconOnly` — `boolean` default `false`. Square control with no label. REQUIRES `aria-label`: an icon-only button with no accessible name is invisible to a screen reader, and this is the single most common way a design system ships an unusable control.
39
+ - `asChild` — `boolean` default `false`. Render the child element instead of a `<button>`, keeping these styles. Use it to hand the styling to a router's `Link` — `asChild` is what keeps this package free of any one router. The decoration slots (`keycap`, `loading`) are not injected into a slotted child; compose them inside it yourself.
40
+ - `className` — `string`.
41
+ - `href` — `string`.
42
+
43
+ Also accepts: `AnchorHTMLAttributes<HTMLAnchorElement>`, `ButtonHTMLAttributes<HTMLButtonElement>`.
44
+
45
+ ## Types
46
+
47
+ - `ButtonVariant` = `'primary' | 'secondary' | 'ghost' | 'danger'`
48
+ - `ButtonSize` = `'sm' | 'md' | 'lg'`
49
+
50
+ ## Examples
51
+
52
+ ```tsx
53
+ <Button variant="secondary" keycap="P">View projects</Button>
54
+ <Button loading disabled>Saving…</Button>
55
+ <Button iconOnly aria-label="Close"><X size={16} /></Button>
56
+ ```
@@ -0,0 +1,42 @@
1
+ # Calendar
2
+
3
+ A month, as a grid of days.
4
+
5
+ - Group: Surfaces
6
+ - Import: `import { Calendar } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/calendar/
9
+ - Related: date-picker
10
+
11
+ ## When to reach for it
12
+
13
+ On its own for a range view or an availability grid; inside a DatePicker for choosing one.
14
+
15
+ ## Accessibility
16
+
17
+ - Arrows move a day, Page keys move a month, Home and End reach the week’s ends.
18
+ - “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.
19
+ - 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.
20
+ - The default span is ten years either side. A birth date needs a wider one, and asks for it with startMonth.
21
+
22
+ ## Keyboard
23
+
24
+ - ← / → — Moves by a day.
25
+ - ↑ / ↓ — Moves by a week.
26
+ - Page Up / Page Down — Moves by a month.
27
+ - Home / End — Jumps to the week's first or last day.
28
+ - Enter / Space — Chooses the focused day.
29
+
30
+ ## Calendar
31
+
32
+ A month, as a grid of days. Wraps react-day-picker rather than building a calendar, and the reason is the long tail: a month grid is easy, and everything around it is not — the keyboard contract (arrows move a day, Page moves a month, Home and End reach the week's ends), the `aria-live` announcement when the month changes, week numbering, the first day of the week varying by locale, and the fact that "today" and "selected" are different states a screen reader must hear apart. Every class is replaced rather than layered over the library's stylesheet, so nothing here depends on a CSS file this package does not control — but the library's OWN class is kept on each slot, because passing a class REPLACES it and every `.rdp-*` selector downstream depends on those.
33
+
34
+ Also accepts: `DayPickerProps`.
35
+
36
+ ## Examples
37
+
38
+ ```tsx
39
+ <Calendar mode="single" selected={date} onSelect={setDate} />
40
+ // A birth date: widen the years, since the default span is deliberately short.
41
+ <Calendar mode="single" startMonth={new Date(1920, 0)} endMonth={new Date()} />
42
+ ```
@@ -0,0 +1,49 @@
1
+ # Card
2
+
3
+ A bounded surface, with no shadow under it.
4
+
5
+ - Group: Surfaces
6
+ - Import: `import { Card } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/card/
9
+ - Related: table, figure-band
10
+
11
+ ## When to reach for it
12
+
13
+ A card that needs to read as raised is a plate, which separates by reversal instead of by blur.
14
+
15
+ ## Card
16
+
17
+ A bounded surface. No shadow, by law: depth in this system is a hairline and a change of ground, never a blur. A card that needs to read as raised is a `plate`, which separates by reversal instead. Compose with the named sub-parts, or drop children straight in when the card has no header or footer to speak of.
18
+
19
+ ### Props
20
+
21
+ - `variant` — `'outline' | 'plate' | 'flat'` default `'outline'`. `outline` is a hairline box on the page ground — the default, and correct for a card sitting among other cards. `plate` fills with the one reversed surface and is for a card that IS the point of its band; use at most one per screen. `flat` drops the border entirely, for a card whose grid already draws the rules between cells.
22
+
23
+ Also accepts: `HTMLAttributes<HTMLDivElement>`.
24
+
25
+ ## CardHeader
26
+
27
+ Header row — title on the left, an action or marker on the right.
28
+
29
+ ## CardTitle
30
+
31
+ The card's title, in the editorial serif. An `<h3>` by default, which is right inside a section with its own `<h2>` and wrong nearly everywhere else — pass `as` rather than leaving a page with a heading order that jumps.
32
+
33
+ ## CardBody
34
+
35
+ The content well.
36
+
37
+ ## CardFooter
38
+
39
+ A quiet strip for metadata or secondary actions.
40
+
41
+ ## Examples
42
+
43
+ ```tsx
44
+ <Card>
45
+ <CardHeader><CardTitle>Recent deploys</CardTitle><Badge>12</Badge></CardHeader>
46
+ <CardBody>…</CardBody>
47
+ <CardFooter>Updated just now</CardFooter>
48
+ </Card>
49
+ ```
@@ -0,0 +1,35 @@
1
+ # Checkbox
2
+
3
+ A choice that takes effect when the form is submitted.
4
+
5
+ - Group: Forms
6
+ - Import: `import { Checkbox } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/checkbox/
9
+ - Related: switch, radio-group
10
+
11
+ ## When to reach for it
12
+
13
+ A setting that applies immediately is a Switch.
14
+
15
+ ## Accessibility
16
+
17
+ - Supports the indeterminate state, which is what a “select all” header needs when only some rows are selected.
18
+
19
+ ## Keyboard
20
+
21
+ - Space — Toggles it.
22
+
23
+ ## Checkbox
24
+
25
+ A choice that takes effect when the form is submitted. Supports the indeterminate state (`checked="indeterminate"`), which is what a "select all" header needs when only some rows are selected — a plain unchecked box there tells the reader the opposite of the truth. Pair with `Field`, or wrap it in a `<label>` at the call site so the words beside it are part of the click target.
26
+
27
+ Also accepts: `ComponentProps<typeof CheckboxPrimitive.Root>`.
28
+
29
+ ## Examples
30
+
31
+ ```tsx
32
+ <label className="flex items-center gap-2.5 text-sm">
33
+ <Checkbox defaultChecked /> Subscribe to updates
34
+ </label>
35
+ ```
@@ -0,0 +1,46 @@
1
+ # Collapsible
2
+
3
+ One thing that opens, on its own.
4
+
5
+ - Group: Navigation
6
+ - Import: `import { Collapsible } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/collapsible/
9
+ - Related: accordion
10
+
11
+ ## When to reach for it
12
+
13
+ The difference from Accordion is arithmetic: an accordion is a SET and can coordinate. An accordion of one manages a value nobody reads.
14
+
15
+ ## Keyboard
16
+
17
+ - Enter / Space — Opens or closes it.
18
+
19
+ ## Collapsible
20
+
21
+ Radix Collapsible root, as a typed passthrough.
22
+
23
+ ## CollapsibleTrigger
24
+
25
+ The trigger and the panel, unstyled, for a disclosure that needs its own layout — a sidebar group whose header carries a count and a chevron on opposite sides, say. `CollapsibleSection` is the composed version and is what most call sites want; these two exist so the ones that do not have to reach for Radix directly and re-derive the keyboard and `aria-expanded` wiring. The panel animates on `--radix-collapsible-content-height`, which Radix measures — so it opens to its real height rather than to a guessed `max-height`, which is what makes a long group and a short one take the same time instead of the long one appearing to stall.
26
+
27
+ ## CollapsibleContent
28
+
29
+ ## CollapsibleSection
30
+
31
+ One thing that opens, on its own. The difference from `Accordion` is arithmetic: an accordion is a SET, and a set can coordinate — opening one closes another. A collapsible is one disclosure with nothing to coordinate with. Reaching for an accordion of one gets you a component managing a value you never read. The marker here is a chevron rather than the accordion's plus, and deliberately: this reveals more of the same thing, where an accordion row opens a distinct answer.
32
+
33
+ ### Props
34
+
35
+ - `title` (required) — `ReactNode`. What the trigger says.
36
+ - `children` (required) — `ReactNode`.
37
+
38
+ Also accepts: `Omit<ComponentProps<typeof CollapsiblePrimitive.Root>, 'children' | 'title'>`.
39
+
40
+ ## Examples
41
+
42
+ ```tsx
43
+ <CollapsibleSection title="Advanced settings">
44
+ <Field label="Retries"><Input type="number" /></Field>
45
+ </CollapsibleSection>
46
+ ```
@@ -0,0 +1,50 @@
1
+ # Combobox
2
+
3
+ A select you can type into.
4
+
5
+ - Group: Forms
6
+ - Import: `import { Combobox } from '@misoto22/design'`
7
+ - Version: 0.6.0
8
+ - Docs: https://ui.misoto22.com/components/combobox/
9
+ - Related: select, command
10
+
11
+ ## When to reach for it
12
+
13
+ Past roughly a dozen options. Below that a native Select is better: the platform picker on a phone, typeahead for free, no JavaScript.
14
+
15
+ ## Accessibility
16
+
17
+ - 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.
18
+ - label is required: the trigger prints a value, and a value is not a name.
19
+
20
+ ## Keyboard
21
+
22
+ - Enter / Space / ↓ — Opens the list.
23
+ - ↑ / ↓ — Moves the highlight while focus stays in the filter.
24
+ - Enter — Chooses the highlighted option; choosing the current one clears it.
25
+ - Escape — Closes without choosing.
26
+
27
+ ## Combobox
28
+
29
+ A select you can type into, choosing one or several. The line against `Select` is length, and it is not a matter of taste: a styled select is better up to roughly a dozen options, because a list nobody can filter is faster to scan than one they have to think about. Past that, this is the right answer. Filtering, the highlighted row and the arrow keys come from cmdk, which implements the ARIA combobox pattern properly: the highlight moves through `aria-activedescendant` while focus stays in the input. Hand-rolled comboboxes move focus into the list instead, and the typed text stops being editable. Controlled or uncontrolled, like every other form control here.
30
+
31
+ ### Props
32
+
33
+ - `multiple` — `false`.
34
+ - `value` — `string`.
35
+ - `defaultValue` — `string`.
36
+ - `onValueChange` — `(value: string) => void`.
37
+ - `options` (required) — `ComboboxOption[]`.
38
+ - `label` (required) — `string`. Names the control. Required — the trigger's text is a value, not a label.
39
+ - `placeholder` — `string` default `'Select…'`. Shown on the trigger when nothing is chosen.
40
+ - `searchPlaceholder` — `string` default `'Search…'`. Placeholder inside the filter field.
41
+ - `emptyMessage` — `string` default `'Nothing matches.'`. Shown when the filter matches nothing. Say what WOULD match.
42
+ - `disabled` — `boolean` default `false`.
43
+ - `className` — `string`.
44
+
45
+ ## Examples
46
+
47
+ ```tsx
48
+ <Combobox label="Framework" options={FRAMEWORKS} placeholder="Pick one" />
49
+ <Combobox multiple label="Tags" options={TAGS} />
50
+ ```