@twoux/ui 0.0.0-stage → 0.1.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 (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/SHADCN-DIFF.md +228 -0
  5. package/agent/AGENTS.md +358 -0
  6. package/agent/docs-md/accessibility.md +49 -0
  7. package/agent/docs-md/action-catalogue.md +81 -0
  8. package/agent/docs-md/actions.md +74 -0
  9. package/agent/docs-md/agent-activity-log.md +70 -0
  10. package/agent/docs-md/agent-permissions.md +82 -0
  11. package/agent/docs-md/agent-run.md +90 -0
  12. package/agent/docs-md/agents-on-behalf.md +74 -0
  13. package/agent/docs-md/ai-column.md +85 -0
  14. package/agent/docs-md/ai-origin-label.md +70 -0
  15. package/agent/docs-md/announcing-features.md +73 -0
  16. package/agent/docs-md/answer-actions.md +81 -0
  17. package/agent/docs-md/app-shell.md +114 -0
  18. package/agent/docs-md/artifact-card.md +89 -0
  19. package/agent/docs-md/ask-on-screen.md +72 -0
  20. package/agent/docs-md/assistant-page.md +100 -0
  21. package/agent/docs-md/assistant-panel.md +142 -0
  22. package/agent/docs-md/avatar.md +82 -0
  23. package/agent/docs-md/banner.md +106 -0
  24. package/agent/docs-md/board.md +163 -0
  25. package/agent/docs-md/breadcrumb.md +89 -0
  26. package/agent/docs-md/breakdown-table.md +97 -0
  27. package/agent/docs-md/bulk-action-bar.md +112 -0
  28. package/agent/docs-md/button.md +293 -0
  29. package/agent/docs-md/card.md +115 -0
  30. package/agent/docs-md/change-list.md +99 -0
  31. package/agent/docs-md/change-request.md +166 -0
  32. package/agent/docs-md/chart-area.md +87 -0
  33. package/agent/docs-md/chart-bar.md +100 -0
  34. package/agent/docs-md/chart-box-plot.md +88 -0
  35. package/agent/docs-md/chart-bullet.md +89 -0
  36. package/agent/docs-md/chart-candlestick.md +112 -0
  37. package/agent/docs-md/chart-card-line.md +120 -0
  38. package/agent/docs-md/chart-donut.md +90 -0
  39. package/agent/docs-md/chart-drill-down.md +72 -0
  40. package/agent/docs-md/chart-funnel.md +71 -0
  41. package/agent/docs-md/chart-heatmap.md +76 -0
  42. package/agent/docs-md/chart-histogram.md +81 -0
  43. package/agent/docs-md/chart-map.md +165 -0
  44. package/agent/docs-md/chart-mixed.md +88 -0
  45. package/agent/docs-md/chart-price.md +92 -0
  46. package/agent/docs-md/chart-radial-bars.md +109 -0
  47. package/agent/docs-md/chart-radial-lines.md +111 -0
  48. package/agent/docs-md/chart-sankey.md +104 -0
  49. package/agent/docs-md/chart-scatter.md +87 -0
  50. package/agent/docs-md/chart-share-bar.md +89 -0
  51. package/agent/docs-md/chart-treemap.md +98 -0
  52. package/agent/docs-md/chart-waterfall.md +93 -0
  53. package/agent/docs-md/checkbox.md +131 -0
  54. package/agent/docs-md/choosing-selection-control.md +71 -0
  55. package/agent/docs-md/citations-sources.md +79 -0
  56. package/agent/docs-md/citing-sources.md +63 -0
  57. package/agent/docs-md/clarify-before-acting.md +69 -0
  58. package/agent/docs-md/clarifying-question.md +92 -0
  59. package/agent/docs-md/code-block.md +174 -0
  60. package/agent/docs-md/colours.md +87 -0
  61. package/agent/docs-md/columns-menu.md +140 -0
  62. package/agent/docs-md/combobox.md +161 -0
  63. package/agent/docs-md/command-palette.md +126 -0
  64. package/agent/docs-md/confidence-note.md +87 -0
  65. package/agent/docs-md/configurable-dashboard.md +76 -0
  66. package/agent/docs-md/confirmation-dialog.md +93 -0
  67. package/agent/docs-md/connected-tools.md +80 -0
  68. package/agent/docs-md/connector-picker.md +127 -0
  69. package/agent/docs-md/consistency.md +53 -0
  70. package/agent/docs-md/content-density.md +61 -0
  71. package/agent/docs-md/conversation-history.md +78 -0
  72. package/agent/docs-md/create-record.md +80 -0
  73. package/agent/docs-md/csv-import.md +88 -0
  74. package/agent/docs-md/dashboard-items.md +78 -0
  75. package/agent/docs-md/data-export.md +61 -0
  76. package/agent/docs-md/data-grid.md +137 -0
  77. package/agent/docs-md/data-vis-colours.md +76 -0
  78. package/agent/docs-md/data-visualisation.md +76 -0
  79. package/agent/docs-md/date-picker.md +178 -0
  80. package/agent/docs-md/delete-record.md +75 -0
  81. package/agent/docs-md/dense-table.md +495 -0
  82. package/agent/docs-md/design-tokens.md +53 -0
  83. package/agent/docs-md/disabled-read-only.md +75 -0
  84. package/agent/docs-md/drag-and-drop.md +74 -0
  85. package/agent/docs-md/dropdown-menu.md +137 -0
  86. package/agent/docs-md/edit-record.md +73 -0
  87. package/agent/docs-md/empty-loading-error.md +78 -0
  88. package/agent/docs-md/empty-state.md +128 -0
  89. package/agent/docs-md/error-messages.md +75 -0
  90. package/agent/docs-md/error-state.md +123 -0
  91. package/agent/docs-md/export-menu.md +86 -0
  92. package/agent/docs-md/feedback-prompt.md +88 -0
  93. package/agent/docs-md/field-mapping.md +78 -0
  94. package/agent/docs-md/file-drop.md +110 -0
  95. package/agent/docs-md/filter-bar.md +138 -0
  96. package/agent/docs-md/filter-panel.md +103 -0
  97. package/agent/docs-md/filtering-search.md +79 -0
  98. package/agent/docs-md/follow-ups-starters.md +79 -0
  99. package/agent/docs-md/form-validation.md +95 -0
  100. package/agent/docs-md/generated-columns.md +65 -0
  101. package/agent/docs-md/generated-drafts-files.md +71 -0
  102. package/agent/docs-md/grouped-list.md +89 -0
  103. package/agent/docs-md/guide-cue.md +170 -0
  104. package/agent/docs-md/help-panel.md +103 -0
  105. package/agent/docs-md/help-system.md +74 -0
  106. package/agent/docs-md/iconography.md +49 -0
  107. package/agent/docs-md/inbox.md +108 -0
  108. package/agent/docs-md/inline-editing-validation.md +80 -0
  109. package/agent/docs-md/inline-input-in-answer.md +70 -0
  110. package/agent/docs-md/items-palette.md +116 -0
  111. package/agent/docs-md/keyboard-model.md +47 -0
  112. package/agent/docs-md/keyboard-navigation.md +68 -0
  113. package/agent/docs-md/keyboard-shortcut-hint.md +87 -0
  114. package/agent/docs-md/keyboard-shortcut-sheet.md +90 -0
  115. package/agent/docs-md/labelling-ai-output.md +66 -0
  116. package/agent/docs-md/layout.md +47 -0
  117. package/agent/docs-md/list-table.md +254 -0
  118. package/agent/docs-md/loading-skeleton.md +91 -0
  119. package/agent/docs-md/managing-agents.md +71 -0
  120. package/agent/docs-md/message-composer.md +105 -0
  121. package/agent/docs-md/migrating.md +49 -0
  122. package/agent/docs-md/motion.md +93 -0
  123. package/agent/docs-md/navigation.md +76 -0
  124. package/agent/docs-md/notification-channels.md +65 -0
  125. package/agent/docs-md/notifications-decision.md +100 -0
  126. package/agent/docs-md/onboarding-step.md +114 -0
  127. package/agent/docs-md/order-book.md +108 -0
  128. package/agent/docs-md/page-header.md +96 -0
  129. package/agent/docs-md/pagination.md +88 -0
  130. package/agent/docs-md/pane-layout.md +105 -0
  131. package/agent/docs-md/period-comparison.md +66 -0
  132. package/agent/docs-md/plan-card.md +120 -0
  133. package/agent/docs-md/popover-rules.md +88 -0
  134. package/agent/docs-md/prompt-editor.md +90 -0
  135. package/agent/docs-md/propose-apply.md +65 -0
  136. package/agent/docs-md/provider-logo.md +97 -0
  137. package/agent/docs-md/radio.md +83 -0
  138. package/agent/docs-md/ranked-list.md +102 -0
  139. package/agent/docs-md/reasoning-progress.md +72 -0
  140. package/agent/docs-md/record-detail.md +71 -0
  141. package/agent/docs-md/regenerating-answers.md +70 -0
  142. package/agent/docs-md/run-status-bar.md +94 -0
  143. package/agent/docs-md/saved-tasks-schedules.md +63 -0
  144. package/agent/docs-md/saved-views.md +149 -0
  145. package/agent/docs-md/saving-views.md +68 -0
  146. package/agent/docs-md/scheduler.md +258 -0
  147. package/agent/docs-md/secondary-panels.md +72 -0
  148. package/agent/docs-md/segmented-control.md +88 -0
  149. package/agent/docs-md/selection-bulk-actions.md +70 -0
  150. package/agent/docs-md/separator.md +75 -0
  151. package/agent/docs-md/setup-checklist.md +92 -0
  152. package/agent/docs-md/shape-elevation.md +55 -0
  153. package/agent/docs-md/sheet-grid.md +211 -0
  154. package/agent/docs-md/side-panel.md +134 -0
  155. package/agent/docs-md/sign-in.md +114 -0
  156. package/agent/docs-md/spacing.md +55 -0
  157. package/agent/docs-md/split-button.md +100 -0
  158. package/agent/docs-md/stat-compare.md +82 -0
  159. package/agent/docs-md/static-dashboard.md +75 -0
  160. package/agent/docs-md/status-badge.md +140 -0
  161. package/agent/docs-md/step-card.md +75 -0
  162. package/agent/docs-md/stepper.md +92 -0
  163. package/agent/docs-md/suggested-changes.md +91 -0
  164. package/agent/docs-md/switch.md +78 -0
  165. package/agent/docs-md/table-settings.md +81 -0
  166. package/agent/docs-md/tabs.md +85 -0
  167. package/agent/docs-md/tag-input.md +108 -0
  168. package/agent/docs-md/tag.md +79 -0
  169. package/agent/docs-md/task-builder.md +87 -0
  170. package/agent/docs-md/team-instructions.md +72 -0
  171. package/agent/docs-md/templates-gallery.md +85 -0
  172. package/agent/docs-md/text-input.md +160 -0
  173. package/agent/docs-md/thinking-steps.md +89 -0
  174. package/agent/docs-md/timeline.md +189 -0
  175. package/agent/docs-md/timestamp.md +84 -0
  176. package/agent/docs-md/timestamps.md +70 -0
  177. package/agent/docs-md/toast.md +117 -0
  178. package/agent/docs-md/tooltip.md +90 -0
  179. package/agent/docs-md/typography.md +62 -0
  180. package/agent/docs-md/undo-destructive.md +66 -0
  181. package/agent/docs-md/unsaved-changes.md +71 -0
  182. package/agent/docs-md/usage-meter.md +80 -0
  183. package/agent/docs-md/user-feedback.md +71 -0
  184. package/agent/docs-md/voice-and-tone.md +60 -0
  185. package/agent/docs-md/why-choice.md +93 -0
  186. package/agent/docs-md/workspace-onboarding.md +74 -0
  187. package/agent/docs-md/writing.md +48 -0
  188. package/agent/llms-full.txt +18369 -0
  189. package/agent/llms.txt +198 -0
  190. package/agent/skills/twoux-audit/SKILL.md +49 -0
  191. package/agent/skills/twoux-build/SKILL.md +39 -0
  192. package/agent/skills/twoux-design/SKILL.md +54 -0
  193. package/agent/skills/twoux-write/SKILL.md +32 -0
  194. package/bin/check.mjs +123 -0
  195. package/bin/docs.mjs +24 -0
  196. package/bin/guard.mjs +27 -0
  197. package/bin/init.mjs +113 -0
  198. package/bin/knowledge.mjs +87 -0
  199. package/bin/mcp.mjs +116 -0
  200. package/bin/theme.mjs +168 -0
  201. package/bin/twoux.mjs +25 -0
  202. package/package.json +80 -3
  203. package/registry/jobs.json +1028 -0
  204. package/registry/palette.json +770 -0
  205. package/registry/rules.json +913 -0
  206. package/src/components/agent-review.tsx +364 -0
  207. package/src/components/ai-basics.tsx +212 -0
  208. package/src/components/ai-work.tsx +304 -0
  209. package/src/components/ai.tsx +227 -0
  210. package/src/components/alert-dialog.tsx +203 -0
  211. package/src/components/alert.tsx +86 -0
  212. package/src/components/avatar.tsx +114 -0
  213. package/src/components/badge.tsx +59 -0
  214. package/src/components/board.tsx +397 -0
  215. package/src/components/breadcrumb.tsx +114 -0
  216. package/src/components/button-group.tsx +90 -0
  217. package/src/components/button.tsx +109 -0
  218. package/src/components/calendar.tsx +247 -0
  219. package/src/components/card.tsx +102 -0
  220. package/src/components/chart-map.tsx +336 -0
  221. package/src/components/charts-more.tsx +1331 -0
  222. package/src/components/charts-radial.tsx +328 -0
  223. package/src/components/charts.tsx +390 -0
  224. package/src/components/checkbox.tsx +40 -0
  225. package/src/components/code.tsx +139 -0
  226. package/src/components/collapsible.tsx +37 -0
  227. package/src/components/combobox.tsx +339 -0
  228. package/src/components/command-extras.tsx +11 -0
  229. package/src/components/command.tsx +196 -0
  230. package/src/components/data-grid.tsx +213 -0
  231. package/src/components/data-table.tsx +334 -0
  232. package/src/components/data-views.tsx +740 -0
  233. package/src/components/date-picker.tsx +686 -0
  234. package/src/components/dense-table.tsx +207 -0
  235. package/src/components/dialog.tsx +162 -0
  236. package/src/components/dropdown-menu.tsx +264 -0
  237. package/src/components/empty.tsx +114 -0
  238. package/src/components/feedback-prompt.tsx +80 -0
  239. package/src/components/field.tsx +254 -0
  240. package/src/components/fields.tsx +112 -0
  241. package/src/components/flow.tsx +840 -0
  242. package/src/components/guide-cue.tsx +273 -0
  243. package/src/components/inbox.tsx +113 -0
  244. package/src/components/input-group.tsx +176 -0
  245. package/src/components/input.tsx +26 -0
  246. package/src/components/kbd.tsx +34 -0
  247. package/src/components/label.tsx +27 -0
  248. package/src/components/labels.tsx +176 -0
  249. package/src/components/motion.tsx +136 -0
  250. package/src/components/onboarding.tsx +454 -0
  251. package/src/components/order-book.tsx +185 -0
  252. package/src/components/pane-layout.tsx +417 -0
  253. package/src/components/popover.tsx +96 -0
  254. package/src/components/provider-logos.data.ts +49 -0
  255. package/src/components/radio-group.tsx +52 -0
  256. package/src/components/scheduler.tsx +997 -0
  257. package/src/components/segmented-control.tsx +28 -0
  258. package/src/components/select.tsx +195 -0
  259. package/src/components/separator.tsx +31 -0
  260. package/src/components/sheet.tsx +148 -0
  261. package/src/components/shell.tsx +426 -0
  262. package/src/components/shortcut-sheet.tsx +83 -0
  263. package/src/components/skeleton.tsx +18 -0
  264. package/src/components/sonner.tsx +107 -0
  265. package/src/components/spinner.tsx +13 -0
  266. package/src/components/split-button.tsx +58 -0
  267. package/src/components/stepper.tsx +78 -0
  268. package/src/components/switch.tsx +43 -0
  269. package/src/components/table.tsx +126 -0
  270. package/src/components/tabs.tsx +118 -0
  271. package/src/components/tag-input.tsx +253 -0
  272. package/src/components/textarea.tsx +21 -0
  273. package/src/components/theme.tsx +80 -0
  274. package/src/components/timeline.tsx +408 -0
  275. package/src/components/toggle-group.tsx +87 -0
  276. package/src/components/toggle.tsx +54 -0
  277. package/src/components/tooltip.tsx +65 -0
  278. package/src/components/workspace-actions.tsx +294 -0
  279. package/src/components/workspace-import.tsx +465 -0
  280. package/src/components/workspace.tsx +1884 -0
  281. package/src/index.ts +80 -0
  282. package/src/lib/active-indicator.tsx +53 -0
  283. package/src/lib/chart-kit.tsx +72 -0
  284. package/src/lib/cn.ts +6 -0
  285. package/src/lib/shortcuts.tsx +61 -0
  286. package/src/lib/workspace.tsx +10 -0
  287. package/src/shadcn/alert-dialog.tsx +196 -0
  288. package/src/shadcn/alert.tsx +65 -0
  289. package/src/shadcn/avatar.tsx +108 -0
  290. package/src/shadcn/badge.tsx +47 -0
  291. package/src/shadcn/breadcrumb.tsx +108 -0
  292. package/src/shadcn/button-group.tsx +83 -0
  293. package/src/shadcn/button.tsx +63 -0
  294. package/src/shadcn/calendar.tsx +220 -0
  295. package/src/shadcn/card.tsx +91 -0
  296. package/src/shadcn/checkbox.tsx +31 -0
  297. package/src/shadcn/collapsible.tsx +33 -0
  298. package/src/shadcn/command.tsx +184 -0
  299. package/src/shadcn/dialog.tsx +158 -0
  300. package/src/shadcn/dropdown-menu.tsx +256 -0
  301. package/src/shadcn/empty.tsx +103 -0
  302. package/src/shadcn/field.tsx +248 -0
  303. package/src/shadcn/input-group.tsx +170 -0
  304. package/src/shadcn/input.tsx +20 -0
  305. package/src/shadcn/kbd.tsx +28 -0
  306. package/src/shadcn/label.tsx +23 -0
  307. package/src/shadcn/popover.tsx +88 -0
  308. package/src/shadcn/radio-group.tsx +44 -0
  309. package/src/shadcn/select.tsx +189 -0
  310. package/src/shadcn/separator.tsx +27 -0
  311. package/src/shadcn/sheet.tsx +142 -0
  312. package/src/shadcn/skeleton.tsx +13 -0
  313. package/src/shadcn/sonner.tsx +40 -0
  314. package/src/shadcn/switch.tsx +34 -0
  315. package/src/shadcn/table.tsx +115 -0
  316. package/src/shadcn/tabs.tsx +90 -0
  317. package/src/shadcn/textarea.tsx +17 -0
  318. package/src/shadcn/toggle-group.tsx +83 -0
  319. package/src/shadcn/toggle.tsx +46 -0
  320. package/src/shadcn/tooltip.tsx +56 -0
  321. package/src/styles/palette.css +127 -0
  322. package/src/styles/theme.css +35 -0
  323. package/src/styles/twoux.css +236 -0
  324. package/theme.json +14 -0
  325. package/README.md +0 -3
@@ -0,0 +1,88 @@
1
+ # Pagination and counts
2
+
3
+ The footer that says which rows are showing and how many exist ("1–100 of 1,262"), with previous and next controls and the selection count.
4
+
5
+ Kind: component · Group: Data · Status: built, import from @twoux/ui
6
+
7
+ ## When to use
8
+
9
+ - A collection is too large for one page or one view.
10
+ - Lists over 20 items, with pagination at the bottom.
11
+ - People need to know where they are and return to a section, which pagination supports better than endless scroll.
12
+
13
+ ## When not to use
14
+
15
+ - Collections under five items.
16
+ - Steps in a flow. Use buttons or a progress control.
17
+ - When the total cannot be known, do not invent one; use an open-ended count such as "100+".
18
+
19
+ ## Structure
20
+
21
+ 1. Range and total ("Showing 1–9 of 24")
22
+ 2. Selection count when rows are selected
23
+ 3. Previous page
24
+ 4. Page numbers or compact "1 of 3"
25
+ 5. Next page
26
+
27
+ ## Guidelines
28
+
29
+ - Show the range and the total. When rows are selected, put the selected count first.
30
+ - Use the compact "1 of 3" form where a row of page numbers does not fit, and offer jump to page past about 9 pages.
31
+ - Previous is inactive on the first page and Next on the last.
32
+ - Show pagination even when everything fits on one page, so the layout does not shift.
33
+ - Changing page clears the selection; say so in the selection count.
34
+
35
+ ## Content
36
+
37
+ - Show the current range and the total together, for example "1–100 of 1,262", with an en dash and thousands separators.
38
+ - Name controls by destination, "Previous page", "Page 6", not "left".
39
+ - Do not show a count while the table is loading.
40
+
41
+ ## Accessibility
42
+
43
+ - Wrap page links in a nav landmark with an aria-label, and mark the current page with aria-current="page".
44
+ - Give previous, next and page buttons labels; set them explicitly for non-English interfaces.
45
+ - 4.1.3 Status Messages: the range and selection count update as status text, "2 of 24 selected".
46
+ - After a page change, move focus and scroll to the top of the new content.
47
+
48
+ ## Keyboard
49
+
50
+ | Keys | Action |
51
+ |---|---|
52
+ | Tab | Reach the pagination controls |
53
+ | Enter / Space | Go to the previous, next or chosen page |
54
+
55
+ ## Examples
56
+
57
+ ### footer
58
+
59
+ ```tsx
60
+ import { Checkbox, TablePagination } from "@twoux/ui";
61
+ import { useState } from "react";
62
+
63
+ export const meta = { title: "Table footer", description: "Range and total always show, even on one page. With rows selected, the count comes first. Previous is off on the first page, Next on the last.", order: 1 };
64
+
65
+ export default function Example() {
66
+ const [page, setPage] = useState(0);
67
+ const [selectSome, setSelectSome] = useState(true);
68
+ return (
69
+ <div className="grid w-full max-w-xl gap-3">
70
+ <label className="flex items-center gap-2 text-base text-ink-2">
71
+ <Checkbox checked={selectSome} onCheckedChange={(v) => setSelectSome(v === true)} />
72
+ Show with 2 rows selected
73
+ </label>
74
+ <div className="overflow-hidden rounded-sm border border-line bg-surface">
75
+ <div className="grid h-24 place-items-center text-base text-ink-3">Page {page + 1} of the listings table</div>
76
+ <TablePagination page={page} pageCount={14} pageSize={100} total={1262} selected={selectSome ? 2 : 0} noun="listings" onPageChange={setPage} />
77
+ </div>
78
+ </div>
79
+ );
80
+ }
81
+ ```
82
+
83
+ ## Related
84
+
85
+ - List table
86
+ - Data grid
87
+ - Columns menu
88
+ - Bulk action bar
@@ -0,0 +1,105 @@
1
+ # Pane layout
2
+
3
+ A workspace that fills the screen with columns of panes people resize with splitters and rearrange by dragging, for tool pages such as trading screens and editors where everything has to stay in view.
4
+
5
+ Kind: component · Group: Navigation · Status: built, import from @twoux/ui
6
+
7
+ ## When to use
8
+
9
+ - Tool pages where people watch and act on several regions at once and need them all in view, such as a trading screen.
10
+ - Letting people give more room to the region they work in and put regions where they expect them.
11
+
12
+ ## When not to use
13
+
14
+ - List, record and dashboard pages. Use the app shell with one side panel, or a Configurable dashboard for movable items.
15
+ - Content people read top to bottom. Let the page scroll instead.
16
+
17
+ ## Structure
18
+
19
+ 1. Columns of panes, edge to edge, divided by 1px splitters
20
+ 2. Pane header: grip, title or a view switch, one action, ⋯ menu
21
+ 3. Pane body that scrolls on its own
22
+ 4. Splitter: 1px line with an 8px grab area, primary on hover and focus
23
+ 5. Drop line in primary where a dragged pane will land
24
+ 6. Collapsed: header only, or a 36px strip with the name when the whole column is collapsed
25
+
26
+ ## Guidelines
27
+
28
+ - Fit the viewport: panes scroll inside, and charts and lists size themselves to their pane with usePaneSize.
29
+ - Every drag has a keyboard path and a menu path: Move up, down, left, right and Wider, Narrower, Taller, Shorter.
30
+ - Splitters follow the window splitter pattern: role separator, a value from 0 to 100, arrow keys, Home and End.
31
+ - Save the layout per person, and offer Reset layout with Undo, never a confirmation.
32
+ - One action at most in a pane header; switch views with a segmented control in place of the title.
33
+ - Below the stack width, panes stack in one column and the page scrolls.
34
+ - Let people collapse a pane they don't need right now; it keeps its header so it is one click from coming back.
35
+ - Put a pane's own options, such as Show as table, at the top of its ⋯ menu rather than as more header buttons.
36
+ - Put a strip of at most six key figures above the panes, the ones people check first, and keep the panes for detail.
37
+ - Keep secondary detail behind a request: an expandable row, a tooltip or the pane's ⋯ menu (Show as table, View all), so the panes show what people watch.
38
+ - Keep panes people use all the time, such as filters, as panes rather than drawers, so they never hide the controls they hold.
39
+
40
+ ## Content
41
+
42
+ - Name every pane with a noun people use for that region: Markets, Order book, Place order.
43
+
44
+ ## Accessibility
45
+
46
+ - 2.5.7 Dragging movements: moving and resizing work from the pane's menu with single clicks.
47
+ - Each pane is a section named by its title; each move and resize is announced.
48
+ - 1.4.10 Reflow: below the stack width the panes stack and nothing scrolls sideways.
49
+
50
+ ## Keyboard
51
+
52
+ | Keys | Action |
53
+ |---|---|
54
+ | ← → (column splitter), ↑ ↓ (pane splitter) | Resize by 16px; with Shift, 64px |
55
+ | Home End | Smallest or largest size |
56
+ | Space or Enter on a grip | Pick up or drop the pane |
57
+ | ← → ↑ ↓ while picked up | Move the pane to another column or position |
58
+ | Esc while picked up | Put the pane back |
59
+
60
+ ## Examples
61
+
62
+ ### workspace
63
+
64
+ ```tsx
65
+ import { PaneLayout, type PaneLayoutValue, toast, usePaneSize } from "@twoux/ui";
66
+ import { useState } from "react";
67
+
68
+ export const meta = { title: "Resize and rearrange panes", description: "Three panes in two columns. Drag a splitter or use its arrow keys to resize; drag a pane's grip, or press Space on it and use the arrow keys, to move it; or use Move, Wider and Taller in the pane's menu. Each pane reports its own size.", order: 1 };
69
+
70
+ const DEFAULT: PaneLayoutValue = [
71
+ { id: "left", size: 2, panes: [{ id: "list", size: 1 }] },
72
+ { id: "right", size: 3, panes: [{ id: "detail", size: 2 }, { id: "log", size: 1 }] },
73
+ ];
74
+
75
+ function Size() {
76
+ const { width, height } = usePaneSize();
77
+ return <p className="p-3 text-sm text-ink-2 tabular">{width} × {height} px</p>;
78
+ }
79
+
80
+ export default function Example() {
81
+ const [layout, setLayout] = useState(DEFAULT);
82
+ return (
83
+ <div className="h-96 w-full overflow-hidden rounded-sm border border-line">
84
+ <PaneLayout
85
+ aria-label="Example workspace"
86
+ stackBelow={480}
87
+ value={layout}
88
+ onValueChange={setLayout}
89
+ onReset={() => { const before = layout; setLayout(DEFAULT); toast.success("Layout reset", { action: { label: "Undo", onClick: () => setLayout(before) } }); }}
90
+ panes={{
91
+ list: { title: "Requests", children: <Size /> },
92
+ detail: { title: "Request detail", children: <Size /> },
93
+ log: { title: "Activity", children: <Size /> },
94
+ }}
95
+ />
96
+ </div>
97
+ );
98
+ }
99
+ ```
100
+
101
+ ## Related
102
+
103
+ - App shell and sidebar navigation
104
+ - Side panel (drawer)
105
+ - Board and board item
@@ -0,0 +1,66 @@
1
+ # Comparison over time
2
+
3
+ Every headline number says what it compares against: this period vs the previous period of the same length, with arrow, sign and colour.
4
+
5
+ Kind: pattern · Group: Patterns: general
6
+
7
+ **Problem:** "312 applications" means nothing on its own. Teams add comparisons in different ways (vs last month, vs last year, percentage or absolute), so numbers on different screens can't be read together.
8
+
9
+ **Solution:** TwoUX compares the current period with the previous period of the same length by default. Stats show the number, then the change with arrow, sign and colour, then what it is compared with. Charts draw the previous period as a dashed grey line behind the current one.
10
+
11
+ **Built from:** Stat card with comparison, Line chart card, Breakdown table, Bar chart, Segmented control, Data visualisation colours
12
+
13
+ ## How it works
14
+
15
+ 1. Pick the period with one control above the chart: 7d, 30d, 90d. It drives every chart and stat on the page.
16
+ 2. The stat leads with the number, then the change ("↑ 18%"), then the comparison in words ("vs 264 the 30 days before").
17
+ 3. The line chart shows the previous period as a dashed grey line behind the current period, with a legend naming both.
18
+ 4. Under the chart, the breakdown table shows current and previous side by side and the change in both units.
19
+ 5. Every chart can switch to a table, which is also its accessible version.
20
+
21
+ ## When to use
22
+
23
+ - For any KPI or trend on a dashboard, report or record header.
24
+ - Next to a single figure in a record, compare with the board median instead of time, so people can judge it without opening a report.
25
+
26
+ ## When not to use
27
+
28
+ - When there is no previous period (new listing, new team). Show a dash, not "+100%".
29
+ - To compare categories in one period. Use a bar chart or breakdown, not a time comparison.
30
+
31
+ ## Guidelines
32
+
33
+ - Never rely on colour alone for up or down; always add an arrow and a sign.
34
+ - Green and red follow meaning, not direction. A fall in time to first apply is good.
35
+ - Bars start at zero. Line charts may start elsewhere, but say so on the axis.
36
+ - One y-axis per chart. Two measures with different scales get two charts side by side.
37
+ - Keep each series the same colour on every chart; status colours never colour a series.
38
+ - The current, incomplete period is marked as incomplete so a half week does not look like a drop.
39
+
40
+ ## Content
41
+
42
+ - Change text: "↑ 18% vs 264 the 30 days before". Units are always stated.
43
+ - Chart footer names the source and when it updated: "updated 12 min ago".
44
+
45
+ ## Accessibility
46
+
47
+ - The change is read as text ("up 18 percent"), not only drawn as an arrow.
48
+ - Chart points are reachable with the arrow keys, and the table view carries every number.
49
+
50
+ ## Do
51
+
52
+ - Do say what every number is compared against.
53
+ - Do use the previous period of the same length.
54
+
55
+ ## Don't
56
+
57
+ - Don't use two y-axes.
58
+ - Don't show a percentage change from zero.
59
+
60
+ ## Related
61
+
62
+ - Data export
63
+ - Filtering and search
64
+ - Stat card with comparison
65
+ - Line chart card
66
+ - Breakdown table
@@ -0,0 +1,120 @@
1
+ # Plan preview
2
+
3
+ The plan an agent shows before a multi-step or costly run: numbered steps people can remove, risky steps marked in words, and nothing running until it is approved.
4
+
5
+ Kind: component · Group: AI and agents · Status: built, import from @twoux/ui
6
+
7
+ ## When to use
8
+
9
+ - Before any run with several steps, or one that costs time or money, so people can see it first.
10
+ - When a step reaches people outside the workspace (an email, a message to a candidate) or cannot be undone (a close, a delete).
11
+ - When the agent was started by a schedule or a request people did not write step by step.
12
+
13
+ ## When not to use
14
+
15
+ - A single, small change. Use Suggested changes (suggested-changes), which is the review step for one proposal.
16
+ - Questions whose answer would change the plan. Ask first with a Clarifying question (clarifying-question); show the plan once the answer is known.
17
+ - Work that has already started. Show progress in the Agent run (agent-run) and use PlanChange only if the plan itself changes.
18
+
19
+ ## Structure
20
+
21
+ 1. Header (plan title, origin label with what it is based on)
22
+ 2. Step rows (number, step, optional detail, risk line, Remove or Put back)
23
+ 3. Footer (count "3 of 4 steps", note "nothing runs until you approve", Cancel, Approve plan)
24
+ 4. Plan change line (PlanChange) in the run if the plan changes later
25
+
26
+ ## Guidelines
27
+
28
+ - Show the plan before any multi-step or costly run. Nothing runs until the person approves, and never on a timeout.
29
+ - Each step is a plain action with its detail underneath. People can remove a step, and put it back, before approving.
30
+ - Mark steps that reach people outside the workspace or cannot be undone, with an icon and words, not colour alone.
31
+ - The footer counts what will run ("3 of 4 steps") and updates as steps are removed. Approve is disabled when no steps are left.
32
+ - When any step is high-stakes, Approve and Cancel carry equal weight. This is the one exception to one primary action: both are outline buttons, so neither is nudged.
33
+ - If the plan changes mid-run, add a PlanChange line saying what changed and why. Never reroute silently.
34
+ - Ask clarifying questions first only if the answer changes the plan. Otherwise show the plan and let people adjust it.
35
+
36
+ ## Content
37
+
38
+ - Title the plan by its outcome ("Close three expired listings and tell applicants"), not by the agent's method.
39
+ - Write steps as actions in the order they happen. Put the consequence in the detail line: "Sends an email to 14 applicants".
40
+ - Name the risk in words: "Reaches people outside the workspace" or "Can't be undone". Do not soften it.
41
+ - PlanChange reads as what changed, then why: "Plan changed: skipped the email step. The listing has no applicants."
42
+
43
+ ## Accessibility
44
+
45
+ - The plan is an ordered list, so the number of steps and each position are announced (SC 1.3.1).
46
+ - Risk is shown by an icon and a line of text, not colour alone (SC 1.4.1).
47
+ - Remove and Put back are real buttons with the step number in their hidden label, and a removed step carries the hidden word "removed" (SC 4.1.2).
48
+ - Nothing starts on a timer, so there is no time limit to adjust (SC 2.2.1). Approving is the review step for work that records data (SC 3.3.4).
49
+ - PlanChange is a role="status" line, so a plan change is announced without moving focus (SC 4.1.3).
50
+
51
+ ## Keyboard
52
+
53
+ | Keys | Action |
54
+ |---|---|
55
+ | Tab | Move through Remove buttons, then Cancel and Approve plan |
56
+ | Enter / Space | Remove or put back the focused step, or press the focused button |
57
+
58
+ ## Examples
59
+
60
+ ### low-stakes
61
+
62
+ ```tsx
63
+ import { PlanCard, PlanChange, toast } from "@twoux/ui";
64
+
65
+ export const meta = { title: "A plan, then a change to it", description: "With no risky step, Approve is the one primary action. If the plan changes during the run, a PlanChange line says what and why.", order: 2 };
66
+
67
+ export default function Example() {
68
+ return (
69
+ <div className="grid w-full max-w-xl gap-3">
70
+ <PlanCard
71
+ title="Tidy the Operations Coordinator listing"
72
+ from="Your request, listing LST-1041"
73
+ steps={[
74
+ { id: "1", title: "Rename the listing", detail: "Operations Coordinator (hybrid)" },
75
+ { id: "2", title: "Add the salary range", detail: "£32,000 to £36,000" },
76
+ { id: "3", title: "Extend the closing date by 30 days", detail: "21 Nov to 21 Dec" },
77
+ ]}
78
+ onApprove={(kept) => toast.success(`Approved ${kept.length} steps`)}
79
+ onCancel={() => toast("Plan cancelled. Nothing ran.")}
80
+ />
81
+ <PlanChange what="Skipped the salary step" why="The listing already shows a range." />
82
+ </div>
83
+ );
84
+ }
85
+ ```
86
+
87
+ ### plan
88
+
89
+ ```tsx
90
+ import { PlanCard, toast } from "@twoux/ui";
91
+
92
+ export const meta = { title: "A plan with a risky step", description: "Steps can be removed. The step that emails applicants is marked, so Approve and Cancel carry equal weight. Nothing runs until you approve.", order: 1 };
93
+
94
+ export default function Example() {
95
+ return (
96
+ <div className="w-full max-w-xl">
97
+ <PlanCard
98
+ title="Close three expired listings and tell applicants"
99
+ from="Weekly listing check, 3 listings past their closing date"
100
+ steps={[
101
+ { id: "1", title: "Find listings past their closing date", detail: "Filter: Closes is before today · 3 listings" },
102
+ { id: "2", title: "Close the 3 listings", detail: "Hides them from the careers page", risk: "irreversible" },
103
+ { id: "3", title: "Email 14 applicants that the role has closed", detail: "Uses the template Role closed", risk: "external" },
104
+ { id: "4", title: "Post a summary to #hiring" },
105
+ ]}
106
+ onApprove={(kept) => toast.success(`Approved ${kept.length} steps`)}
107
+ onCancel={() => toast("Plan cancelled. Nothing ran.")}
108
+ />
109
+ </div>
110
+ );
111
+ }
112
+ ```
113
+
114
+ ## Related
115
+
116
+ - Agent run timeline
117
+ - Clarifying question card
118
+ - Agent permissions
119
+ - Suggested changes
120
+ - Step card
@@ -0,0 +1,88 @@
1
+ # Popover rules
2
+
3
+ Shared behaviour for every floating layer (menus, filters, snooze, selectors): one open at a time and never cut off.
4
+
5
+ Kind: component · Group: Actions and inputs · Status: built, import from @twoux/ui
6
+
7
+ ## When to use
8
+
9
+ - For short supporting content or a small set of controls tied to a trigger: filter values, snooze times, column choices.
10
+ - When the person must stay in context and the page behind stays usable.
11
+
12
+ ## When not to use
13
+
14
+ - For long reading or a multi-step task. Use a dialog or side panel.
15
+ - For a one-line label. Use Tooltip.
16
+ - Inside another popover. Open a submenu (one level) or a dialog instead.
17
+ - For required fields that would be lost on outside click. Use a dialog.
18
+
19
+ ## Structure
20
+
21
+ 1. Trigger (aria-expanded)
22
+ 2. Floating panel (10px radius, shadow)
23
+ 3. Header (when dismissible)
24
+ 4. Body
25
+ 5. Footer actions (optional)
26
+
27
+ ## Guidelines
28
+
29
+ - Only one popover is open at a time; opening a menu, filter, snooze or selector closes any other.
30
+ - Popovers open on a user action, never on page load.
31
+ - Placement flips and shifts to stay inside the panel and the screen, 8px from the edge. Nothing is ever cut off.
32
+ - Open 4 to 6px from the trigger, aligned to its start edge.
33
+ - Close on outside click, Esc, or when focus leaves; return focus to the trigger.
34
+ - Only the body scrolls, never sideways.
35
+
36
+ ## Content
37
+
38
+ - Header in sentence case, one short line, when the popover can be dismissed.
39
+ - No help articles or Learn more links inside; keep help at page level.
40
+ - Footer buttons follow Button wording: Cancel and Apply.
41
+
42
+ ## Accessibility
43
+
44
+ - Triggers set aria-expanded (and aria-haspopup for menus). Enter or Space opens.
45
+ - Give the panel a role (menu or dialog) and a label.
46
+ - Esc closes and focus returns to the trigger.
47
+ - The popover must not hide the focused element.
48
+ - At 320px width it fits without sideways scrolling.
49
+
50
+ ## Keyboard
51
+
52
+ | Keys | Action |
53
+ |---|---|
54
+ | Enter / Space | Open or close from the trigger |
55
+ | Esc | Close and return focus to the trigger |
56
+ | Tab | Move through controls inside; leaving closes it |
57
+
58
+ ## Examples
59
+
60
+ ### one-at-a-time
61
+
62
+ ```tsx
63
+ import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, FilterBar, FilterPill } from "@twoux/ui";
64
+ import { useState } from "react";
65
+
66
+ export const meta = { title: "One at a time, never cut off", description: "Open the Status filter, then the menu: the first closes. Each opens 4px from its trigger, flips and shifts to stay 8px inside the screen, and Esc returns focus to the trigger.", order: 1 };
67
+
68
+ const OPTIONS = ["Open", "Closing soon", "Draft", "Closed"].map((v) => ({ value: v, label: v }));
69
+
70
+ export default function Example() {
71
+ const [status, setStatus] = useState<string[]>([]);
72
+ return (
73
+ <div className="flex w-full items-center justify-between gap-3">
74
+ <FilterBar><FilterPill field="Status" options={OPTIONS} selected={status} onChange={setStatus} /></FilterBar>
75
+ <DropdownMenu>
76
+ <DropdownMenuTrigger asChild><Button variant="outline" size="sm">Actions</Button></DropdownMenuTrigger>
77
+ <DropdownMenuContent align="end"><DropdownMenuItem>Duplicate</DropdownMenuItem><DropdownMenuItem>Archive</DropdownMenuItem></DropdownMenuContent>
78
+ </DropdownMenu>
79
+ </div>
80
+ );
81
+ }
82
+ ```
83
+
84
+ ## Related
85
+
86
+ - Dropdown menu
87
+ - Tooltip
88
+ - Button
@@ -0,0 +1,90 @@
1
+ # Prompt editor with fields
2
+
3
+ An editor where row fields and team files are removable chips, inputs and outputs are listed with types, and the prompt is tested on a few rows before running on the whole table.
4
+
5
+ Kind: component · Group: AI and agents · Status: built, import from @twoux/ui
6
+
7
+ ## When to use
8
+
9
+ - Defining the prompt behind an AI column or a per-row agent.
10
+ - When the output must have a type (text, person, link) to land in the table.
11
+
12
+ ## When not to use
13
+
14
+ - Asking a question once. Use the Message composer (message-composer).
15
+ - Repeated tasks with filter inputs. Use the Task builder (task-builder).
16
+
17
+ ## Structure
18
+
19
+ 1. Hint line ({{ for a field, @ for a team file, ⌘K to rewrite)
20
+ 2. Prompt text with field chips
21
+ 3. Inputs list with types
22
+ 4. Output (one field or several) with types
23
+ 5. Suggest outputs from prompt
24
+ 6. Test on 3 rows
25
+
26
+ ## Guidelines
27
+
28
+ - Fields are chips you can remove, not hidden syntax.
29
+ - List inputs and outputs with their type.
30
+ - Test on a few rows before running on the whole table; show the per-row cost.
31
+ - Let the prompt return "Not found" when it is unsure, rather than forcing an answer.
32
+ - ⌘K rewrites selected text as a suggestion, not an overwrite.
33
+
34
+ ## Content
35
+
36
+ - Use plain headings in the prompt ("Your task", "Rules").
37
+ - Field names match the column names people see.
38
+
39
+ ## Accessibility
40
+
41
+ - Each chip's remove button is named ("Remove field listing.title") (SC 4.1.2).
42
+ - {{ and @ open a combobox list of fields or files, with arrow keys and Enter (APG combobox).
43
+ - Output type is a radiogroup with a label (APG radio).
44
+
45
+ ## Keyboard
46
+
47
+ | Keys | Action |
48
+ |---|---|
49
+ | {{ | Add a field from the row |
50
+ | @ | Add a team file |
51
+ | ⌘K / Ctrl+K | Rewrite the selected text |
52
+ | Enter | Insert the highlighted field |
53
+ | Esc | Close the field list |
54
+
55
+ ## Examples
56
+
57
+ ### editor
58
+
59
+ ```tsx
60
+ import { PromptEditor } from "@twoux/ui";
61
+ import { useState } from "react";
62
+
63
+ export const meta = { title: "Prompt with fields as chips", description: "Fields from the row are removable chips, not hidden syntax. Inputs and outputs are listed with their type, and Test on 3 rows comes before running on the whole table.", order: 1 };
64
+
65
+ export default function Example() {
66
+ const [segs, setSegs] = useState<(string | { field: string })[]>(["List the 3 key requirements in ", { field: "description" }, " for the role ", { field: "role" }, ", in under 12 words."]);
67
+ const [testing, setTesting] = useState(false);
68
+ const [results, setResults] = useState<{ row: string; value: string }[]>();
69
+ return (
70
+ <div className="w-full max-w-xl">
71
+ <PromptEditor
72
+ segments={segs}
73
+ onRemoveField={(i) => setSegs((s) => s.filter((_, j) => j !== i))}
74
+ inputs={[{ name: "description", type: "Long text" }, { name: "role", type: "Text" }]}
75
+ outputs={[{ name: "key_requirements", type: "Text" }]}
76
+ testing={testing}
77
+ results={results}
78
+ onTest={() => { setTesting(true); setTimeout(() => { setTesting(false); setResults([{ row: "LST-1040", value: "Portfolio, Figma, hybrid in Leeds" }, { row: "LST-1041", value: "React, TypeScript, 3+ years" }, { row: "LST-1045", value: "Playwright, CI, test plans" }]); }, 800); }}
79
+ />
80
+ </div>
81
+ );
82
+ }
83
+ ```
84
+
85
+ ## Related
86
+
87
+ - AI column
88
+ - Task builder
89
+ - Templates gallery
90
+ - Change review
@@ -0,0 +1,65 @@
1
+ # Propose, then apply
2
+
3
+ The assistant never edits on its own: it lists suggested changes with checkboxes, the person applies them in one step, each change shows its progress, and Undo reverses all of it.
4
+
5
+ Kind: pattern · Group: Patterns: AI
6
+
7
+ **Problem:** When AI edits records directly, people can't see what changed or trust it with real data. When every feature invents its own approval flow, nobody knows whether clicking a suggestion has already changed something.
8
+
9
+ **Solution:** Changes arrive as a Suggested changes card: one row per change with what changes, an Edit and a Dismiss. Apply N changes (⌘↵) turns the card into a step card that ticks off each change as the table updates. A toast offers Undo.
10
+
11
+ **Built from:** Suggested changes, Step card, Assistant side panel, Toast, Agent permissions, AI origin label
12
+
13
+ ## How it works
14
+
15
+ 1. The answer ends with "Suggested changes · 2", each a row with a checkbox, the change and its effect ("New closing date 6 Dec").
16
+ 2. "Nothing changes until you apply" sits next to the buttons: Dismiss, Edit, Apply 2 changes ⌘↵.
17
+ 3. The person unticks, edits or dismisses individual changes without regenerating the whole proposal.
18
+ 4. Apply turns the card into a step card: each change gets a spinner then a tick, with a counter "1 / 2". The table updates row by row.
19
+ 5. When done, a toast confirms ("2 changes applied") with Undo; ⌘Z also works.
20
+ 6. If a change fails, its step says why and offers Retry; the others stay applied.
21
+
22
+ ## When to use
23
+
24
+ - Whenever the assistant or an agent would change records: rename, extend, close, reassign.
25
+
26
+ ## When not to use
27
+
28
+ - For answers that change nothing; just answer.
29
+ - For actions the person set to Allow in agent permissions; those run and are logged, with Undo where possible.
30
+ - For changes that reach people outside the workspace, such as emailing candidates. Those also need explicit approval of the message itself (see Agents acting on your behalf).
31
+
32
+ ## Guidelines
33
+
34
+ - A proposal shows the consequence of each change before it runs, including whether it can be undone.
35
+ - Approve is never pre-selected or auto-focused for risky changes.
36
+ - If applying needs to deviate from the proposal, stop and explain rather than change something else.
37
+ - The proposal is the same component everywhere: assistant answers, agent runs and the Inbox.
38
+
39
+ ## Content
40
+
41
+ - Each change is a verb and object with its effect: "Extend Operations Coordinator by 30 days. New closing date 6 Dec."
42
+ - Apply button says the count: "Apply 2 changes".
43
+
44
+ ## Accessibility
45
+
46
+ - Step progress and completion are announced as status messages.
47
+ - Apply has a keyboard shortcut (⌘↵) and focus does not jump to it automatically.
48
+
49
+ ## Do
50
+
51
+ - Do let people untick individual changes.
52
+ - Do offer Undo after applying.
53
+
54
+ ## Don't
55
+
56
+ - Don't apply anything from inside the answer text.
57
+ - Don't regenerate the whole proposal to fix one change.
58
+
59
+ ## Related
60
+
61
+ - Undo and destructive actions
62
+ - Agents acting on your behalf
63
+ - Showing reasoning and progress
64
+ - Suggested changes
65
+ - Step card