@misoto22/design 0.8.0 → 0.9.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 (157) hide show
  1. package/dist/agent/Accordion.md +1 -1
  2. package/dist/agent/Alert.md +1 -1
  3. package/dist/agent/AppShell.md +1 -1
  4. package/dist/agent/ArchitectureFigure.md +1 -1
  5. package/dist/agent/AreaChart.md +1 -1
  6. package/dist/agent/Article.md +1 -1
  7. package/dist/agent/AspectRatio.md +1 -1
  8. package/dist/agent/Avatar.md +1 -1
  9. package/dist/agent/Badge.md +1 -1
  10. package/dist/agent/BarChart.md +1 -1
  11. package/dist/agent/BarList.md +1 -1
  12. package/dist/agent/BigNumber.md +1 -1
  13. package/dist/agent/BoxPlot.md +1 -1
  14. package/dist/agent/Breadcrumb.md +1 -1
  15. package/dist/agent/BulletChart.md +1 -1
  16. package/dist/agent/Button.md +1 -1
  17. package/dist/agent/Calendar.md +1 -1
  18. package/dist/agent/Card.md +1 -1
  19. package/dist/agent/Checkbox.md +1 -1
  20. package/dist/agent/Code.md +1 -1
  21. package/dist/agent/CodeBlock.md +1 -1
  22. package/dist/agent/Collapsible.md +1 -1
  23. package/dist/agent/ColorPicker.md +75 -0
  24. package/dist/agent/Combobox.md +1 -1
  25. package/dist/agent/Command.md +1 -1
  26. package/dist/agent/ComposedChart.md +1 -1
  27. package/dist/agent/ContextMenu.md +1 -1
  28. package/dist/agent/DataflowFigure.md +1 -1
  29. package/dist/agent/DatePicker.md +1 -1
  30. package/dist/agent/DescriptionList.md +1 -1
  31. package/dist/agent/Diagram.md +1 -1
  32. package/dist/agent/DiagramCanvas.md +1 -1
  33. package/dist/agent/DiagramExportMenu.md +1 -1
  34. package/dist/agent/DiagramInspector.md +1 -1
  35. package/dist/agent/DiagramLegend.md +1 -1
  36. package/dist/agent/DiagramMinimap.md +1 -1
  37. package/dist/agent/DiagramToolbar.md +1 -1
  38. package/dist/agent/Dialog.md +1 -1
  39. package/dist/agent/DropdownMenu.md +1 -1
  40. package/dist/agent/EmptyState.md +1 -1
  41. package/dist/agent/ErrorState.md +1 -1
  42. package/dist/agent/Facet.md +1 -1
  43. package/dist/agent/Field.md +1 -1
  44. package/dist/agent/FigureBand.md +1 -1
  45. package/dist/agent/FloatingIconButton.md +1 -1
  46. package/dist/agent/FunnelChart.md +1 -1
  47. package/dist/agent/Heading.md +1 -1
  48. package/dist/agent/Heatmap.md +1 -1
  49. package/dist/agent/Histogram.md +1 -1
  50. package/dist/agent/Input.md +1 -1
  51. package/dist/agent/Kbd.md +1 -1
  52. package/dist/agent/LifecycleFigure.md +1 -1
  53. package/dist/agent/LineChart.md +1 -1
  54. package/dist/agent/LinkArrow.md +1 -1
  55. package/dist/agent/Markdown.md +1 -1
  56. package/dist/agent/NativeSelect.md +1 -1
  57. package/dist/agent/NavItem.md +1 -1
  58. package/dist/agent/NumberField.md +72 -0
  59. package/dist/agent/Pagination.md +1 -1
  60. package/dist/agent/PieChart.md +1 -1
  61. package/dist/agent/Popover.md +1 -1
  62. package/dist/agent/Progress.md +1 -1
  63. package/dist/agent/RadarChart.md +1 -1
  64. package/dist/agent/RadialChart.md +1 -1
  65. package/dist/agent/RadioGroup.md +1 -1
  66. package/dist/agent/SankeyChart.md +1 -1
  67. package/dist/agent/ScatterChart.md +1 -1
  68. package/dist/agent/ScrollArea.md +1 -1
  69. package/dist/agent/SearchableMenu.md +1 -1
  70. package/dist/agent/Select.md +1 -1
  71. package/dist/agent/Separator.md +1 -1
  72. package/dist/agent/SequenceFigure.md +1 -1
  73. package/dist/agent/Sheet.md +1 -1
  74. package/dist/agent/Sidebar.md +193 -0
  75. package/dist/agent/Skeleton.md +1 -1
  76. package/dist/agent/Slider.md +7 -3
  77. package/dist/agent/Sparkline.md +1 -1
  78. package/dist/agent/Spinner.md +1 -1
  79. package/dist/agent/StatusDot.md +1 -1
  80. package/dist/agent/StatusPill.md +1 -1
  81. package/dist/agent/Steps.md +1 -1
  82. package/dist/agent/Switch.md +1 -1
  83. package/dist/agent/Table.md +3 -1
  84. package/dist/agent/Tabs.md +1 -1
  85. package/dist/agent/Tag.md +1 -1
  86. package/dist/agent/Text.md +1 -1
  87. package/dist/agent/Textarea.md +1 -1
  88. package/dist/agent/Timestamp.md +1 -1
  89. package/dist/agent/Toast.md +1 -1
  90. package/dist/agent/ToggleGroup.md +1 -1
  91. package/dist/agent/Toolbar.md +1 -1
  92. package/dist/agent/Tooltip.md +1 -1
  93. package/dist/agent/TreemapChart.md +1 -1
  94. package/dist/agent/WaterfallChart.md +1 -1
  95. package/dist/agent/WorkflowFigure.md +1 -1
  96. package/dist/agent/catalog.json +361 -2
  97. package/dist/agent/index.md +8 -5
  98. package/dist/charts/BulletChart/BulletChart.js +16 -2
  99. package/dist/charts/BulletChart/BulletChart.js.map +1 -1
  100. package/dist/charts/RadarChart/RadarChart.js +4 -2
  101. package/dist/charts/RadarChart/RadarChart.js.map +1 -1
  102. package/dist/components/ColorPicker/ColorPicker.d.ts +67 -0
  103. package/dist/components/ColorPicker/ColorPicker.js +334 -0
  104. package/dist/components/ColorPicker/ColorPicker.js.map +1 -0
  105. package/dist/components/Command/Command.js +1 -1
  106. package/dist/components/Command/Command.js.map +1 -1
  107. package/dist/components/ContextMenu/ContextMenu.js +1 -1
  108. package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
  109. package/dist/components/Dialog/Dialog.js +1 -1
  110. package/dist/components/Dialog/Dialog.js.map +1 -1
  111. package/dist/components/DropdownMenu/DropdownMenu.js +1 -1
  112. package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
  113. package/dist/components/ErrorState/ErrorState.js +1 -1
  114. package/dist/components/ErrorState/ErrorState.js.map +1 -1
  115. package/dist/components/NavItem/NavItem.js +1 -1
  116. package/dist/components/NavItem/NavItem.js.map +1 -1
  117. package/dist/components/NumberField/NumberField.d.ts +69 -0
  118. package/dist/components/NumberField/NumberField.js +162 -0
  119. package/dist/components/NumberField/NumberField.js.map +1 -0
  120. package/dist/components/Popover/Popover.js +1 -1
  121. package/dist/components/Popover/Popover.js.map +1 -1
  122. package/dist/components/Select/Select.js +1 -1
  123. package/dist/components/Select/Select.js.map +1 -1
  124. package/dist/components/Sheet/Sheet.js +1 -1
  125. package/dist/components/Sheet/Sheet.js.map +1 -1
  126. package/dist/components/Sidebar/Sidebar.d.ts +349 -0
  127. package/dist/components/Sidebar/Sidebar.js +455 -0
  128. package/dist/components/Sidebar/Sidebar.js.map +1 -0
  129. package/dist/components/Slider/Slider.d.ts +22 -1
  130. package/dist/components/Slider/Slider.js +72 -8
  131. package/dist/components/Slider/Slider.js.map +1 -1
  132. package/dist/components/Table/Table.d.ts +14 -0
  133. package/dist/components/Table/Table.js.map +1 -1
  134. package/dist/components/Tabs/Tabs.js +7 -1
  135. package/dist/components/Tabs/Tabs.js.map +1 -1
  136. package/dist/diagrams/lib/route.d.ts +22 -1
  137. package/dist/diagrams/lib/route.js +24 -1
  138. package/dist/diagrams/lib/route.js.map +1 -1
  139. package/dist/diagrams/lib/wires.js +9 -5
  140. package/dist/diagrams/lib/wires.js.map +1 -1
  141. package/dist/index.d.ts +3 -0
  142. package/dist/index.js +3 -0
  143. package/dist/index.js.map +1 -1
  144. package/dist/lib/color.d.ts +80 -0
  145. package/dist/lib/color.js +189 -0
  146. package/dist/lib/color.js.map +1 -0
  147. package/dist/lib/numeric.d.ts +35 -0
  148. package/dist/lib/numeric.js +29 -0
  149. package/dist/lib/numeric.js.map +1 -0
  150. package/dist/styles.css +1 -1
  151. package/dist/themes.css +8 -0
  152. package/dist/tokens.css +66 -3
  153. package/dist/tokens.d.ts +3 -0
  154. package/dist/tokens.js +17 -0
  155. package/dist/tokens.json +17 -0
  156. package/package.json +1 -1
  157. package/skills/misoto22-design/rules/forms.md +3 -1
@@ -4,7 +4,7 @@ The system’s paragraph, on the second rung of the ink ladder.
4
4
 
5
5
  - Group: Display
6
6
  - Import: `import { Text } from '@misoto22/design'`
7
- - Version: 0.8.0
7
+ - Version: 0.9.0
8
8
  - Docs: https://ui.misoto22.com/components/text/
9
9
  - Related: heading, article, markdown
10
10
 
@@ -4,7 +4,7 @@ Multi-line text entry, resizable vertically only.
4
4
 
5
5
  - Group: Forms
6
6
  - Import: `import { Textarea } from '@misoto22/design'`
7
- - Version: 0.8.0
7
+ - Version: 0.9.0
8
8
  - Docs: https://ui.misoto22.com/components/textarea/
9
9
  - Related: input, field
10
10
 
@@ -4,7 +4,7 @@ A date or a time, rendered the one way the system renders them.
4
4
 
5
5
  - Group: Display
6
6
  - Import: `import { Timestamp } from '@misoto22/design'`
7
- - Version: 0.8.0
7
+ - Version: 0.9.0
8
8
  - Docs: https://ui.misoto22.com/components/timestamp/
9
9
  - Related: text, badge, description-list
10
10
 
@@ -4,7 +4,7 @@ A transient confirmation, mounted once near the app root.
4
4
 
5
5
  - Group: Feedback
6
6
  - Import: `import { Toast } from '@misoto22/design'`
7
- - Version: 0.8.0
7
+ - Version: 0.9.0
8
8
  - Docs: https://ui.misoto22.com/components/toast/
9
9
  - Related: alert
10
10
 
@@ -4,7 +4,7 @@ A segmented control: several options, one strip.
4
4
 
5
5
  - Group: Forms
6
6
  - Import: `import { ToggleGroup } from '@misoto22/design'`
7
- - Version: 0.8.0
7
+ - Version: 0.9.0
8
8
  - Docs: https://ui.misoto22.com/components/toggle-group/
9
9
  - Related: tabs, radio-group
10
10
 
@@ -4,7 +4,7 @@ The bar of actions at the edge of a working surface.
4
4
 
5
5
  - Group: Surfaces
6
6
  - Import: `import { Toolbar } from '@misoto22/design'`
7
- - Version: 0.8.0
7
+ - Version: 0.9.0
8
8
  - Docs: https://ui.misoto22.com/components/toolbar/
9
9
  - Related: button, app-shell, card
10
10
 
@@ -4,7 +4,7 @@ A short label on hover and on focus.
4
4
 
5
5
  - Group: Overlays
6
6
  - Import: `import { Tooltip } from '@misoto22/design'`
7
- - Version: 0.8.0
7
+ - Version: 0.9.0
8
8
  - Docs: https://ui.misoto22.com/components/tooltip/
9
9
  - Related: dialog
10
10
 
@@ -4,7 +4,7 @@ Part of a whole, when the whole has too many parts for a pie — and the parts n
4
4
 
5
5
  - Group: Charts
6
6
  - Import: `import { TreemapChart } from '@misoto22/design/charts'`
7
- - Version: 0.8.0
7
+ - Version: 0.9.0
8
8
  - Docs: https://ui.misoto22.com/components/treemap-chart/
9
9
  - Related: pie-chart, bar-chart
10
10
 
@@ -4,7 +4,7 @@ How a total got from one figure to another.
4
4
 
5
5
  - Group: Charts
6
6
  - Import: `import { WaterfallChart } from '@misoto22/design/charts'`
7
- - Version: 0.8.0
7
+ - Version: 0.9.0
8
8
  - Docs: https://ui.misoto22.com/components/waterfall-chart/
9
9
  - Related: bar-chart, funnel-chart
10
10
 
@@ -4,7 +4,7 @@ A process in lanes and phases, with the main path drawn heavier than its branche
4
4
 
5
5
  - Group: Diagrams
6
6
  - Import: `import { WorkflowFigure } from '@misoto22/design/diagrams'`
7
- - Version: 0.8.0
7
+ - Version: 0.9.0
8
8
  - Docs: https://ui.misoto22.com/components/workflow-figure/
9
9
  - Related: lifecycle-figure, sequence-figure, steps
10
10
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.8.0",
2
+ "version": "0.9.0",
3
3
  "groups": [
4
4
  "Actions",
5
5
  "Forms",
@@ -310,6 +310,87 @@
310
310
  "textarea"
311
311
  ]
312
312
  },
313
+ {
314
+ "slug": "number-field",
315
+ "entry": "@misoto22/design",
316
+ "name": "NumberField",
317
+ "group": "Forms",
318
+ "summary": "A number, typed or swept to.",
319
+ "when": "The number has a range and a sensible increment. A bare quantity is an Input with type=\"number\"; a value judged by WHERE it sits on a track is a Slider.",
320
+ "anatomy": [
321
+ {
322
+ "element": "Field",
323
+ "required": true,
324
+ "description": "A native number input wearing CONTROL_BASE, so it is the same box as Input, Textarea and Select — same padding, same focus, same disabled opacity. The native spinner buttons are hidden: they are three different controls in three browsers and none of them is this system’s."
325
+ },
326
+ {
327
+ "element": "Scrub grip",
328
+ "description": "A horizontal-arrows glyph at the inline start, on unless scrub is false. Dragging it changes the value by one step every 4px, ten steps with Shift held, and it follows the reading direction — in an RTL page, more is to the left. Pointer only and aria-hidden, because the keyboard already has the arrow keys."
329
+ },
330
+ {
331
+ "element": "Unit",
332
+ "description": "unit, drawn inside the end of the box and announced through aria-describedby. The slot is a fixed 3rem, so a unit longer than about four characters runs under a long number."
333
+ }
334
+ ],
335
+ "practices": [
336
+ {
337
+ "kind": "do",
338
+ "text": "Reach for it when a value is TUNED rather than entered — a duration, a line height, an offset. The grip is the whole argument for this over an Input: a reader finds those by sweeping past the neighbouring values, not by typing candidates one at a time."
339
+ },
340
+ {
341
+ "kind": "do",
342
+ "text": "Wrap it in a Field. The root is a div and the id lands on the input inside it, so the label binds and clicks through exactly as it does for an Input — but only if there is a Field to do it."
343
+ },
344
+ {
345
+ "kind": "do",
346
+ "text": "Pass min, max and step. They are what the arrows step by, what one notch of a scrub is worth, and what the value is reconciled with when the field is left; without them the control is an Input with a grip on it."
347
+ },
348
+ {
349
+ "kind": "dont",
350
+ "text": "Do not expect the range to hold mid-keystroke. Clamping happens on blur, not on every character, because a minimum of 10 otherwise makes 50 unreachable — the 5 is clamped up before the 0 arrives. onValueChange can report a number outside the range; the value that SETTLES is always inside it."
351
+ },
352
+ {
353
+ "kind": "dont",
354
+ "text": "Do not turn the grip off and expect a pointer to have another way through. There are no spinner buttons behind it — hiding those is the point — so scrub={false} leaves a mouse with typing and nothing else. Turn it off for a quantity that is chosen rather than swept to, and accept that trade knowingly."
355
+ },
356
+ {
357
+ "kind": "dont",
358
+ "text": "Do not put the unit in the box and nowhere else past about four characters. The slot is fixed, so “requests” runs under the number; a long unit belongs in the Field’s label, where it is read rather than clipped."
359
+ }
360
+ ],
361
+ "accessibility": [
362
+ "It is a real <input type=\"number\">, so the platform supplies the spinbutton role, the value, and the range it is announced against.",
363
+ "unit reaches assistive tech through aria-describedby, so “300” is not announced as a number with no dimension.",
364
+ "The grip is aria-hidden and not focusable: it commits nothing a keyboard cannot already reach, and announcing it would offer a reader a control that does nothing when they press it.",
365
+ "invalid and aria-invalid are read together, so a form library setting either one paints the same border."
366
+ ],
367
+ "keyboard": [
368
+ {
369
+ "keys": [
370
+ "↑",
371
+ "↓"
372
+ ],
373
+ "does": "Steps by one step, honouring min and max."
374
+ },
375
+ {
376
+ "keys": [
377
+ "Enter"
378
+ ],
379
+ "does": "Reconciles what has been typed with the range and the step."
380
+ },
381
+ {
382
+ "keys": [
383
+ "Escape"
384
+ ],
385
+ "does": "Abandons the edit and restores the last settled value."
386
+ }
387
+ ],
388
+ "related": [
389
+ "input",
390
+ "slider",
391
+ "field"
392
+ ]
393
+ },
313
394
  {
314
395
  "slug": "textarea",
315
396
  "entry": "@misoto22/design",
@@ -925,6 +1006,112 @@
925
1006
  "field"
926
1007
  ]
927
1008
  },
1009
+ {
1010
+ "slug": "color-picker",
1011
+ "entry": "@misoto22/design",
1012
+ "name": "ColorPicker",
1013
+ "group": "Forms",
1014
+ "summary": "A colour, chosen or typed.",
1015
+ "when": "A person is choosing the colour. A colour that is merely being SHOWN is a swatch, and a set of fixed brand colours is a RadioGroup — a picker offers sixteen million answers to a question with six.",
1016
+ "anatomy": [
1017
+ {
1018
+ "element": "Trigger",
1019
+ "required": true,
1020
+ "description": "The closed control: a swatch, then the value as text, in the same box as Input and Select. Named by its label AND by its own value, so a reader hears “Brand colour, #a78bfa” rather than either half."
1021
+ },
1022
+ {
1023
+ "element": "Swatch",
1024
+ "description": "The colour over a checkerboard, so a half-transparent value reads as transparent rather than as a paler colour."
1025
+ },
1026
+ {
1027
+ "element": "Notation strip",
1028
+ "description": "Hex, OKLCH and Display P3, as a single-value ToggleGroup. It changes what onValueChange emits, not what the colour is — and hex and P3 are bounded, so switching to one of them fits the colour to that gamut on the way out."
1029
+ },
1030
+ {
1031
+ "element": "Field",
1032
+ "required": true,
1033
+ "description": "The plane: chroma across, lightness up. Each ROW is normalised to the most chroma that exists at that lightness and hue, so the whole surface is reachable instead of a lens of colour inside bands of clipped duplicates. Underneath it are two real sliders rather than key handlers on a canvas, which is what gives it arrows, Home, End and an announced position."
1034
+ },
1035
+ {
1036
+ "element": "Hue track",
1037
+ "description": "A ramp taken at the lightness and chroma already chosen, not a generic rainbow — so the strip shows the hues of THIS colour rather than of some other one."
1038
+ },
1039
+ {
1040
+ "element": "Opacity track",
1041
+ "description": "Transparent to the current colour, over the same checkerboard as the swatch."
1042
+ },
1043
+ {
1044
+ "element": "CSS box",
1045
+ "description": "The value as text. Accepts hex, rgb(), hsl(), oklch() and color(display-p3 …) in both syntaxes, and paints itself invalid on anything else."
1046
+ }
1047
+ ],
1048
+ "practices": [
1049
+ {
1050
+ "kind": "do",
1051
+ "text": "Wrap it in a Field. The trigger is a button, which a label binds to and clicks through — one of the few composites where that works without help."
1052
+ },
1053
+ {
1054
+ "kind": "do",
1055
+ "text": "Pass the notation you want back. The panel emits in whatever notation the value arrived in until somebody changes it in the strip, so a defaultValue of \"#a78bfa\" keeps a consumer in hex."
1056
+ },
1057
+ {
1058
+ "kind": "do",
1059
+ "text": "Reach for this over <input type=\"color\"> when the colours are being TUNED. The native picker works in HSV, where a row of constant lightness visibly darkens as it saturates — so a reader building a palette is fighting the instrument. OKLCH is the space where two colours at the same height genuinely match."
1060
+ },
1061
+ {
1062
+ "kind": "dont",
1063
+ "text": "Do not pass a named colour. Hex, rgb(), hsl(), oklch() and color(display-p3 …) parse; \"rebeccapurple\" does not, and the box will show it as invalid. Resolving names needs a table of every CSS keyword or a live DOM, and a picker that takes some names and not others is worse than one that takes none."
1064
+ },
1065
+ {
1066
+ "kind": "dont",
1067
+ "text": "Do not read the emitted string as a fixed notation. It is whatever the strip is set to, so a consumer that slices a \"#\" off the front breaks the first time a reader picks OKLCH."
1068
+ },
1069
+ {
1070
+ "kind": "dont",
1071
+ "text": "Do not use it to pick text or background colour and call the result accessible. Nothing here measures contrast; a picker that lets a reader choose #eeeeee for body copy is doing exactly what it was asked."
1072
+ }
1073
+ ],
1074
+ "accessibility": [
1075
+ "label is required. The trigger shows a value, and a value is not a name.",
1076
+ "The plane is a group of two real sliders — Chroma and Lightness — each announced with a percentage, so the 2D surface is operable and reported rather than merely clickable.",
1077
+ "The focus ring is drawn on the plane, because the sliders that take the focus are visually hidden and the browser’s own ring is clipped away with them.",
1078
+ "Alpha is doubled by a checkerboard everywhere it is shown, so transparency is not carried by lightness alone."
1079
+ ],
1080
+ "keyboard": [
1081
+ {
1082
+ "keys": [
1083
+ "Enter",
1084
+ "Space"
1085
+ ],
1086
+ "does": "Opens the panel."
1087
+ },
1088
+ {
1089
+ "keys": [
1090
+ "←",
1091
+ "→"
1092
+ ],
1093
+ "does": "Moves the focused axis or track by one step."
1094
+ },
1095
+ {
1096
+ "keys": [
1097
+ "Home",
1098
+ "End"
1099
+ ],
1100
+ "does": "Jumps that axis or track to its ends."
1101
+ },
1102
+ {
1103
+ "keys": [
1104
+ "Escape"
1105
+ ],
1106
+ "does": "Closes the panel; focus returns to the trigger."
1107
+ }
1108
+ ],
1109
+ "related": [
1110
+ "field",
1111
+ "input",
1112
+ "popover"
1113
+ ]
1114
+ },
928
1115
  {
929
1116
  "slug": "slider",
930
1117
  "entry": "@misoto22/design",
@@ -948,6 +1135,10 @@
948
1135
  {
949
1136
  "element": "Value readout",
950
1137
  "description": "Only with showValue: a mono row above the track, the names on the start edge and the formatted values on the end, each joined by an en dash and in the thumbs’ own order — so a two-ended range reads “Minimum – Maximum” over “10 – 90”."
1138
+ },
1139
+ {
1140
+ "element": "Editable readout",
1141
+ "description": "What editable turns those figures into: one box per thumb, showing format’s output at rest and the bare number while it has focus, so a reader still sees “$1,200” and a typist is never asked to type a currency symbol back. Each is named separately from its thumb — two controls announcing “Quality” is one control announced twice."
951
1142
  }
952
1143
  ],
953
1144
  "practices": [
@@ -961,12 +1152,16 @@
961
1152
  },
962
1153
  {
963
1154
  "kind": "do",
964
- "text": "Put an Input beside it when the exact number matters. A slider cannot be typed into, and someone who needs 37 rather than roughly 40 is dragging a 16px thumb across a hundred steps to get it."
1155
+ "text": "Turn on editable when the exact number matters. A slider on its own cannot be typed into, and someone who needs 37 rather than roughly 40 is dragging a 16px thumb across a hundred steps to get it — the box in the readout is the way out, and it replaces the second Input this used to ask for."
965
1156
  },
966
1157
  {
967
1158
  "kind": "dont",
968
1159
  "text": "format becomes each thumb’s aria-valuetext, which REPLACES the number rather than decorating it — so a formatter that rounds hard or drops the unit is what a screen reader gets instead of the value."
969
1160
  },
1161
+ {
1162
+ "kind": "dont",
1163
+ "text": "editable typing is bounded by the NEIGHBOURING thumb as well as by min and max, and it has to be: 90 typed into the lower end of a range sitting at 70 would otherwise cross the two thumbs over. So a number can be accepted and then land somewhere else, and the box shows where it landed."
1164
+ },
970
1165
  {
971
1166
  "kind": "dont",
972
1167
  "text": "Do not disable a slider to make it read-only: the whole control dims and stops taking the pointer, and Radix drops the thumb out of the tab order, so the value becomes unreachable rather than uneditable."
@@ -1412,6 +1607,148 @@
1412
1607
  "breadcrumb"
1413
1608
  ]
1414
1609
  },
1610
+ {
1611
+ "slug": "sidebar",
1612
+ "entry": "@misoto22/design",
1613
+ "name": "Sidebar",
1614
+ "group": "Navigation",
1615
+ "summary": "A navigation rail down the side of an application.",
1616
+ "when": "A whole application’s navigation, in a column that stays. A list of links inside a page is NavItem on its own; a strip of panels is Tabs.",
1617
+ "anatomy": [
1618
+ {
1619
+ "element": "Provider",
1620
+ "required": true,
1621
+ "description": "SidebarProvider. It holds whether the rail is open and binds the shortcut that changes it, and it sits ABOVE both the rail and the content beside it — the page has to reserve the rail’s width, and a state that lived inside the rail could only ever be read downwards. It also supplies the tooltip provider a collapsed rail needs, so the icon state works without the app being told to wrap itself in one."
1622
+ },
1623
+ {
1624
+ "element": "Rail",
1625
+ "required": true,
1626
+ "description": "Sidebar. A <nav>, not an <aside>: the element decides the landmark, and a rail of links announced as “complementary” is not the one a reader jumps to when they go looking for the navigation. Its width animates between --sidebar-w and --sidebar-w-icon while the column inside stays full width, so the rows do not reflow under the wipe."
1627
+ },
1628
+ {
1629
+ "element": "Header",
1630
+ "description": "SidebarHeader. The brand, the workspace, the switcher — and where SidebarTrigger belongs. A control that hides a thing lives on the thing; out in an application’s masthead it is one more anonymous icon with nothing connecting it to the column it operates."
1631
+ },
1632
+ {
1633
+ "element": "Content",
1634
+ "description": "SidebarContent. The scrolling middle, and the only part that scrolls."
1635
+ },
1636
+ {
1637
+ "element": "Group",
1638
+ "description": "SidebarGroup: a heading, an optional count, an optional action, and rows behind a hairline. The heading is the same size as its rows and outranks them by weight and one step of ink — smaller than what it contains, it reads as a footnote over a list rather than as a title over its own contents."
1639
+ },
1640
+ {
1641
+ "element": "Row",
1642
+ "description": "SidebarItem, which is NavItem plus the two things a rail adds: a trailing slot, and an answer for the state with no room for words. Collapsed, the label leaves the layout and becomes the row’s tooltip."
1643
+ },
1644
+ {
1645
+ "element": "Branch",
1646
+ "description": "SidebarBranch: a row that opens onto more rows, behind the same hairline a group draws and one indent further in. It is the line between a place and a heading — a workspace that contains projects is a place containing places, and it carries an icon and a state the way its children do, which a Group has neither of. Two levels is what the indent has room for; a third in a 16rem column is a horizontal scrollbar with an outline in it."
1647
+ },
1648
+ {
1649
+ "element": "Footer",
1650
+ "description": "SidebarFooter. The utilities a rail ends on, kept out of the index above it."
1651
+ },
1652
+ {
1653
+ "element": "Page",
1654
+ "description": "SidebarInset, the column beside the rail. It is `min-w-0` — the half every hand-written version forgets, and the reason one wide table inside pushes the page past the viewport and takes the rail’s width with it. Under variant=\"inset\" it is also the panel: the rail becomes the ground, and this draws the bordered --paper surface sitting on it."
1655
+ },
1656
+ {
1657
+ "element": "Drawer",
1658
+ "description": "What the rail becomes under the provider’s breakpoint (768px by default): fixed against its own edge, over a scrim, and inert while closed. Nothing to render — the same <Sidebar> is both — but it is a different component to a reader, and the collapsible setting does not apply there."
1659
+ }
1660
+ ],
1661
+ "practices": [
1662
+ {
1663
+ "kind": "do",
1664
+ "text": "Give every row an icon if the rail collapses to icons. The icon is the whole of what a collapsed row shows, and SidebarItem keeps the label drawn on a row without one rather than leaving a blank line — which is a rail that is half collapsed."
1665
+ },
1666
+ {
1667
+ "kind": "do",
1668
+ "text": "Choose collapsible by what the rows ARE. icon suits a fixed set a reader learns the shape of; offcanvas suits a long index nobody memorises, where a column of unrecognisable glyphs is worse than no column."
1669
+ },
1670
+ {
1671
+ "kind": "do",
1672
+ "text": "Reach for SidebarBranch when the thing is a PLACE that contains places, and for SidebarGroup when it is a heading over a set. A group has no icon and no state because it is not somewhere you can be; a branch has both because it is."
1673
+ },
1674
+ {
1675
+ "kind": "do",
1676
+ "text": "Put SidebarTrigger in the header. It is where the component expects it and where a reader looks for it, and it is the difference between a control that belongs to the rail and one that has wandered into the masthead."
1677
+ },
1678
+ {
1679
+ "kind": "dont",
1680
+ "text": "Do not reach for it for navigation inside a page. This is an application landmark that owns a whole edge of the window; a set of links in a column is NavItem, and putting those in a rail gives a page two navigation landmarks competing for the same reader."
1681
+ },
1682
+ {
1683
+ "kind": "dont",
1684
+ "text": "Do not pass shortcut and then bind Cmd+B yourself. Two handlers on one chord toggle twice and land back where they started, which reads as a rail that ignores its own shortcut. Pass shortcut={null} where the app owns it."
1685
+ },
1686
+ {
1687
+ "kind": "dont",
1688
+ "text": "Do not nest a branch inside a branch. The indent is sized for two levels at this width, and a third takes the words with it — what a reader gets is an outline with a horizontal scrollbar under it."
1689
+ },
1690
+ {
1691
+ "kind": "dont",
1692
+ "text": "Do not control open without onOpenChange. The trigger and the shortcut then both do nothing, and the state that looks broken is the one the caller froze."
1693
+ },
1694
+ {
1695
+ "kind": "do",
1696
+ "text": "Wrap the page in SidebarInset rather than a hand-written flex column. It carries min-w-0, which is what stops one wide table inside the page from pushing the whole layout past the viewport, and it is the other half of variant=\"inset\"."
1697
+ },
1698
+ {
1699
+ "kind": "do",
1700
+ "text": "Pass persist with a key when the rail is an application’s own. A reader who put the rail away did not mean “until the next page”. Only the docked state is kept: restoring an open drawer is a page that loads with its navigation over the top of itself."
1701
+ },
1702
+ {
1703
+ "kind": "do",
1704
+ "text": "Give the provider a ground for variant=\"floating\" and variant=\"inset\" — bg-(--stone) on the element holding it. Both draw a --paper panel, and a panel on the same colour as the thing behind it is a border with nothing on either side of it."
1705
+ },
1706
+ {
1707
+ "kind": "dont",
1708
+ "text": "Do not put a transform, filter or perspective on an element wrapping the provider. The drawer is fixed, and any of those makes that ancestor its containing block — so it opens inside the wrapper instead of against the edge of the window."
1709
+ },
1710
+ {
1711
+ "kind": "dont",
1712
+ "text": "Do not build the phone drawer yourself around this. It already is one under breakpoint, with the scrim, the inert closed state and the close-on-navigate; a second one outside gives the page two drawers and one of them has no scrim."
1713
+ }
1714
+ ],
1715
+ "accessibility": [
1716
+ "label is required, and names the landmark. A page with two navigations in it announces two things called “navigation” unless each says which it is.",
1717
+ "The trigger’s name says what it will DO and aria-expanded reports what is true now, so it is never the permanently ambiguous “Toggle sidebar”.",
1718
+ "A collapsed row keeps its label as its accessible name, through a tooltip — an icon alone is a guess for a sighted reader and nothing at all for a screen reader.",
1719
+ "A collapsed group keeps its heading as the group’s name even though the words are not drawn.",
1720
+ "The current row carries aria-current=\"page\", not only a darker ground.",
1721
+ "The closed drawer is inert, not merely translated off-screen. Off-screen it still holds focus and is still read aloud, so a shut drawer puts its whole index between the reader and the page they were on.",
1722
+ "The scrim is a button with a name, because tapping beside a drawer is how a drawer is closed — and a gesture that exists only for a pointer is one a keyboard cannot make."
1723
+ ],
1724
+ "keyboard": [
1725
+ {
1726
+ "keys": [
1727
+ "⌘B",
1728
+ "Ctrl B"
1729
+ ],
1730
+ "does": "Opens and closes the rail."
1731
+ },
1732
+ {
1733
+ "keys": [
1734
+ "Enter",
1735
+ "Space"
1736
+ ],
1737
+ "does": "On a group heading, folds or unfolds it."
1738
+ },
1739
+ {
1740
+ "keys": [
1741
+ "Tab"
1742
+ ],
1743
+ "does": "Moves through the rows in the order they are drawn."
1744
+ }
1745
+ ],
1746
+ "related": [
1747
+ "nav-item",
1748
+ "collapsible",
1749
+ "app-shell"
1750
+ ]
1751
+ },
1415
1752
  {
1416
1753
  "slug": "nav-item",
1417
1754
  "entry": "@misoto22/design",
@@ -6666,6 +7003,7 @@
6666
7003
  "CollapsibleTrigger": "Collapsible",
6667
7004
  "CollapsibleContent": "Collapsible",
6668
7005
  "CollapsibleSection": "Collapsible",
7006
+ "ColorPicker": "ColorPicker",
6669
7007
  "Combobox": "Combobox",
6670
7008
  "Command": "Command",
6671
7009
  "CommandInput": "Command",
@@ -6719,6 +7057,7 @@
6719
7057
  "Markdown": "Markdown",
6720
7058
  "NativeSelect": "NativeSelect",
6721
7059
  "NavItem": "NavItem",
7060
+ "NumberField": "NumberField",
6722
7061
  "paginationRange": "Pagination",
6723
7062
  "Pagination": "Pagination",
6724
7063
  "Popover": "Popover",
@@ -6743,6 +7082,22 @@
6743
7082
  "SheetClose": "Sheet",
6744
7083
  "SheetContent": "Sheet",
6745
7084
  "SheetSide": "Sheet",
7085
+ "useSidebar": "Sidebar",
7086
+ "SidebarProvider": "Sidebar",
7087
+ "Sidebar": "Sidebar",
7088
+ "SidebarInset": "Sidebar",
7089
+ "SidebarHeader": "Sidebar",
7090
+ "SidebarContent": "Sidebar",
7091
+ "SidebarFooter": "Sidebar",
7092
+ "SidebarSeparator": "Sidebar",
7093
+ "SidebarTrigger": "Sidebar",
7094
+ "SidebarGroup": "Sidebar",
7095
+ "SidebarBranch": "Sidebar",
7096
+ "SidebarItem": "Sidebar",
7097
+ "SidebarCollapsible": "Sidebar",
7098
+ "SidebarSide": "Sidebar",
7099
+ "SidebarVariant": "Sidebar",
7100
+ "SidebarBreakpoint": "Sidebar",
6746
7101
  "Skeleton": "Skeleton",
6747
7102
  "SkeletonLine": "Skeleton",
6748
7103
  "SkeletonBlock": "Skeleton",
@@ -6857,6 +7212,7 @@
6857
7212
  {
6858
7213
  "axis": "data-density",
6859
7214
  "values": [
7215
+ "comfortable",
6860
7216
  "compact"
6861
7217
  ],
6862
7218
  "unset": "comfortable"
@@ -6889,6 +7245,7 @@
6889
7245
  "axis": "data-rules",
6890
7246
  "values": [
6891
7247
  "firm",
7248
+ "hairline",
6892
7249
  "quiet"
6893
7250
  ],
6894
7251
  "unset": "hairline"
@@ -6898,6 +7255,7 @@
6898
7255
  "values": [
6899
7256
  "cool",
6900
7257
  "glass",
7258
+ "paper",
6901
7259
  "warm"
6902
7260
  ],
6903
7261
  "unset": "paper"
@@ -6913,6 +7271,7 @@
6913
7271
  "axis": "data-type",
6914
7272
  "values": [
6915
7273
  "bookish",
7274
+ "editorial",
6916
7275
  "grotesk"
6917
7276
  ],
6918
7277
  "unset": "editorial"
@@ -1,4 +1,4 @@
1
- # @misoto22/design 0.8.0
1
+ # @misoto22/design 0.9.0
2
2
 
3
3
  > Monochrome design system: portable CSS tokens and accessible React 19
4
4
  > primitives. Components ship compiled — import them, do not copy them.
@@ -17,14 +17,14 @@ Attributes, independent, and they work on any element — not just the root.
17
17
  An unset axis is the default.
18
18
 
19
19
  - `data-chart-palette`: `chroma` (unset = the neutral series ramp)
20
- - `data-density`: `compact` (unset = comfortable)
20
+ - `data-density`: `comfortable` `compact` (unset = comfortable)
21
21
  - `data-mode`: `dark` `light` (unset = follows the app)
22
22
  - `data-motion`: `snappy` `still` (unset = calm)
23
23
  - `data-radius`: `round` `sharp` (unset = the default radius ladder)
24
- - `data-rules`: `firm` `quiet` (unset = hairline)
25
- - `data-surface`: `cool` `glass` `warm` (unset = paper)
24
+ - `data-rules`: `firm` `hairline` `quiet` (unset = hairline)
25
+ - `data-surface`: `cool` `glass` `paper` `warm` (unset = paper)
26
26
  - `data-table-density`: `compact` (unset = comfortable — whatever `data-density` is doing around it)
27
- - `data-type`: `bookish` `grotesk` (unset = editorial)
27
+ - `data-type`: `bookish` `editorial` `grotesk` (unset = editorial)
28
28
 
29
29
  There is no `data-accent` attribute: `--accent` is a CSS custom property,
30
30
  re-pointed in a stylesheet.
@@ -40,6 +40,7 @@ re-pointed in a stylesheet.
40
40
 
41
41
  - **Field** — A labelled form row: label, control, and the one message below it — and, in row layout, the settings row.
42
42
  - **Input** — A single line of text entry.
43
+ - **NumberField** — A number, typed or swept to.
43
44
  - **Textarea** — Multi-line text entry, resizable vertically only.
44
45
  - **Select** — A choice from a list, styled the whole way down.
45
46
  - **NativeSelect** — The platform’s own picker, restyled where it can be.
@@ -48,6 +49,7 @@ re-pointed in a stylesheet.
48
49
  - **Switch** — A setting that takes effect immediately.
49
50
  - **Combobox** — A select you can type into.
50
51
  - **DatePicker** — A date — or a span of them — chosen from a calendar.
52
+ - **ColorPicker** — A colour, chosen or typed.
51
53
  - **Slider** — A value chosen along a range.
52
54
  - **ToggleGroup** — A segmented control: several options, one strip.
53
55
 
@@ -57,6 +59,7 @@ re-pointed in a stylesheet.
57
59
  - **Accordion** — Disclosure rows that open in place.
58
60
  - **Breadcrumb** — Where you are, as a path.
59
61
  - **Pagination** — Numbered pages, with the middle elided.
62
+ - **Sidebar** — A navigation rail down the side of an application.
60
63
  - **NavItem** — A row in a sidebar.
61
64
  - **Collapsible** — One thing that opens, on its own.
62
65
 
@@ -143,12 +143,26 @@ function BulletRow({
143
143
  targetShare !== null && // A rule ACROSS the bar rather than a second bar beside it: the two
144
144
  // are different kinds of number, and the reader has to be able to
145
145
  // tell at a glance which one was achieved and which was asked for.
146
+ //
147
+ // The paper halo is what makes that true where the rule lands ON the
148
+ // bar. Both are drawn in --ink, so a target inside the achieved range
149
+ // — which is every measure that is doing well — was an ink rule on an
150
+ // ink bar and simply not there.
146
151
  /* @__PURE__ */ jsx(
147
152
  "span",
148
153
  {
149
154
  "data-slot": "bullet-target",
150
- className: "absolute inset-y-1 block w-0.5 bg-(--ink)",
151
- style: { insetInlineStart: pct(targetShare), marginInlineStart: "-1px" }
155
+ className: "absolute inset-y-1 block w-0.5 bg-(--ink) shadow-[0_0_0_1px_var(--paper)]",
156
+ style: {
157
+ insetInlineStart: pct(targetShare),
158
+ // Pulled back by its own width in PROPORTION to where it sits:
159
+ // flush at the start at 0, centred in the middle, flush at the end
160
+ // at 1. A fixed half-width pull put a target of zero half outside
161
+ // the track, where `overflow-hidden` took it — so "Open incidents,
162
+ // target 0" drew no target at all, on the one measure whose whole
163
+ // point is the distance from it.
164
+ marginInlineStart: `${-2 * targetShare}px`
165
+ }
152
166
  }
153
167
  ),
154
168
  runsOver && // Clamped and silent, a number past the end of the scale fills the