@twoux/ui 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (325) hide show
  1. package/LICENSE.md +61 -0
  2. package/LICENSES/Apache-2.0.txt +202 -0
  3. package/NOTICE.md +64 -0
  4. package/README.md +211 -2
  5. package/SHADCN-DIFF.md +228 -0
  6. package/agent/AGENTS.md +358 -0
  7. package/agent/docs-md/accessibility.md +49 -0
  8. package/agent/docs-md/action-catalogue.md +81 -0
  9. package/agent/docs-md/actions.md +74 -0
  10. package/agent/docs-md/agent-activity-log.md +70 -0
  11. package/agent/docs-md/agent-permissions.md +82 -0
  12. package/agent/docs-md/agent-run.md +90 -0
  13. package/agent/docs-md/agents-on-behalf.md +74 -0
  14. package/agent/docs-md/ai-column.md +85 -0
  15. package/agent/docs-md/ai-origin-label.md +70 -0
  16. package/agent/docs-md/announcing-features.md +73 -0
  17. package/agent/docs-md/answer-actions.md +81 -0
  18. package/agent/docs-md/app-shell.md +114 -0
  19. package/agent/docs-md/artifact-card.md +89 -0
  20. package/agent/docs-md/ask-on-screen.md +72 -0
  21. package/agent/docs-md/assistant-page.md +100 -0
  22. package/agent/docs-md/assistant-panel.md +142 -0
  23. package/agent/docs-md/avatar.md +82 -0
  24. package/agent/docs-md/banner.md +106 -0
  25. package/agent/docs-md/board.md +163 -0
  26. package/agent/docs-md/breadcrumb.md +89 -0
  27. package/agent/docs-md/breakdown-table.md +97 -0
  28. package/agent/docs-md/bulk-action-bar.md +112 -0
  29. package/agent/docs-md/button.md +293 -0
  30. package/agent/docs-md/card.md +115 -0
  31. package/agent/docs-md/change-list.md +99 -0
  32. package/agent/docs-md/change-request.md +166 -0
  33. package/agent/docs-md/chart-area.md +87 -0
  34. package/agent/docs-md/chart-bar.md +100 -0
  35. package/agent/docs-md/chart-box-plot.md +88 -0
  36. package/agent/docs-md/chart-bullet.md +89 -0
  37. package/agent/docs-md/chart-candlestick.md +112 -0
  38. package/agent/docs-md/chart-card-line.md +120 -0
  39. package/agent/docs-md/chart-donut.md +90 -0
  40. package/agent/docs-md/chart-drill-down.md +72 -0
  41. package/agent/docs-md/chart-funnel.md +71 -0
  42. package/agent/docs-md/chart-heatmap.md +76 -0
  43. package/agent/docs-md/chart-histogram.md +81 -0
  44. package/agent/docs-md/chart-map.md +165 -0
  45. package/agent/docs-md/chart-mixed.md +88 -0
  46. package/agent/docs-md/chart-price.md +92 -0
  47. package/agent/docs-md/chart-radial-bars.md +109 -0
  48. package/agent/docs-md/chart-radial-lines.md +111 -0
  49. package/agent/docs-md/chart-sankey.md +104 -0
  50. package/agent/docs-md/chart-scatter.md +87 -0
  51. package/agent/docs-md/chart-share-bar.md +89 -0
  52. package/agent/docs-md/chart-treemap.md +98 -0
  53. package/agent/docs-md/chart-waterfall.md +93 -0
  54. package/agent/docs-md/checkbox.md +131 -0
  55. package/agent/docs-md/choosing-selection-control.md +71 -0
  56. package/agent/docs-md/citations-sources.md +79 -0
  57. package/agent/docs-md/citing-sources.md +63 -0
  58. package/agent/docs-md/clarify-before-acting.md +69 -0
  59. package/agent/docs-md/clarifying-question.md +92 -0
  60. package/agent/docs-md/code-block.md +174 -0
  61. package/agent/docs-md/colours.md +87 -0
  62. package/agent/docs-md/columns-menu.md +140 -0
  63. package/agent/docs-md/combobox.md +161 -0
  64. package/agent/docs-md/command-palette.md +126 -0
  65. package/agent/docs-md/confidence-note.md +87 -0
  66. package/agent/docs-md/configurable-dashboard.md +76 -0
  67. package/agent/docs-md/confirmation-dialog.md +93 -0
  68. package/agent/docs-md/connected-tools.md +80 -0
  69. package/agent/docs-md/connector-picker.md +127 -0
  70. package/agent/docs-md/consistency.md +53 -0
  71. package/agent/docs-md/content-density.md +61 -0
  72. package/agent/docs-md/conversation-history.md +78 -0
  73. package/agent/docs-md/create-record.md +80 -0
  74. package/agent/docs-md/csv-import.md +88 -0
  75. package/agent/docs-md/dashboard-items.md +78 -0
  76. package/agent/docs-md/data-export.md +61 -0
  77. package/agent/docs-md/data-grid.md +137 -0
  78. package/agent/docs-md/data-vis-colours.md +76 -0
  79. package/agent/docs-md/data-visualisation.md +76 -0
  80. package/agent/docs-md/date-picker.md +178 -0
  81. package/agent/docs-md/delete-record.md +75 -0
  82. package/agent/docs-md/dense-table.md +495 -0
  83. package/agent/docs-md/design-tokens.md +53 -0
  84. package/agent/docs-md/disabled-read-only.md +75 -0
  85. package/agent/docs-md/drag-and-drop.md +74 -0
  86. package/agent/docs-md/dropdown-menu.md +137 -0
  87. package/agent/docs-md/edit-record.md +73 -0
  88. package/agent/docs-md/empty-loading-error.md +78 -0
  89. package/agent/docs-md/empty-state.md +128 -0
  90. package/agent/docs-md/error-messages.md +75 -0
  91. package/agent/docs-md/error-state.md +123 -0
  92. package/agent/docs-md/export-menu.md +86 -0
  93. package/agent/docs-md/feedback-prompt.md +88 -0
  94. package/agent/docs-md/field-mapping.md +78 -0
  95. package/agent/docs-md/file-drop.md +110 -0
  96. package/agent/docs-md/filter-bar.md +138 -0
  97. package/agent/docs-md/filter-panel.md +103 -0
  98. package/agent/docs-md/filtering-search.md +79 -0
  99. package/agent/docs-md/follow-ups-starters.md +79 -0
  100. package/agent/docs-md/form-validation.md +95 -0
  101. package/agent/docs-md/generated-columns.md +65 -0
  102. package/agent/docs-md/generated-drafts-files.md +71 -0
  103. package/agent/docs-md/grouped-list.md +89 -0
  104. package/agent/docs-md/guide-cue.md +170 -0
  105. package/agent/docs-md/help-panel.md +103 -0
  106. package/agent/docs-md/help-system.md +74 -0
  107. package/agent/docs-md/iconography.md +49 -0
  108. package/agent/docs-md/inbox.md +108 -0
  109. package/agent/docs-md/inline-editing-validation.md +80 -0
  110. package/agent/docs-md/inline-input-in-answer.md +70 -0
  111. package/agent/docs-md/items-palette.md +116 -0
  112. package/agent/docs-md/keyboard-model.md +47 -0
  113. package/agent/docs-md/keyboard-navigation.md +68 -0
  114. package/agent/docs-md/keyboard-shortcut-hint.md +87 -0
  115. package/agent/docs-md/keyboard-shortcut-sheet.md +90 -0
  116. package/agent/docs-md/labelling-ai-output.md +66 -0
  117. package/agent/docs-md/layout.md +47 -0
  118. package/agent/docs-md/list-table.md +254 -0
  119. package/agent/docs-md/loading-skeleton.md +91 -0
  120. package/agent/docs-md/managing-agents.md +71 -0
  121. package/agent/docs-md/message-composer.md +105 -0
  122. package/agent/docs-md/migrating.md +49 -0
  123. package/agent/docs-md/motion.md +93 -0
  124. package/agent/docs-md/navigation.md +76 -0
  125. package/agent/docs-md/notification-channels.md +65 -0
  126. package/agent/docs-md/notifications-decision.md +100 -0
  127. package/agent/docs-md/onboarding-step.md +114 -0
  128. package/agent/docs-md/order-book.md +108 -0
  129. package/agent/docs-md/page-header.md +96 -0
  130. package/agent/docs-md/pagination.md +88 -0
  131. package/agent/docs-md/pane-layout.md +105 -0
  132. package/agent/docs-md/period-comparison.md +66 -0
  133. package/agent/docs-md/plan-card.md +120 -0
  134. package/agent/docs-md/popover-rules.md +88 -0
  135. package/agent/docs-md/prompt-editor.md +90 -0
  136. package/agent/docs-md/propose-apply.md +65 -0
  137. package/agent/docs-md/provider-logo.md +97 -0
  138. package/agent/docs-md/radio.md +83 -0
  139. package/agent/docs-md/ranked-list.md +102 -0
  140. package/agent/docs-md/reasoning-progress.md +72 -0
  141. package/agent/docs-md/record-detail.md +71 -0
  142. package/agent/docs-md/regenerating-answers.md +70 -0
  143. package/agent/docs-md/run-status-bar.md +94 -0
  144. package/agent/docs-md/saved-tasks-schedules.md +63 -0
  145. package/agent/docs-md/saved-views.md +149 -0
  146. package/agent/docs-md/saving-views.md +68 -0
  147. package/agent/docs-md/scheduler.md +258 -0
  148. package/agent/docs-md/secondary-panels.md +72 -0
  149. package/agent/docs-md/segmented-control.md +88 -0
  150. package/agent/docs-md/selection-bulk-actions.md +70 -0
  151. package/agent/docs-md/separator.md +75 -0
  152. package/agent/docs-md/setup-checklist.md +92 -0
  153. package/agent/docs-md/shape-elevation.md +55 -0
  154. package/agent/docs-md/sheet-grid.md +211 -0
  155. package/agent/docs-md/side-panel.md +134 -0
  156. package/agent/docs-md/sign-in.md +114 -0
  157. package/agent/docs-md/spacing.md +55 -0
  158. package/agent/docs-md/split-button.md +100 -0
  159. package/agent/docs-md/stat-compare.md +82 -0
  160. package/agent/docs-md/static-dashboard.md +75 -0
  161. package/agent/docs-md/status-badge.md +140 -0
  162. package/agent/docs-md/step-card.md +75 -0
  163. package/agent/docs-md/stepper.md +92 -0
  164. package/agent/docs-md/suggested-changes.md +91 -0
  165. package/agent/docs-md/switch.md +78 -0
  166. package/agent/docs-md/table-settings.md +81 -0
  167. package/agent/docs-md/tabs.md +85 -0
  168. package/agent/docs-md/tag-input.md +108 -0
  169. package/agent/docs-md/tag.md +79 -0
  170. package/agent/docs-md/task-builder.md +87 -0
  171. package/agent/docs-md/team-instructions.md +72 -0
  172. package/agent/docs-md/templates-gallery.md +85 -0
  173. package/agent/docs-md/text-input.md +160 -0
  174. package/agent/docs-md/thinking-steps.md +89 -0
  175. package/agent/docs-md/timeline.md +189 -0
  176. package/agent/docs-md/timestamp.md +84 -0
  177. package/agent/docs-md/timestamps.md +70 -0
  178. package/agent/docs-md/toast.md +117 -0
  179. package/agent/docs-md/tooltip.md +90 -0
  180. package/agent/docs-md/typography.md +62 -0
  181. package/agent/docs-md/undo-destructive.md +66 -0
  182. package/agent/docs-md/unsaved-changes.md +71 -0
  183. package/agent/docs-md/usage-meter.md +80 -0
  184. package/agent/docs-md/user-feedback.md +71 -0
  185. package/agent/docs-md/voice-and-tone.md +60 -0
  186. package/agent/docs-md/why-choice.md +93 -0
  187. package/agent/docs-md/workspace-onboarding.md +74 -0
  188. package/agent/docs-md/writing.md +48 -0
  189. package/agent/llms-full.txt +18369 -0
  190. package/agent/llms.txt +198 -0
  191. package/agent/skills/twoux-audit/SKILL.md +49 -0
  192. package/agent/skills/twoux-build/SKILL.md +39 -0
  193. package/agent/skills/twoux-design/SKILL.md +54 -0
  194. package/agent/skills/twoux-write/SKILL.md +32 -0
  195. package/bin/check.mjs +123 -0
  196. package/bin/docs.mjs +24 -0
  197. package/bin/guard.mjs +27 -0
  198. package/bin/init.mjs +113 -0
  199. package/bin/knowledge.mjs +87 -0
  200. package/bin/mcp.mjs +116 -0
  201. package/bin/theme.mjs +168 -0
  202. package/bin/twoux.mjs +25 -0
  203. package/package.json +80 -3
  204. package/registry/jobs.json +1028 -0
  205. package/registry/palette.json +770 -0
  206. package/registry/rules.json +913 -0
  207. package/src/components/agent-review.tsx +364 -0
  208. package/src/components/ai-basics.tsx +212 -0
  209. package/src/components/ai-work.tsx +304 -0
  210. package/src/components/ai.tsx +227 -0
  211. package/src/components/alert-dialog.tsx +203 -0
  212. package/src/components/alert.tsx +86 -0
  213. package/src/components/avatar.tsx +114 -0
  214. package/src/components/badge.tsx +59 -0
  215. package/src/components/board.tsx +397 -0
  216. package/src/components/breadcrumb.tsx +114 -0
  217. package/src/components/button-group.tsx +90 -0
  218. package/src/components/button.tsx +109 -0
  219. package/src/components/calendar.tsx +247 -0
  220. package/src/components/card.tsx +102 -0
  221. package/src/components/chart-map.tsx +336 -0
  222. package/src/components/charts-more.tsx +1331 -0
  223. package/src/components/charts-radial.tsx +328 -0
  224. package/src/components/charts.tsx +390 -0
  225. package/src/components/checkbox.tsx +40 -0
  226. package/src/components/code.tsx +139 -0
  227. package/src/components/collapsible.tsx +37 -0
  228. package/src/components/combobox.tsx +339 -0
  229. package/src/components/command-extras.tsx +11 -0
  230. package/src/components/command.tsx +196 -0
  231. package/src/components/data-grid.tsx +213 -0
  232. package/src/components/data-table.tsx +334 -0
  233. package/src/components/data-views.tsx +740 -0
  234. package/src/components/date-picker.tsx +686 -0
  235. package/src/components/dense-table.tsx +207 -0
  236. package/src/components/dialog.tsx +162 -0
  237. package/src/components/dropdown-menu.tsx +264 -0
  238. package/src/components/empty.tsx +114 -0
  239. package/src/components/feedback-prompt.tsx +80 -0
  240. package/src/components/field.tsx +254 -0
  241. package/src/components/fields.tsx +112 -0
  242. package/src/components/flow.tsx +840 -0
  243. package/src/components/guide-cue.tsx +273 -0
  244. package/src/components/inbox.tsx +113 -0
  245. package/src/components/input-group.tsx +176 -0
  246. package/src/components/input.tsx +26 -0
  247. package/src/components/kbd.tsx +34 -0
  248. package/src/components/label.tsx +27 -0
  249. package/src/components/labels.tsx +176 -0
  250. package/src/components/motion.tsx +136 -0
  251. package/src/components/onboarding.tsx +454 -0
  252. package/src/components/order-book.tsx +185 -0
  253. package/src/components/pane-layout.tsx +417 -0
  254. package/src/components/popover.tsx +96 -0
  255. package/src/components/provider-logos.data.ts +49 -0
  256. package/src/components/radio-group.tsx +52 -0
  257. package/src/components/scheduler.tsx +997 -0
  258. package/src/components/segmented-control.tsx +28 -0
  259. package/src/components/select.tsx +195 -0
  260. package/src/components/separator.tsx +31 -0
  261. package/src/components/sheet.tsx +148 -0
  262. package/src/components/shell.tsx +426 -0
  263. package/src/components/shortcut-sheet.tsx +83 -0
  264. package/src/components/skeleton.tsx +18 -0
  265. package/src/components/sonner.tsx +107 -0
  266. package/src/components/spinner.tsx +13 -0
  267. package/src/components/split-button.tsx +58 -0
  268. package/src/components/stepper.tsx +78 -0
  269. package/src/components/switch.tsx +43 -0
  270. package/src/components/table.tsx +126 -0
  271. package/src/components/tabs.tsx +118 -0
  272. package/src/components/tag-input.tsx +253 -0
  273. package/src/components/textarea.tsx +21 -0
  274. package/src/components/theme.tsx +80 -0
  275. package/src/components/timeline.tsx +408 -0
  276. package/src/components/toggle-group.tsx +87 -0
  277. package/src/components/toggle.tsx +54 -0
  278. package/src/components/tooltip.tsx +65 -0
  279. package/src/components/workspace-actions.tsx +294 -0
  280. package/src/components/workspace-import.tsx +465 -0
  281. package/src/components/workspace.tsx +1884 -0
  282. package/src/index.ts +80 -0
  283. package/src/lib/active-indicator.tsx +53 -0
  284. package/src/lib/chart-kit.tsx +72 -0
  285. package/src/lib/cn.ts +6 -0
  286. package/src/lib/shortcuts.tsx +61 -0
  287. package/src/lib/workspace.tsx +10 -0
  288. package/src/shadcn/alert-dialog.tsx +196 -0
  289. package/src/shadcn/alert.tsx +65 -0
  290. package/src/shadcn/avatar.tsx +108 -0
  291. package/src/shadcn/badge.tsx +47 -0
  292. package/src/shadcn/breadcrumb.tsx +108 -0
  293. package/src/shadcn/button-group.tsx +83 -0
  294. package/src/shadcn/button.tsx +63 -0
  295. package/src/shadcn/calendar.tsx +220 -0
  296. package/src/shadcn/card.tsx +91 -0
  297. package/src/shadcn/checkbox.tsx +31 -0
  298. package/src/shadcn/collapsible.tsx +33 -0
  299. package/src/shadcn/command.tsx +184 -0
  300. package/src/shadcn/dialog.tsx +158 -0
  301. package/src/shadcn/dropdown-menu.tsx +256 -0
  302. package/src/shadcn/empty.tsx +103 -0
  303. package/src/shadcn/field.tsx +248 -0
  304. package/src/shadcn/input-group.tsx +170 -0
  305. package/src/shadcn/input.tsx +20 -0
  306. package/src/shadcn/kbd.tsx +28 -0
  307. package/src/shadcn/label.tsx +23 -0
  308. package/src/shadcn/popover.tsx +88 -0
  309. package/src/shadcn/radio-group.tsx +44 -0
  310. package/src/shadcn/select.tsx +189 -0
  311. package/src/shadcn/separator.tsx +27 -0
  312. package/src/shadcn/sheet.tsx +142 -0
  313. package/src/shadcn/skeleton.tsx +13 -0
  314. package/src/shadcn/sonner.tsx +40 -0
  315. package/src/shadcn/switch.tsx +34 -0
  316. package/src/shadcn/table.tsx +115 -0
  317. package/src/shadcn/tabs.tsx +90 -0
  318. package/src/shadcn/textarea.tsx +17 -0
  319. package/src/shadcn/toggle-group.tsx +83 -0
  320. package/src/shadcn/toggle.tsx +46 -0
  321. package/src/shadcn/tooltip.tsx +56 -0
  322. package/src/styles/palette.css +127 -0
  323. package/src/styles/theme.css +35 -0
  324. package/src/styles/twoux.css +236 -0
  325. package/theme.json +14 -0
@@ -0,0 +1,98 @@
1
+ # Treemap
2
+
3
+ Parts of a total as nested rectangles sized by value: squarified so tiles stay readable, names only where they fit, and the tail folded into Other after 12 tiles.
4
+
5
+ Kind: component · Group: Data visualisation · Status: built, import from @twoux/ui
6
+
7
+ ## When to use
8
+
9
+ - Showing which of many items make up most of a total, such as cloud spend by service.
10
+ - A total with one level of grouping, where the groups matter as well as the items.
11
+
12
+ ## When not to use
13
+
14
+ - To compare items precisely. Use the TwoUX Bar chart, because areas are read less exactly than lengths.
15
+ - For five parts or fewer. Use the TwoUX Share bar.
16
+
17
+ ## Structure
18
+
19
+ 1. Title and subtitle
20
+ 2. Tiles sized by value, with 2px surface gaps
21
+ 3. Name and share inside tiles that can hold them
22
+ 4. Other tile in grey
23
+ 5. Legend of groups when there are two or more
24
+ 6. Tooltip: name, value, share, group
25
+
26
+ ## Guidelines
27
+
28
+ - Keep to 12 tiles; the rest fold into a grey Other.
29
+ - Use the squarified layout so tiles stay close to square and readable.
30
+ - Without groups every tile is one colour; with groups each group takes its series colour and a legend. Never colour tiles by value.
31
+ - Print a name only where it fits and a share only where there is room; never clip text.
32
+ - Values go in the tooltip and the Table view.
33
+ - Use ChartFrame for the four states: loading keeps the frame, an error says what failed with Try again, an empty period says so, and no match offers Clear filters.
34
+
35
+ ## Content
36
+
37
+ - Short tile names; the full name is in the tooltip and table.
38
+ - Subtitle gives the period and scope, such as October 2026, all projects.
39
+
40
+ ## Accessibility
41
+
42
+ - 1.4.1 Use of Color: groups are named in the legend and the tooltip; every value is in the table.
43
+ - 1.1.1 and WAI complex images: the chart has a short generated summary as its accessible name and a Table view with every value.
44
+ - 2.1.1 Keyboard: the chart is one tab stop; arrow keys move between marks and show the same tooltip as hover.
45
+ - 1.4.13 Content on Hover or Focus: the tooltip never covers the mark it describes, stays while the pointer is over the chart and closes with Esc.
46
+ - Accessible description: "Treemap showing cloud spend by service, October 2026."
47
+
48
+ ## Keyboard
49
+
50
+ | Keys | Action |
51
+ |---|---|
52
+ | Tab | Focus the chart |
53
+ | ← → ↑ ↓ | Move to the previous or next mark and show its values |
54
+ | Home End | Jump to the first or last mark |
55
+ | Esc | Hide the tooltip |
56
+
57
+ ## Examples
58
+
59
+ ### cloud-spend
60
+
61
+ ```tsx
62
+ import { ChartFrame, shareTable, Treemap } from "@twoux/ui";
63
+
64
+ export const meta = { title: "Cloud spend by service", description: "Fifteen services in three groups: the twelfth tile onwards fold into Other. Names show only on tiles big enough to hold them.", order: 1 };
65
+
66
+ const ITEMS = [
67
+ { id: "vm", label: "Virtual machines", value: 48_200, group: "Compute" },
68
+ { id: "k8s", label: "Kubernetes", value: 31_400, group: "Compute" },
69
+ { id: "fn", label: "Functions", value: 6_900, group: "Compute" },
70
+ { id: "gpu", label: "GPU instances", value: 22_800, group: "Compute" },
71
+ { id: "obj", label: "Object storage", value: 18_600, group: "Storage" },
72
+ { id: "block", label: "Block storage", value: 12_100, group: "Storage" },
73
+ { id: "backup", label: "Backups", value: 5_400, group: "Storage" },
74
+ { id: "pg", label: "Postgres", value: 19_700, group: "Data" },
75
+ { id: "wh", label: "Warehouse", value: 15_300, group: "Data" },
76
+ { id: "cache", label: "Cache", value: 4_200, group: "Data" },
77
+ { id: "stream", label: "Streaming", value: 3_900, group: "Data" },
78
+ { id: "search", label: "Search", value: 2_800, group: "Data" },
79
+ { id: "dns", label: "DNS", value: 600, group: "Compute" },
80
+ { id: "logs", label: "Log archive", value: 1_100, group: "Storage" },
81
+ { id: "etl", label: "ETL jobs", value: 900, group: "Data" },
82
+ ];
83
+ const gbp = (n: number) => `£${n.toLocaleString("en-GB")}`;
84
+
85
+ export default function Example() {
86
+ return (
87
+ <ChartFrame className="w-full" title="Cloud spend by service" description="October 2026, all projects" table={shareTable(ITEMS, gbp, "Service")} height={260}>
88
+ <Treemap items={ITEMS} format={gbp} aria-label="Cloud spend by service, October 2026" />
89
+ </ChartFrame>
90
+ );
91
+ }
92
+ ```
93
+
94
+ ## Related
95
+
96
+ - Share bar
97
+ - Bar chart
98
+ - Donut chart
@@ -0,0 +1,93 @@
1
+ # Waterfall chart
2
+
3
+ How an opening amount becomes a closing amount: each increase and decrease floats from the running total, joined by connectors, with totals in grey from zero.
4
+
5
+ Kind: component · Group: Data visualisation · Status: built, import from @twoux/ui
6
+
7
+ ## When to use
8
+
9
+ - Explaining how a balance or profit moved from one figure to another, such as cash flow for a month.
10
+ - A bridge between two totals where each step matters, such as budget to actual.
11
+
12
+ ## When not to use
13
+
14
+ - To show a series over time. Use the TwoUX Line chart card.
15
+ - For parts of one total with no order. Use the TwoUX Share bar or Bar chart.
16
+
17
+ ## Structure
18
+
19
+ 1. Title and subtitle
20
+ 2. Y axis from zero (or below, when totals go negative)
21
+ 3. Total bars in grey from zero
22
+ 4. Increase and decrease bars floating from the running total
23
+ 5. Connector lines between bars
24
+ 6. Value labels with + or − where they fit
25
+ 7. Legend: increase, decrease, total
26
+ 8. Tooltip: change and running total
27
+
28
+ ## Guidelines
29
+
30
+ - Increases and decreases take two categorical colours (c1 and c2), never green and red; the + or − on each label carries direction.
31
+ - Totals are grey and start from zero, so they read as levels, not changes.
32
+ - Join bars with thin connectors at the running total.
33
+ - Print a value only where it fits; the tooltip and table always have it.
34
+ - Order steps as the money moved: opening, money in, money out, closing.
35
+ - Use ChartFrame for the four states: loading keeps the frame, an error says what failed with Try again, an empty period says so, and no match offers Clear filters.
36
+
37
+ ## Content
38
+
39
+ - Use a real minus sign and a plus sign on every change; totals have no sign.
40
+ - Name the legend by meaning (Money in, Money out, Balance), not by colour.
41
+
42
+ ## Accessibility
43
+
44
+ - 1.4.1 Use of Color: direction is carried by the sign on each label, in the tooltip and in the table, not by colour.
45
+ - 1.1.1 and WAI complex images: the chart has a short generated summary as its accessible name and a Table view with every value.
46
+ - 2.1.1 Keyboard: the chart is one tab stop; arrow keys move between marks and show the same tooltip as hover.
47
+ - 1.4.13 Content on Hover or Focus: the tooltip never covers the mark it describes, stays while the pointer is over the chart and closes with Esc.
48
+ - Accessible description: "Waterfall chart showing cash flow for October 2026."
49
+
50
+ ## Keyboard
51
+
52
+ | Keys | Action |
53
+ |---|---|
54
+ | Tab | Focus the chart |
55
+ | ← → ↑ ↓ | Move to the previous or next mark and show its values |
56
+ | Home End | Jump to the first or last mark |
57
+ | Esc | Hide the tooltip |
58
+
59
+ ## Examples
60
+
61
+ ### cash-flow
62
+
63
+ ```tsx
64
+ import { ChartFrame, Waterfall, type WaterfallStep, waterfallTable } from "@twoux/ui";
65
+
66
+ export const meta = { title: "Cash flow for the month", description: "Opening balance, money in and money out, then the closing balance as a total. Grey totals, two categorical colours for in and out, a + or − on every change that fits.", order: 1 };
67
+
68
+ const STEPS: WaterfallStep[] = [
69
+ { id: "open", label: "Opening", value: 1_240_000, total: true },
70
+ { id: "subs", label: "Subscriptions", value: 486_000 },
71
+ { id: "services", label: "Services", value: 92_000 },
72
+ { id: "payroll", label: "Payroll", value: -412_000 },
73
+ { id: "hosting", label: "Hosting", value: -88_000 },
74
+ { id: "rent", label: "Rent", value: -46_000 },
75
+ { id: "vat", label: "VAT", value: -131_000 },
76
+ { id: "close", label: "Closing", total: true },
77
+ ];
78
+ const gbp = (n: number) => (Math.abs(n) >= 1_000_000 ? `£${(n / 1_000_000).toFixed(2)}m` : n === 0 ? "£0" : `£${Math.round(n / 1000)}k`);
79
+
80
+ export default function Example() {
81
+ return (
82
+ <ChartFrame className="w-full" title="Cash flow" description="October 2026, all accounts" table={waterfallTable(STEPS, gbp)}>
83
+ <Waterfall steps={STEPS} format={gbp} labels={{ increase: "Money in", decrease: "Money out", total: "Balance" }} aria-label="Cash flow, October 2026" />
84
+ </ChartFrame>
85
+ );
86
+ }
87
+ ```
88
+
89
+ ## Related
90
+
91
+ - Bar chart
92
+ - Bullet chart
93
+ - Stat card with comparison
@@ -0,0 +1,131 @@
1
+ # Checkbox
2
+
3
+ Lets people choose any number of options, or confirm one setting that is applied when they save.
4
+
5
+ Kind: component · Group: Actions and inputs · Status: built, import from @twoux/ui
6
+
7
+ ## When to use
8
+
9
+ - To pick any number of options from a list, including none.
10
+ - To select table rows for bulk actions, with a header checkbox that selects all.
11
+ - For a single setting in a form that is applied when the person saves: Show salary on listing.
12
+ - As a parent with an indeterminate dash when only some children are selected.
13
+
14
+ ## When not to use
15
+
16
+ - For one choice out of several. Use Radio.
17
+ - For a setting that takes effect at once. Use Switch.
18
+ - To switch the view of other content. Use Segmented control.
19
+
20
+ ## Structure
21
+
22
+ 1. Box (15px)
23
+ 2. Check or dash mark
24
+ 3. Label
25
+ 4. Hint (optional)
26
+ 5. Group label (for sets)
27
+
28
+ ## Guidelines
29
+
30
+ - Box is 15px, 4px radius. Checked and indeterminate fill with primary.
31
+ - The label is part of the click target. Clicking either toggles the box.
32
+ - List options vertically, one per line. Horizontal only for two short options with clear spacing.
33
+ - Indeterminate is visual only; clicking it selects all rows.
34
+ - Opt-in checkboxes start unticked.
35
+
36
+ ## Content
37
+
38
+ - Write labels positively: Accept CVs by email, not Don't accept CVs by email.
39
+ - Keep labels short, sentence case, no end punctuation.
40
+ - Group labels say what to choose: Columns to show.
41
+
42
+ ## Accessibility
43
+
44
+ - Use a native input type="checkbox" with a label element. Space toggles it.
45
+ - Parent checkboxes expose aria-checked="mixed" when partly selected.
46
+ - Wrap related checkboxes in a fieldset with a legend, or role="group" with aria-labelledby.
47
+ - The 15px box is below 24px, so the label is clickable and rows are 36px apart to meet target spacing.
48
+ - Unchecked border and checked fill need 3:1 against white.
49
+
50
+ ## Keyboard
51
+
52
+ | Keys | Action |
53
+ |---|---|
54
+ | Space | Toggle the focused checkbox |
55
+ | X | Select the focused table row (single-key shortcut, can be turned off) |
56
+ | Shift+J / Shift+K | Extend row selection down or up |
57
+
58
+ ## Examples
59
+
60
+ ### select-all
61
+
62
+ ```tsx
63
+ import { Checkbox } from "@twoux/ui";
64
+ import { useState } from "react";
65
+
66
+ export const meta = { title: "Select all", description: "The parent shows indeterminate when only some rows are selected. Clicking it selects all; clicking again clears all.", order: 3 };
67
+
68
+ const roles = ["Junior Product Designer", "Graduate Data Analyst", "Junior QA Engineer"];
69
+
70
+ export default function Example() {
71
+ const [sel, setSel] = useState<string[]>([roles[0]]);
72
+ const all = sel.length === roles.length ? true : sel.length ? "indeterminate" : false;
73
+ return (
74
+ <div className="w-72 overflow-hidden rounded-sm border border-line bg-surface">
75
+ <label className="flex h-row cursor-pointer items-center gap-2.5 bg-surface-2 px-3 text-sm font-medium text-ink-2">
76
+ <Checkbox checked={all} onCheckedChange={() => setSel(all === true ? [] : roles)} aria-label="Select all listings" />
77
+ {sel.length ? `${sel.length} of ${roles.length} selected` : "Select all"}
78
+ </label>
79
+ {roles.map((r) => (
80
+ <label key={r} className="flex h-row cursor-pointer items-center gap-2.5 border-t border-line px-3 hover:bg-surface-2">
81
+ <Checkbox checked={sel.includes(r)} onCheckedChange={(v) => setSel((s) => (v ? [...s, r] : s.filter((x) => x !== r)))} />
82
+ {r}
83
+ </label>
84
+ ))}
85
+ </div>
86
+ );
87
+ }
88
+ ```
89
+
90
+ ### states
91
+
92
+ ```tsx
93
+ import { Checkbox } from "@twoux/ui";
94
+
95
+ export const meta = { title: "States", description: "Unchecked, checked, indeterminate (some children selected) and disabled. The box is 16px; its row is 24px so it is easy to hit.", order: 1 };
96
+
97
+ export default function Example() {
98
+ return (
99
+ <div className="flex items-center gap-6">
100
+ <Checkbox aria-label="Unchecked" />
101
+ <Checkbox aria-label="Checked" defaultChecked />
102
+ <Checkbox aria-label="Some selected" checked="indeterminate" />
103
+ <Checkbox aria-label="Disabled" disabled />
104
+ <Checkbox aria-label="Disabled and checked" disabled defaultChecked />
105
+ </div>
106
+ );
107
+ }
108
+ ```
109
+
110
+ ### with-label
111
+
112
+ ```tsx
113
+ import { CheckboxField } from "@twoux/ui";
114
+
115
+ export const meta = { title: "With label and hint", description: "The label is clickable and part of the target. A hint explains the consequence, not the control.", order: 2 };
116
+
117
+ export default function Example() {
118
+ return (
119
+ <div className="grid gap-3">
120
+ <CheckboxField id="ex-salary" label="Show salary on listing" hint="Listings with a salary get about a third more applies." defaultChecked />
121
+ <CheckboxField id="ex-email" label="Accept CVs by email" />
122
+ </div>
123
+ );
124
+ }
125
+ ```
126
+
127
+ ## Related
128
+
129
+ - Radio
130
+ - Switch
131
+ - Form validation
@@ -0,0 +1,71 @@
1
+ # Choosing a selection control
2
+
3
+ Pick the control from three questions: one choice or many, how many options, and does it apply at once or on Save.
4
+
5
+ Kind: pattern · Group: Patterns: general
6
+
7
+ **Problem:** The same kind of choice ends up as a radio group on one form, a dropdown on another and a switch on a third, so people can't predict when a change takes effect.
8
+
9
+ **Solution:** One choice from up to seven: radio. One choice from eight or more: select. Many from up to seven: checkboxes. Many from eight or more: multiselect. On or off with immediate effect: switch. On or off applied on Save: checkbox. Two to three view options: segmented control.
10
+
11
+ **Built from:** Radio, Checkbox, Switch, Segmented control, Combobox, Text input
12
+
13
+ ## How it works
14
+
15
+ 1. One option or many? Many means checkboxes or a multiselect.
16
+ 2. How many options? Up to seven show all of them (radio or checkboxes); eight or more use a Combobox (combobox), with multiple for several.
17
+ 3. For on or off: does it take effect at once (switch) or when the form is saved (checkbox)?
18
+ 4. If both the on and off states need explaining, use two radio options with descriptions instead.
19
+
20
+ ## When to use
21
+
22
+ - Radio: Work pattern on a listing (On-site, Hybrid, Remote (UK)).
23
+ - Select: Location from the list of offices; multiselect: Skills from a long list.
24
+ - Switch: "Email me when a listing closes" in notification settings, saved at once. Checkbox: "Offer visa sponsorship" in the Create listing form.
25
+
26
+ ## When not to use
27
+
28
+ - Segmented control for a form value. It switches views or settings of what is shown, such as Daily or Weekly.
29
+ - A switch inside a form with a Save button; people expect a switch to act at once.
30
+ - Any selection control for a filter on a list page; filters use the filter pills.
31
+
32
+ ## Guidelines
33
+
34
+ - When a choice reveals sub-options, use a different control for the parent than for the children: a checkbox that reveals radio options, not checkboxes inside checkboxes.
35
+ - Place revealed sub-options after the whole radio group, never between two radio options.
36
+ - Use the same parent control for the same kind of reveal everywhere on a page.
37
+ - Order options logically: by frequency, by the order of the hiring process, or alphabetically for long lists.
38
+ - Give options short descriptions only when they help people choose; keep the sentence structure the same across options.
39
+
40
+ ## Content
41
+
42
+ - Switch labels describe the setting when on: "Email me when a listing closes".
43
+ - Checkbox labels describe what ticking does: "Offer visa sponsorship".
44
+ - When every option shares a subject, put it in the group label ("Work pattern") and keep options short.
45
+
46
+ ## Accessibility
47
+
48
+ - Radio and checkbox groups are fieldsets with a legend that is the group label.
49
+ - A switch uses role="switch" and announces on or off.
50
+ - Revealed sub-options follow their parent in the focus order.
51
+
52
+ ## Do
53
+
54
+ - Do show all options when there are seven or fewer.
55
+ - Do use a switch only for changes that apply at once.
56
+ - Do use radio options with descriptions when both on and off need explaining.
57
+
58
+ ## Don't
59
+
60
+ - Don't hide three options in a dropdown.
61
+ - Don't nest the same control type for parent and sub-options.
62
+ - Don't put controls between radio options.
63
+
64
+ ## Related
65
+
66
+ - Inline editing and validation
67
+ - Filtering and search
68
+ - Radio
69
+ - Checkbox
70
+ - Switch
71
+ - Segmented control
@@ -0,0 +1,79 @@
1
+ # Citations and sources
2
+
3
+ Record IDs inline in answers that open the record, plus a Sources panel on the full page listing every record and file the answer used.
4
+
5
+ Kind: component · Group: AI and agents · Status: built, import from @twoux/ui
6
+
7
+ ## When to use
8
+
9
+ - Every claim about a record or figure in an answer or an AI column cell.
10
+ - When an answer relies on a team file, cite the file.
11
+
12
+ ## When not to use
13
+
14
+ - Generic wording with no factual claim. Do not add filler citations.
15
+ - To label content as generated. Use the AI origin label (ai-origin-label).
16
+
17
+ ## Structure
18
+
19
+ 1. Inline citation (record ID, for example LST-1044)
20
+ 2. Sources panel (record rows, files)
21
+ 3. Highlight state on the cited source
22
+
23
+ ## Guidelines
24
+
25
+ - Citations are record IDs that open the record, so checking takes one click.
26
+ - In the panel, a citation focuses the row in the table; on the full page it highlights the source in the Sources panel.
27
+ - Place citations at the end of the claim they support, consistently.
28
+ - Say when a source is missing or stale rather than showing an empty state that implies success.
29
+ - Point to the exact data used where possible (views, applies, period).
30
+
31
+ ## Content
32
+
33
+ - Use the record's own ID format (LST-1044), not numbers like [1], so the citation is meaningful on its own.
34
+ - Sources list title, ID and what was read.
35
+
36
+ ## Accessibility
37
+
38
+ - Citations are links with an accessible name that includes the record, for example "LST-1044, Operations Coordinator" (SC 2.4.6, 4.1.2).
39
+ - Do not signal citations by colour alone; use the chip shape (SC 1.4.1).
40
+ - Moving focus to the cited row must keep that row visible (SC 2.4.11).
41
+
42
+ ## Keyboard
43
+
44
+ | Keys | Action |
45
+ |---|---|
46
+ | Tab | Move to the next citation |
47
+ | Enter | Open or highlight the cited record |
48
+
49
+ ## Examples
50
+
51
+ ### cite
52
+
53
+ ```tsx
54
+ import { Citation, SourcesList } from "@twoux/ui";
55
+ import { useState } from "react";
56
+
57
+ export const meta = { title: "Every claim names its record", description: "Citations are record IDs at the end of the claim. Selecting one highlights the source; on a list page it would focus the row.", order: 1 };
58
+
59
+ const SRC = [{ id: "LST-1041", title: "Frontend Engineer", detail: "6 applicants · closes 21 Nov" }, { id: "LST-1044", title: "Customer Success Lead", detail: "3 applicants · closes 23 Nov" }];
60
+
61
+ export default function Example() {
62
+ const [a, setA] = useState<string>();
63
+ return (
64
+ <div className="grid w-full max-w-2xl grid-cols-[1fr_240px] gap-4 max-md:grid-cols-1">
65
+ <p className="text-base text-ink">Two listings close this week with fewer than 10 applicants: Frontend Engineer <Citation id="LST-1041" active={a === "LST-1041"} onOpen={setA} /> and Customer Success Lead <Citation id="LST-1044" active={a === "LST-1044"} onOpen={setA} />.</p>
66
+ <SourcesList sources={SRC} active={a} onSelect={setA} />
67
+ </div>
68
+ );
69
+ }
70
+ ```
71
+
72
+ ## Related
73
+
74
+ - Assistant page
75
+ - AI column
76
+ - Team instructions and files
77
+ - AI origin label
78
+ - Confidence note
79
+ - Why this choice
@@ -0,0 +1,63 @@
1
+ # Citing sources
2
+
3
+ Every claim in an answer links to the record it came from by ID; clicking opens the record in the side panel, and the full page lists every record used.
4
+
5
+ Kind: pattern · Group: Patterns: AI
6
+
7
+ **Problem:** People can't act on an answer they can't check, and generic "Sources" lists at the bottom don't say which claim came from where.
8
+
9
+ **Solution:** Citations are record IDs (LST-1044) placed right after the claim. They open the record in the side panel. The full-page view adds a Sources panel listing every record and file the answer used, and highlights the one being cited.
10
+
11
+ **Built from:** Citations and sources, Assistant side panel, Assistant page, Side panel (drawer), AI column, Team instructions and files
12
+
13
+ ## How it works
14
+
15
+ 1. Place the record ID straight after the sentence it supports.
16
+ 2. Hover or focus shows a preview: record title, the figure used, when it was updated.
17
+ 3. Click opens the record in the side panel next to the answer.
18
+ 4. When the answer relied on a team file, cite the file by name.
19
+ 5. Expanded to a full page, a Sources panel lists every record and file used, and citations highlight their source.
20
+
21
+ ## When to use
22
+
23
+ - For every factual claim about workspace data in an answer, a generated cell or an agent step.
24
+
25
+ ## When not to use
26
+
27
+ - To decorate an answer with sources that don't support a specific claim; that builds false trust.
28
+ - For reasoning steps; those are progress, not evidence (see Showing reasoning and progress).
29
+
30
+ ## Guidelines
31
+
32
+ - Cite at the claim, not in a list at the end, so people can tell sourced claims from synthesis.
33
+ - Use descriptive citations (the record ID and title on hover), never "Source 1".
34
+ - If a source is missing or deleted, say so openly instead of hiding the gap.
35
+ - Keep citation style identical in answers, AI columns and agent runs.
36
+ - Say what data the answer could not see, so people know when to rely on their own judgement.
37
+
38
+ ## Content
39
+
40
+ - Citations use the record ID as it appears in the product: "LST-1044".
41
+ - Sources panel heading: "Sources", each item with title, type and last updated.
42
+
43
+ ## Accessibility
44
+
45
+ - Citations are links with accessible names that include the record title, not just the ID.
46
+ - Citation previews open on focus as well as hover and close with Esc.
47
+
48
+ ## Do
49
+
50
+ - Do link each claim to its record.
51
+ - Do cite team files by name.
52
+
53
+ ## Don't
54
+
55
+ - Don't list sources only at the bottom.
56
+ - Don't show a citation that doesn't support the claim.
57
+
58
+ ## Related
59
+
60
+ - Ask about what's on screen
61
+ - Labelling AI output
62
+ - Generated table columns and enrichment
63
+ - Citations and sources
@@ -0,0 +1,69 @@
1
+ # Clarifying before acting
2
+
3
+ When the answer would change the result, ask with a question card above the composer: options with a recommended default, number keys, Skip and Next.
4
+
5
+ Kind: pattern · Group: Patterns: AI
6
+
7
+ **Problem:** An assistant that guesses rewrites the wrong listings; one that asks too much becomes a form. Without a rule, each feature decides differently when to ask.
8
+
9
+ **Solution:** Ask only when the answer changes the result, at most three questions, one at a time. Each has a recommended option first, a one-line explanation per option, and "Use defaults" to skip the rest.
10
+
11
+ **Built from:** Clarifying question card, Assistant side panel, Message composer, Radio, Agent run timeline
12
+
13
+ ## How it works
14
+
15
+ 1. Before acting, check whether the request is ambiguous in a way that changes the outcome (which listings, which period, who receives it).
16
+ 2. If yes, show the question card docked above the composer: "1 / 2", the question, then options.
17
+ 3. Options have a title and one line each, the recommended one first and marked, Other last with free text.
18
+ 4. Number keys 1 to 4 pick an option; Previous, Skip and Next ↵ move through the questions.
19
+ 5. The thread shows "Waiting for your answer" with a timer; in an agent run the step is marked Needs you and appears in the Inbox.
20
+ 6. Once answered, the card collapses into a one-line summary of the choice, and the work continues.
21
+
22
+ ## When to use
23
+
24
+ - When the request is ambiguous and the action is costly to get wrong.
25
+ - When an agent hits a decision it is not allowed to make alone.
26
+
27
+ ## When not to use
28
+
29
+ - When the answer can be inferred from context chips or retrieved from data; don't ask what you already know.
30
+ - For low-stakes answers; answer first and offer follow-ups instead.
31
+ - For approving a concrete change; use Propose then apply.
32
+
33
+ ## Guidelines
34
+
35
+ - At most three questions per request, one at a time.
36
+ - Every question has a default and "Use defaults" skips the rest.
37
+ - Options before free text; the composer stays available for anything the options miss.
38
+ - Say why the answer matters in the option's line ("Leaves listings that are doing well alone").
39
+ - An unanswered question never blocks forever; in a scheduled run it expires and the run reports that nothing ran.
40
+ - Ask first when the stakes are high or confidence is low; otherwise answer for the common case and offer follow-up options to narrow it.
41
+ - If the person may not know the answer, say where to find it: "Salary bands are in Team files" with a link.
42
+ - Values needed to carry out an action (dates, amounts) are not clarifying questions; use an input card (see Asking for details inside the answer).
43
+
44
+ ## Content
45
+
46
+ - Questions are short and specific: "Which titles should I rewrite?"
47
+ - Mark the default "(Recommended)" in text, not only with a colour.
48
+
49
+ ## Accessibility
50
+
51
+ - Options are a radio group: arrows move, Space or the number key selects, Enter goes to Next.
52
+ - Focus moves into the card when it appears and returns to the composer when it closes.
53
+
54
+ ## Do
55
+
56
+ - Do put the recommended option first.
57
+ - Do let people skip with defaults.
58
+
59
+ ## Don't
60
+
61
+ - Don't ask more than three questions.
62
+ - Don't ask for information already in context.
63
+
64
+ ## Related
65
+
66
+ - Ask about what's on screen
67
+ - Agents acting on your behalf
68
+ - Propose, then apply
69
+ - Clarifying question card