@godxjp/ui 28.8.0 → 28.10.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 (271) hide show
  1. package/agent/START-HERE.md +193 -0
  2. package/agent/anti-ai-tells.json +158 -0
  3. package/agent/components/Accordion.json +60 -0
  4. package/agent/components/AccountChip.json +59 -0
  5. package/agent/components/Actions.json +78 -0
  6. package/agent/components/Activity.json +80 -0
  7. package/agent/components/Affix.json +78 -0
  8. package/agent/components/Alert.json +65 -0
  9. package/agent/components/AlertDialog.json +109 -0
  10. package/agent/components/AlertDialogRoot.json +52 -0
  11. package/agent/components/Anchor.json +119 -0
  12. package/agent/components/AppLauncher.json +95 -0
  13. package/agent/components/AppProvider.json +105 -0
  14. package/agent/components/AppSettingPicker.json +88 -0
  15. package/agent/components/AppSettingToggle.json +70 -0
  16. package/agent/components/AppShell.json +159 -0
  17. package/agent/components/AreaChart.json +105 -0
  18. package/agent/components/AspectRatio.json +38 -0
  19. package/agent/components/Attachments.json +76 -0
  20. package/agent/components/AuthAccountSummary.json +64 -0
  21. package/agent/components/AuthDivider.json +35 -0
  22. package/agent/components/AuthFooter.json +48 -0
  23. package/agent/components/AuthIdentity.json +42 -0
  24. package/agent/components/AuthShell.json +108 -0
  25. package/agent/components/AuthStack.json +21 -0
  26. package/agent/components/Avatar.json +89 -0
  27. package/agent/components/Badge.json +96 -0
  28. package/agent/components/Banner.json +48 -0
  29. package/agent/components/BarChart.json +108 -0
  30. package/agent/components/BranchScopePicker.json +89 -0
  31. package/agent/components/Breadcrumb.json +54 -0
  32. package/agent/components/Button.json +133 -0
  33. package/agent/components/Calendar.json +259 -0
  34. package/agent/components/Callout.json +46 -0
  35. package/agent/components/Card.json +112 -0
  36. package/agent/components/CardBar.json +49 -0
  37. package/agent/components/CardContent.json +51 -0
  38. package/agent/components/Carousel.json +50 -0
  39. package/agent/components/Cascader.json +209 -0
  40. package/agent/components/CenteredShell.json +66 -0
  41. package/agent/components/ChatBubble.json +100 -0
  42. package/agent/components/ChatBubbleList.json +64 -0
  43. package/agent/components/ChatComposer.json +160 -0
  44. package/agent/components/ChatSuggestion.json +86 -0
  45. package/agent/components/Checkbox.json +68 -0
  46. package/agent/components/CheckboxGroup.json +96 -0
  47. package/agent/components/CodeBlock.json +64 -0
  48. package/agent/components/Collapsible.json +74 -0
  49. package/agent/components/ColorPicker.json +87 -0
  50. package/agent/components/Command.json +168 -0
  51. package/agent/components/CommandPalette.json +84 -0
  52. package/agent/components/CompactBarTrend.json +101 -0
  53. package/agent/components/Conversations.json +82 -0
  54. package/agent/components/CredentialReveal.json +93 -0
  55. package/agent/components/DataState.json +79 -0
  56. package/agent/components/DataTable.json +268 -0
  57. package/agent/components/DatePicker.json +275 -0
  58. package/agent/components/Descriptions.json +67 -0
  59. package/agent/components/Dialog.json +78 -0
  60. package/agent/components/DraggablePanel.json +106 -0
  61. package/agent/components/DropdownMenu.json +102 -0
  62. package/agent/components/EmptyState.json +83 -0
  63. package/agent/components/ErrorSurface.json +128 -0
  64. package/agent/components/FeatureList.json +43 -0
  65. package/agent/components/Field.json +64 -0
  66. package/agent/components/FilterBar.json +99 -0
  67. package/agent/components/Flex.json +153 -0
  68. package/agent/components/FloatButton.json +91 -0
  69. package/agent/components/Form.json +87 -0
  70. package/agent/components/FormErrors.json +51 -0
  71. package/agent/components/FormField.json +137 -0
  72. package/agent/components/FormFieldArray.json +39 -0
  73. package/agent/components/FormFieldControl.json +129 -0
  74. package/agent/components/FormRoot.json +122 -0
  75. package/agent/components/Heading.json +61 -0
  76. package/agent/components/HoverCard.json +55 -0
  77. package/agent/components/Icon.json +60 -0
  78. package/agent/components/InfiniteQueryState.json +58 -0
  79. package/agent/components/Input.json +122 -0
  80. package/agent/components/InputOTP.json +106 -0
  81. package/agent/components/Label.json +43 -0
  82. package/agent/components/LegalDocumentShell.json +102 -0
  83. package/agent/components/Legend.json +42 -0
  84. package/agent/components/LineChart.json +103 -0
  85. package/agent/components/Link.json +41 -0
  86. package/agent/components/ListRow.json +92 -0
  87. package/agent/components/Logo.json +85 -0
  88. package/agent/components/Marquee.json +91 -0
  89. package/agent/components/Masonry.json +82 -0
  90. package/agent/components/MasterDetail.json +95 -0
  91. package/agent/components/MegaMenu.json +120 -0
  92. package/agent/components/MobileShell.json +73 -0
  93. package/agent/components/NavList.json +63 -0
  94. package/agent/components/NumberInput.json +158 -0
  95. package/agent/components/OrgSwitcher.json +89 -0
  96. package/agent/components/OverlayPortalProvider.json +42 -0
  97. package/agent/components/PageContainer.json +181 -0
  98. package/agent/components/Pagination.json +132 -0
  99. package/agent/components/Paragraph.json +40 -0
  100. package/agent/components/PasswordInput.json +79 -0
  101. package/agent/components/PasswordStrength.json +51 -0
  102. package/agent/components/PermissionMatrix.json +81 -0
  103. package/agent/components/PieChart.json +99 -0
  104. package/agent/components/Popover.json +110 -0
  105. package/agent/components/PrefetchLink.json +65 -0
  106. package/agent/components/Progress.json +79 -0
  107. package/agent/components/Prose.json +57 -0
  108. package/agent/components/QrCode.json +62 -0
  109. package/agent/components/Radio.json +98 -0
  110. package/agent/components/RadioGroup.json +91 -0
  111. package/agent/components/RangeTimeline.json +80 -0
  112. package/agent/components/Rating.json +92 -0
  113. package/agent/components/ResizablePanel.json +69 -0
  114. package/agent/components/ResponsiveGrid.json +77 -0
  115. package/agent/components/Reveal.json +70 -0
  116. package/agent/components/ScrollArea.json +104 -0
  117. package/agent/components/SearchInput.json +98 -0
  118. package/agent/components/Segmented.json +96 -0
  119. package/agent/components/Select.json +397 -0
  120. package/agent/components/Separator.json +86 -0
  121. package/agent/components/ServiceCatalogCta.json +46 -0
  122. package/agent/components/ServiceLauncherCard.json +86 -0
  123. package/agent/components/ServiceRolePanel.json +83 -0
  124. package/agent/components/Sheet.json +85 -0
  125. package/agent/components/Sidebar.json +118 -0
  126. package/agent/components/Skeleton.json +57 -0
  127. package/agent/components/SkeletonArticle.json +71 -0
  128. package/agent/components/SkeletonAvatar.json +50 -0
  129. package/agent/components/SkeletonButton.json +57 -0
  130. package/agent/components/SkeletonForm.json +52 -0
  131. package/agent/components/SkeletonImage.json +37 -0
  132. package/agent/components/SkeletonInput.json +51 -0
  133. package/agent/components/SkeletonNode.json +42 -0
  134. package/agent/components/SkeletonRows.json +49 -0
  135. package/agent/components/SkeletonTable.json +45 -0
  136. package/agent/components/Slider.json +160 -0
  137. package/agent/components/SplitPane.json +66 -0
  138. package/agent/components/StatCard.json +83 -0
  139. package/agent/components/Steps.json +95 -0
  140. package/agent/components/Swatch.json +41 -0
  141. package/agent/components/Switch.json +81 -0
  142. package/agent/components/Table.json +112 -0
  143. package/agent/components/Tabs.json +158 -0
  144. package/agent/components/TagInput.json +105 -0
  145. package/agent/components/Text.json +201 -0
  146. package/agent/components/Textarea.json +126 -0
  147. package/agent/components/ThoughtChain.json +76 -0
  148. package/agent/components/Thumbnail.json +70 -0
  149. package/agent/components/TimePicker.json +200 -0
  150. package/agent/components/TimeRangePicker.json +90 -0
  151. package/agent/components/Timeline.json +47 -0
  152. package/agent/components/TimelineGrid.json +92 -0
  153. package/agent/components/Title.json +67 -0
  154. package/agent/components/Toaster.json +42 -0
  155. package/agent/components/Toggle.json +90 -0
  156. package/agent/components/ToggleGroup.json +102 -0
  157. package/agent/components/Toolbar.json +120 -0
  158. package/agent/components/Tooltip.json +110 -0
  159. package/agent/components/Topbar.json +83 -0
  160. package/agent/components/TopbarItem.json +79 -0
  161. package/agent/components/Transfer.json +141 -0
  162. package/agent/components/Tree.json +185 -0
  163. package/agent/components/TreeSelect.json +232 -0
  164. package/agent/components/TwoFactorSetup.json +79 -0
  165. package/agent/components/Typography.json +42 -0
  166. package/agent/components/Upload.json +221 -0
  167. package/agent/components/UploadCropDialog.json +60 -0
  168. package/agent/components/VisuallyHidden.json +20 -0
  169. package/agent/components/Welcome.json +65 -0
  170. package/agent/components/formatDate.json +46 -0
  171. package/agent/components/inertiaUpload.json +32 -0
  172. package/agent/components/useZodForm.json +39 -0
  173. package/agent/components-index.json +884 -0
  174. package/agent/components.json +15507 -0
  175. package/agent/index.json +56 -0
  176. package/agent/llms.txt +32 -0
  177. package/agent/patterns/account-recovery-settings.json +19 -0
  178. package/agent/patterns/async-data-state.json +20 -0
  179. package/agent/patterns/auth-recovery-panels.json +29 -0
  180. package/agent/patterns/badge-coloring.json +14 -0
  181. package/agent/patterns/common-fixes.json +16 -0
  182. package/agent/patterns/confirm-destructive.json +11 -0
  183. package/agent/patterns/data-table-page.json +18 -0
  184. package/agent/patterns/deferred-loading.json +12 -0
  185. package/agent/patterns/error-pages.json +28 -0
  186. package/agent/patterns/inertia-detail-page.json +13 -0
  187. package/agent/patterns/inertia-list-page.json +15 -0
  188. package/agent/patterns/inertia-persistent-layout.json +14 -0
  189. package/agent/patterns/organization-memberships.json +19 -0
  190. package/agent/patterns/page-sections.json +18 -0
  191. package/agent/patterns/settings-page-responsive.json +18 -0
  192. package/agent/patterns/settings-section-rows.json +23 -0
  193. package/agent/patterns/signup-form.json +13 -0
  194. package/agent/patterns/topbar-account-chip.json +18 -0
  195. package/agent/patterns/transactional-email.json +22 -0
  196. package/agent/patterns-index.json +323 -0
  197. package/agent/patterns.json +342 -0
  198. package/agent/rules.json +237 -0
  199. package/agent/tokens.json +8422 -0
  200. package/agent/vocabulary.json +198 -0
  201. package/dist/components/data-entry/input.js +8 -1
  202. package/dist/components/layout/flex.d.ts +2 -2
  203. package/dist/components/layout/flex.js +2 -0
  204. package/dist/components/ui/tag-input.d.ts +10 -0
  205. package/dist/components/ui/tag-input.js +35 -2
  206. package/dist/contracts/measurement.json +1 -1
  207. package/dist/i18n/messages/en.json +23 -1
  208. package/dist/i18n/messages/ja.json +21 -1
  209. package/dist/i18n/messages/vi.json +21 -1
  210. package/dist/lib/variants.js +4 -1
  211. package/dist/props/components/data-entry.prop.d.ts +21 -2
  212. package/dist/props/components/layout.prop.d.ts +42 -0
  213. package/dist/props/registry.d.ts +9 -0
  214. package/dist/props/registry.js +6 -0
  215. package/dist/props/vocabulary/layout.prop.d.ts +1 -1
  216. package/dist/styles/base.css +47 -14
  217. package/dist/styles/card-layout.css +6 -6
  218. package/dist/styles/chart-layout.css +6 -6
  219. package/dist/styles/control.css +41 -6
  220. package/dist/styles/data-display-layout.css +21 -6
  221. package/dist/styles/density.css +2 -0
  222. package/dist/styles/dialog-layout.css +4 -1
  223. package/dist/styles/focus-ring.css +4 -1
  224. package/dist/styles/layout.css +30 -3
  225. package/dist/styles/navigation-layout.css +3 -1
  226. package/dist/styles/shell-layout.css +27 -21
  227. package/dist/styles/table-layout.css +50 -9
  228. package/dist/styles/text-layout.css +94 -23
  229. package/dist/tokens/components/activity.css +13 -4
  230. package/dist/tokens/components/attachments.css +1 -1
  231. package/dist/tokens/components/badge.css +1 -1
  232. package/dist/tokens/components/card.css +28 -7
  233. package/dist/tokens/components/chart.css +4 -1
  234. package/dist/tokens/components/chat-composer.css +4 -1
  235. package/dist/tokens/components/control.css +69 -30
  236. package/dist/tokens/components/conversations.css +4 -1
  237. package/dist/tokens/components/data-display.css +42 -15
  238. package/dist/tokens/components/data-entry.css +8 -2
  239. package/dist/tokens/components/descriptions.css +1 -1
  240. package/dist/tokens/components/feedback.css +8 -5
  241. package/dist/tokens/components/float-button.css +8 -2
  242. package/dist/tokens/components/legal-document.css +12 -3
  243. package/dist/tokens/components/logo.css +15 -6
  244. package/dist/tokens/components/mega-menu.css +14 -5
  245. package/dist/tokens/components/navigation.css +37 -13
  246. package/dist/tokens/components/segmented.css +9 -2
  247. package/dist/tokens/components/separator.css +4 -1
  248. package/dist/tokens/components/shell.css +96 -31
  249. package/dist/tokens/components/table.css +13 -6
  250. package/dist/tokens/components/thought-chain.css +4 -1
  251. package/dist/tokens/components/toggle.css +4 -1
  252. package/dist/tokens/components/tree.css +1 -1
  253. package/dist/tokens/components/upload.css +21 -9
  254. package/dist/tokens/foundation.css +24 -30
  255. package/dist/tokens/semantic/layout.css +19 -5
  256. package/docs/COMPOSITION-VS-COMPONENT.md +41 -0
  257. package/docs/DESIGN-AUTHORITY.md +14 -0
  258. package/docs/DEVELOPMENT.md +81 -6
  259. package/docs/TOKENS.md +16 -1
  260. package/docs/data-entry/tag-input.tsx +37 -0
  261. package/docs/layout/flex.tsx +40 -0
  262. package/docs/roadmap/website-components.md +34 -0
  263. package/docs/showcase/case4-login.tsx +10 -2
  264. package/docs/showcase/case5-shift-calendar.tsx +1 -1
  265. package/docs/showcase/case6-agency-handy.tsx +6 -6
  266. package/docs/showcase/futurelastic-web.tsx +7 -9
  267. package/docs/showcase/marketing-page.tsx +61 -52
  268. package/docs/showcase/table-expandable-rows.tsx +4 -1
  269. package/docs/showcase/table-pagination.tsx +88 -18
  270. package/docs/showcase/theme-customization.tsx +25 -2
  271. package/package.json +8 -5
@@ -0,0 +1,86 @@
1
+ {
2
+ "docPath": "data-entry/chat-composer.tsx",
3
+ "example": "import { ChatComposer, ChatSuggestion } from \"@godxjp/ui/data-entry\";\n\nconst [draft, setDraft] = useState(\"\");\n\n<ChatSuggestion\n items={[\n { value: \"summarize\", label: \"要約する\", description: \"Summarize the thread\" },\n { value: \"translate\", label: \"翻訳する\" },\n ]}\n onValueChange={(value) => setDraft(\"/\" + value + \" \")}\n>\n {({ onTrigger, onKeyDown }) => (\n <ChatComposer\n value={draft}\n onValueChange={(next) => { setDraft(next); onTrigger(next); }}\n onKeyDown={onKeyDown}\n onSubmit={(text) => send(text)}\n />\n )}\n</ChatSuggestion>",
4
+ "group": "data-entry",
5
+ "importPath": "@godxjp/ui/data-entry",
6
+ "name": "ChatSuggestion",
7
+ "props": [
8
+ {
9
+ "description": "The rows to offer: { value, label?, description?, icon?, disabled?, children? }. One level of children is honoured — picking a parent drills into it instead of emitting.",
10
+ "name": "items",
11
+ "required": true,
12
+ "type": "ChatSuggestionItemProp[]"
13
+ },
14
+ {
15
+ "description": "Fires with the picked row's value. The CALLER owns what that does to the draft text — the component never rewrites the textarea behind your back.",
16
+ "name": "onValueChange",
17
+ "type": "(value: string) => void"
18
+ },
19
+ {
20
+ "defaultValue": "\"/\"",
21
+ "description": "The character that opens the list when typed at a word boundary (use \"@\" for a mention list).",
22
+ "name": "triggerCharacter",
23
+ "type": "string"
24
+ },
25
+ {
26
+ "description": "Controlled open state of the list.",
27
+ "name": "open",
28
+ "type": "boolean"
29
+ },
30
+ {
31
+ "description": "Uncontrolled initial open state.",
32
+ "name": "defaultOpen",
33
+ "type": "boolean"
34
+ },
35
+ {
36
+ "description": "Open-state change handler.",
37
+ "name": "onOpenChange",
38
+ "type": "(open: boolean) => void"
39
+ },
40
+ {
41
+ "description": "Render prop wrapping the composer. Call onTrigger from the composer's onValueChange and forward onKeyDown to its onKeyDown.",
42
+ "name": "children",
43
+ "required": true,
44
+ "type": "(props: { onTrigger: (value?: string | false) => void; onKeyDown: React.KeyboardEventHandler<HTMLTextAreaElement> }) => React.ReactNode"
45
+ },
46
+ {
47
+ "description": "Shown when the query matches nothing (localized default otherwise).",
48
+ "name": "emptyMessage",
49
+ "type": "string"
50
+ },
51
+ {
52
+ "description": "Accessible name of the listbox (localized default otherwise).",
53
+ "name": "listLabel",
54
+ "type": "string"
55
+ },
56
+ {
57
+ "description": "DOM id of the anchor wrapping the composer.",
58
+ "name": "id",
59
+ "type": "string"
60
+ }
61
+ ],
62
+ "related": [
63
+ "ChatComposer — the control it wraps; use it alone when there is nothing to suggest.",
64
+ "Command / CommandPalette — a full-screen command surface opened by a shortcut, not by a character in a draft.",
65
+ "Select (showSearch) — the searchable single-select; a suggestion list edits free text, it does not hold a value."
66
+ ],
67
+ "rules": [
68
+ 2,
69
+ 3,
70
+ 6
71
+ ],
72
+ "storyPath": "data-entry/ChatSuggestion.stories.tsx",
73
+ "tagline": "Trigger-character autocomplete over a ChatComposer (Ant Design X Suggestion): type / at a word boundary and a Command list opens against the composer, driven from the textarea without ever taking focus off it.",
74
+ "usage": [
75
+ "DO wire BOTH halves of the render prop: `onTrigger` from the composer's onValueChange and `onKeyDown` from its onKeyDown. With only one wired the list either never opens or cannot be driven.",
76
+ "DO decide yourself what a pick does to the draft — onValueChange hands you the value; the typed /query is still in the box, so replace it or append to it as your screen needs.",
77
+ "DON'T hand-roll a listbox next to a textarea. This composes the real Command (cmdk) inside a Popover, which already ships the listbox/option roles, active-row bookkeeping and scroll-into-view.",
78
+ "DO rely on Escape: it closes the list, returns focus to the textarea and leaves the typed text intact. It also stops propagating, so a composer inside a Dialog does not close the Dialog too.",
79
+ "DON'T expect it to filter server-side — filtering is a plain substring match over label/value/description. For a remote list, filter `items` yourself as the query changes."
80
+ ],
81
+ "useCases": [
82
+ "Slash commands over an assistant composer (/summarize, /translate, /explain).",
83
+ "Mention picker in a comment composer (triggerCharacter=\"@\").",
84
+ "Prompt-template inserter grouped one level deep (a category row that drills into its templates)."
85
+ ]
86
+ }
@@ -0,0 +1,68 @@
1
+ {
2
+ "example": "import { Checkbox } from \"@godxjp/ui/data-entry\";\n\n// children is the inline label (antd): box first, label on the same line, the text toggles the box.\n// Never a hand-rolled <div className=\"flex items-center gap-2\"> around a bare <Label>.\n<Checkbox checked={agreed} onCheckedChange={(v) => setAgreed(v === true)}>\n 利用規約に同意する\n</Checkbox>",
3
+ "group": "data-entry",
4
+ "importPath": "@godxjp/ui/data-entry",
5
+ "name": "Checkbox",
6
+ "props": [
7
+ {
8
+ "description": "antd `indeterminate` — paint the PARTIAL mark (a dash) and announce `mixed`, without changing `checked`. This component also accepts the same state as `checked=\"indeterminate\"`; the flag is antd's spelling of it, and the box falls back to the underlying `checked` the moment the flag goes false.",
9
+ "name": "indeterminate",
10
+ "type": "boolean"
11
+ },
12
+ {
13
+ "description": "Controlled checked state.",
14
+ "name": "checked",
15
+ "type": "boolean | 'indeterminate'"
16
+ },
17
+ {
18
+ "description": "Uncontrolled initial state. It takes the tri-state too, and the box keeps the dash until the first click rather than falling back to unchecked.",
19
+ "name": "defaultChecked",
20
+ "type": "boolean | 'indeterminate'"
21
+ },
22
+ {
23
+ "description": "Fires when checked state changes.",
24
+ "name": "onCheckedChange",
25
+ "type": "(checked) => void"
26
+ },
27
+ {
28
+ "description": "Links to a <Label htmlFor>.",
29
+ "name": "id",
30
+ "type": "string"
31
+ },
32
+ {
33
+ "description": "antd `<Checkbox>label</Checkbox>` — the INLINE label: box first, label at inline-end on the same line, the same markup as a `Checkbox.Group` option. A real `<label for>`: clicking the text toggles the box and the text is its accessible name. `className` then styles the labelled row.",
34
+ "name": "children",
35
+ "type": "React.ReactNode"
36
+ }
37
+ ],
38
+ "related": [
39
+ "CheckboxGroup — use instead of bare Checkbox when you have a list of 2+ options from an array; it handles id generation, Field wrapping, value array management, and the `name` prop for form submission. Checkbox is for a single boolean; CheckboxGroup is for multi-select.",
40
+ "Switch / Field — use Switch when the action takes immediate effect (enable/disable a feature in settings) rather than selecting an option to be submitted later. Checkbox implies 'will be submitted as part of a form'; Switch implies 'applies now'. Field adds a hidden input for HTML form compatibility.",
41
+ "RadioGroup — use when only one option in a group may be selected at a time (mutually exclusive). CheckboxGroup = multiple selections allowed; RadioGroup = single selection only.",
42
+ "Field — the internal layout primitive (control slot + Label + description) that Checkbox.Group renders per item. Use it directly only when you need a one-off labelled checkbox or radio item outside of a group, and you want the consistent indent/description layout without the group's value-management overhead."
43
+ ],
44
+ "rules": [],
45
+ "storyPath": "data-entry/Checkbox.stories.tsx",
46
+ "subParts": [
47
+ "CheckboxVisual"
48
+ ],
49
+ "tagline": "Checkbox on react-aria-components; standalone or via CheckboxGroup with an options array. `role=\"checkbox\"` is the real `<input>`; the painted box is the `<label>` around it and carries `data-state`.",
50
+ "usage": [
51
+ "DO give a single boolean its label as children (antd `<Checkbox>label</Checkbox>`, gh#709): `<Checkbox checked={agreed} onCheckedChange={(v) => setAgreed(v === true)}>利用規約に同意する</Checkbox>` — box first, label on the same line, the text toggles the box and is its accessible name. In a form: `<FormFieldControl name=\"agree\" valuePropName=\"checked\">{(field) => <Checkbox {...field}>利用規約に同意する</Checkbox>}</FormFieldControl>`.",
52
+ "DON'T render a boolean field's label ABOVE its checkbox — `<FormFieldControl label=\"…\">{(field) => <Checkbox checked={field.value} … />}</FormFieldControl>` puts the label on one row and the box far below it. Put the label in the Checkbox's children and use `valuePropName=\"checked\"` on the field.",
53
+ "DO pair every standalone Checkbox WITHOUT children with a `<Label htmlFor={id}>` (or an `aria-label`) — the id prop on Checkbox must match the htmlFor on Label so screen readers announce the label on focus. Without this pairing the control is inaccessible.",
54
+ "DO use the controlled pattern (`checked` + `onCheckedChange`) for any form-bound checkbox. `onCheckedChange` receives `boolean | 'indeterminate'` — always coerce with `!!v` or an explicit guard before storing in state.",
55
+ "DO use `Checkbox.Group` (alias for CheckboxGroup) with the `options` prop when you have ≥2 choices from an array — it renders each item inside a `Field` (label + optional description), generates stable ids automatically, and manages the `string[]` value array. NEVER hand-roll a loop of bare `<Checkbox>` elements for a multi-select list.",
56
+ "DO pass `name` on `Checkbox.Group` (not on individual checkboxes) when the group must submit as form fields — the group propagates the name to each internal checkbox so the browser serialises all checked values under that key.",
57
+ "DON'T use `checked='indeterminate'` on `Checkbox.Group` children — indeterminate is only meaningful on a parent 'select-all' control you wire manually; the group itself does not auto-compute it.",
58
+ "DON'T wrap a standalone Checkbox in `Field` manually — `Field` is the internal composition primitive that `Checkbox.Group` uses. For a single boolean with a label, pass the label as children (`<Checkbox …>label</Checkbox>`, the catalog example) — it renders the same row. Use `<Field id='x' label='…' description='…'><Checkbox id='x' … /></Field>` only when the row needs a description line — Field owns the label-to-control id wiring, the description slot and the row rhythm, and a hand-rolled flex row owns none of them; for a full labelled-checkbox with description, use `Field` directly only if you need a one-off item outside a group."
59
+ ],
60
+ "useCases": [
61
+ "A 'Select all' / bulk-action row above a DataTable — standalone Checkbox with `checked='indeterminate'` when some (not all) rows are selected, toggling between all-selected and none-selected.",
62
+ "A multi-step filter panel (e.g. filter invoices by payment status: Paid, Unpaid, Overdue) — `Checkbox.Group` with `options` prop and `orientation='vertical'`, controlled value wired to Toolbar state.",
63
+ "Confirmation or consent acknowledgement before a destructive action in a Dialog — standalone Checkbox with controlled state used to enable/disable the confirm Button.",
64
+ "Settings panel where each feature flag is a boolean toggle with a description line — `Checkbox.Group` with options carrying a `description` field so each row renders label + subtext via Field.",
65
+ "Bulk-edit form row in an accounting ledger (e.g. 'Apply to all selected entries') — standalone Checkbox with name + value inside a `<form>` for native HTML form submission.",
66
+ "Onboarding checklist (e.g. 'I have read the terms', 'I consent to data processing') with multiple distinct items whose values are independent — two separate standalone Checkboxes, each with their own id/state, not a Checkbox.Group (since each item maps to a different boolean field)."
67
+ ]
68
+ }
@@ -0,0 +1,96 @@
1
+ {
2
+ "example": "import { CheckboxGroup } from \"@godxjp/ui/data-entry\";\nimport { useState } from \"react\";\n\nconst PERMISSIONS = [\n { label: \"View invoices\", value: \"invoices:read\" },\n { label: \"Create invoices\", value: \"invoices:write\", description: \"Includes editing and deleting\" },\n { label: \"Manage users\", value: \"users:manage\", disabled: true },\n];\n\n// Uncontrolled — use defaultValue\nexport function PermissionsForm() {\n return (\n <form method=\"post\">\n <CheckboxGroup\n name=\"permissions\"\n options={PERMISSIONS}\n defaultValue={[\"invoices:read\"]}\n orientation=\"vertical\"\n />\n </form>\n );\n}\n\n// Controlled — use value + onChange\nexport function ControlledExample() {\n const [selected, setSelected] = useState<string[]>([\"invoices:read\"]);\n return (\n <CheckboxGroup\n name=\"permissions\"\n options={PERMISSIONS}\n value={selected}\n onValueChange={setSelected}\n />\n );\n}",
3
+ "group": "data-entry",
4
+ "importPath": "@godxjp/ui/data-entry",
5
+ "name": "CheckboxGroup",
6
+ "props": [
7
+ {
8
+ "description": "Id của nhóm; `FormField` tự truyền xuống để nối nhãn ↔ control.",
9
+ "name": "id",
10
+ "type": "string"
11
+ },
12
+ {
13
+ "description": "Data-driven mode: array of { label, value, disabled?, description? }. When provided and non-empty, renders all checkboxes automatically. When omitted, renders `children` instead.",
14
+ "name": "options",
15
+ "type": "ChoiceOptionProp[]"
16
+ },
17
+ {
18
+ "description": "Controlled selected values. When provided, the component is controlled and won't manage state internally — you must handle onChange to update it.",
19
+ "name": "value",
20
+ "type": "string[]"
21
+ },
22
+ {
23
+ "defaultValue": "[]",
24
+ "description": "Uncontrolled initial selection. Use this instead of `value` when you don't need to control state externally.",
25
+ "name": "defaultValue",
26
+ "type": "string[]"
27
+ },
28
+ {
29
+ "description": "Called with the full updated selection array whenever any checkbox is toggled. Works in both controlled and uncontrolled modes.",
30
+ "name": "onChange",
31
+ "type": "(value: string[]) => void"
32
+ },
33
+ {
34
+ "defaultValue": "\"vertical\"",
35
+ "description": "Layout direction of the checkbox items. Vertical stacks items; horizontal places them in a row.",
36
+ "name": "orientation",
37
+ "type": "\"vertical\" | \"horizontal\""
38
+ },
39
+ {
40
+ "description": "Disables the entire group. Individual options can also set their own disabled flag via ChoiceOptionProp.disabled.",
41
+ "name": "disabled",
42
+ "type": "boolean"
43
+ },
44
+ {
45
+ "description": "HTML form name applied to each underlying checkbox input. Required for native form submission — all checkboxes share the same name so the form collects multiple values.",
46
+ "name": "name",
47
+ "type": "string"
48
+ },
49
+ {
50
+ "description": "Extra CSS class on the group container div.",
51
+ "name": "className",
52
+ "type": "string"
53
+ },
54
+ {
55
+ "description": "Manual children mode: used when `options` is omitted or empty. Render Checkbox items directly as children. You are responsible for composing each Checkbox with a Field for correct label/description layout.",
56
+ "name": "children",
57
+ "type": "React.ReactNode"
58
+ },
59
+ {
60
+ "description": "Fires with the checked values array.",
61
+ "name": "onValueChange",
62
+ "type": "(value: string[]) => void"
63
+ }
64
+ ],
65
+ "related": [
66
+ "RadioGroup — use when only ONE selection is allowed at a time (mutually exclusive). CheckboxGroup = multiple, RadioGroup = single.",
67
+ "Checkbox (standalone) — use a bare `Checkbox` for a single boolean toggle (e.g. 'I agree to terms'). Use CheckboxGroup when you have 2+ related choices.",
68
+ "Checkbox.Group — alias; the same component is also accessible as `Checkbox.Group` (the Checkbox export attaches CheckboxGroup as `.Group`). Both are equivalent — prefer the named `CheckboxGroup` import for clarity in larger files.",
69
+ "Switch / Field — for a single binary on/off toggle with immediate effect (not a form submission value). Do not use CheckboxGroup to fake toggle rows.",
70
+ "Select (multi) — for a long list (10+ items) where space is limited; CheckboxGroup is better for ≤10 visible options that benefit from scanning all at once."
71
+ ],
72
+ "rules": [
73
+ 3,
74
+ 6,
75
+ 23,
76
+ 31
77
+ ],
78
+ "storyPath": "data-entry/CheckboxGroup.stories.tsx",
79
+ "tagline": "Multi-select checkbox list from an options array or manual children — use `options` prop for the data-driven path, never hand-roll individual Checkbox items in a group.",
80
+ "usage": [
81
+ "DO use the `options` prop for any data-driven list — it auto-generates IDs, handles checked state, and wires up Field (label + description) for each item. NEVER hand-roll individual `<Checkbox>` elements inside a loop when you have an options array.",
82
+ "DO pass `name` when inside an HTML form so each checkbox submits its value under the same field name, giving the server a multi-value array. Without `name`, native form submission silently drops all values.",
83
+ "Controlled vs uncontrolled: pass `value` + `onChange` together for controlled usage (e.g. react-hook-form). Pass `defaultValue` alone for uncontrolled usage. Do NOT mix both — if `value` is provided, `defaultValue` is ignored and onChange must update value externally or the UI freezes.",
84
+ "Each option's `description` renders as a secondary line below its label via Field — use it for help text or sub-copy; keep `label` short.",
85
+ "Group-level `disabled` disables all checkboxes. Individual `options[n].disabled` disables only that item. Both can coexist.",
86
+ "DO NOT wrap this inside another ARIA group or fieldset without removing the built-in `role=\"group\"` — it already provides the correct grouping semantics. Pair the group with a `<legend>` or visible heading for a11y."
87
+ ],
88
+ "useCases": [
89
+ "Permission / role selectors in admin forms — e.g. 'Select applicable roles: Admin, Editor, Viewer' where users can pick multiple.",
90
+ "Filter panels — e.g. 'Filter by status: Active, Pending, Archived' with horizontal orientation for compact toolbar layout.",
91
+ "Feature flag or settings toggles where multiple independent boolean flags share a label/description pair, loaded from a config array.",
92
+ "Multi-category tagging forms — e.g. 'Tag this invoice: Recurring, Billable, Internal' driven by an options array fetched from an API.",
93
+ "Onboarding checklists or multi-step preference screens where selections persist across steps via controlled `value`.",
94
+ "Accounting module: select which cost centres or account codes apply to a transaction, driven by a normalized options list."
95
+ ]
96
+ }
@@ -0,0 +1,64 @@
1
+ {
2
+ "example": "import { CodeBlock } from \"@godxjp/ui/data-display\";\n\n<CodeBlock maxHeight=\"sm\" language=\"json\" aria-label=\"Response body\">{body}</CodeBlock>\n<CodeBlock size=\"xs\" maxHeight=\"md\" aria-label=\"Console\">{consoleText}</CodeBlock>",
3
+ "group": "data-display",
4
+ "importPath": "@godxjp/ui/data-display",
5
+ "name": "CodeBlock",
6
+ "props": [
7
+ {
8
+ "description": "The text. Pass a string, or a highlighter's spans tagged `data-code-token` (the twelve Shiki createCssVariablesTheme token names) — the package colours them from the `--code-block-token-*` knobs, so the consumer never writes a colour.",
9
+ "name": "children",
10
+ "type": "ReactNode"
11
+ },
12
+ {
13
+ "defaultValue": "true",
14
+ "description": "Soft-wrap long lines (`white-space: pre-wrap; overflow-wrap: anywhere`). `false` keeps lines intact and scrolls horizontally.",
15
+ "name": "wrap",
16
+ "type": "boolean"
17
+ },
18
+ {
19
+ "description": "Token presets, or one explicit CSS length such as {value:\"16rem\"}. Still keyboard scrollable.",
20
+ "name": "maxHeight",
21
+ "type": "\"sm\" | \"md\" | \"lg\" | \"none\" | { value: string }"
22
+ },
23
+ {
24
+ "defaultValue": "\"sm\"",
25
+ "description": "Type size: `sm` for bodies and snippets, `xs` for dense logs.",
26
+ "name": "size",
27
+ "type": "\"xs\" | \"sm\""
28
+ },
29
+ {
30
+ "description": "Lands on `data-language`. No highlighter is bundled — bring your own and tag its output with `data-code-token` (gh#784).",
31
+ "name": "language",
32
+ "type": "string"
33
+ },
34
+ {
35
+ "description": "Extra classes on the `pre`.",
36
+ "name": "className",
37
+ "type": "string"
38
+ }
39
+ ],
40
+ "related": [
41
+ "Prose - renders whole documents (Markdown, CMS bodies) and delegates its `pre` treatment to the same tokens; use Prose when the block sits inside rendered content, CodeBlock for a standalone block.",
42
+ "Text - `as=\"code\"` is inline monospace for an identifier in a sentence, not a block.",
43
+ "Descriptions - `Descriptions.Item mono` is a mono VALUE in a label/value row.",
44
+ "CredentialReveal - a masked secret with copy; not for arbitrary text."
45
+ ],
46
+ "rules": [],
47
+ "storyPath": "data-display/CodeBlock.stories.tsx",
48
+ "tagline": "A block of preformatted text (request and response bodies, console output, snippets): mono, muted surface, soft-wrapped long lines by default, and an optional height cap that scrolls inside the block instead of pushing the page.",
49
+ "usage": [
50
+ "DO import from `@godxjp/ui/data-display`: `import { CodeBlock } from \"@godxjp/ui/data-display\";`",
51
+ "DO give a block that can scroll (`maxHeight` or `wrap={false}`) an `aria-label`: it becomes a keyboard tab stop so the content is reachable without a mouse.",
52
+ "DO cap the height of anything that can be large (a 64 KB response body, a console dump) with `maxHeight`; the page keeps its rhythm and the block scrolls.",
53
+ "DON'T hand-roll `<pre className=\"max-h-64 overflow-auto rounded bg-muted p-2 whitespace-pre-wrap\">`: every one of those values is a copy of a token this component reads.",
54
+ "DON'T reach for `Text as=\"code\"` for a block: that is inline monospace with no wrapping axis. Use `Text as=\"code\"` for an identifier inside a sentence, CodeBlock for a block.",
55
+ "DON'T use CodeBlock for a single value in a Descriptions row: `Descriptions.Item mono` owns that (it breaks the value, not the row).",
56
+ "SYNTAX COLOUR (gh#784): CodeBlock does not highlight, but it DOES own the palette. Tag each span from your highlighter with `data-code-token` — the twelve names are Shiki createCssVariablesTheme's verbatim (comment, keyword, string, string-expression, function, constant, parameter, punctuation, link, inserted, deleted, changed, plus the block foreground) — and the package colours them. DON'T put `style={{ color }}` or a palette `className` on the spans: both are visual overrides, and the colour is not the consumer's to choose. Retheme with the `--code-block-token-*-color` knobs, which are role-mirrors, so light and dark follow the theme with no second palette."
57
+ ],
58
+ "useCases": [
59
+ "Request and response bodies of an HTTP trace (HAR) in a bug-report inbox: JSON up to 64 KB, lines up to 240 characters, wrapped and capped at `maxHeight=\"sm\"`.",
60
+ "Console output attached to a bug report: `size=\"xs\"` for density, `maxHeight=\"md\"`.",
61
+ "An API example in developer documentation: `language=\"bash\"` or `\"json\"`, no height cap.",
62
+ "A stack trace in an error detail sheet: `wrap={false}` so frames stay on one line, scrolled horizontally."
63
+ ]
64
+ }
@@ -0,0 +1,74 @@
1
+ {
2
+ "example": "{`import { useState } from \"react\";\nimport { ChevronDown } from \"lucide-react\";\n// Money goes through Intl — the symbol, the grouping and the minor units are all locale data.\nconst money = new Intl.NumberFormat(\"ja-JP\", { style: \"currency\", currency: \"JPY\" });\nimport {\n Collapsible,\n CollapsibleTrigger,\n CollapsibleContent,\n} from \"@godxjp/ui/data-display\";\nimport { Card, CardContent } from \"@godxjp/ui/data-display\";\nimport { Button, Text } from \"@godxjp/ui/general\";\nimport { Flex } from \"@godxjp/ui/layout\";\n\n// --- Uncontrolled (simplest) ---\n// The icon needs no margin of its own: Button spaces its own icon slot. The gap between the\n// trigger and the revealed body belongs to the Flex around them, and the body is a Card — a\n// rounded-md border div is a hand-rolled surface with the radius frozen at the call site.\nexport function InvoiceLineDetail() {\n return (\n <Collapsible>\n <Flex direction=\"col\" align=\"start\" gap=\"sm\">\n <CollapsibleTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\">\n <ChevronDown aria-hidden=\"true\" />\n Show tax breakdown\n </Button>\n </CollapsibleTrigger>\n <CollapsibleContent>\n <Card>\n <CardContent>\n <Flex direction=\"col\" gap=\"xs\">\n <Text size=\"sm\">Consumption tax (10%): {money.format(1234)}</Text>\n <Text size=\"sm\">Withholding tax: {money.format(0)}</Text>\n </Flex>\n </CardContent>\n </Card>\n </CollapsibleContent>\n </Flex>\n </Collapsible>\n );\n}\n\n// --- Controlled (open driven externally) ---\nexport function FilterSection() {\n const [open, setOpen] = useState(false);\n return (\n <Collapsible open={open} onOpenChange={setOpen}>\n <Flex direction=\"col\" align=\"start\" gap=\"sm\">\n <CollapsibleTrigger asChild>\n <Button variant=\"outline\" size=\"sm\">\n Advanced filters\n <ChevronDown aria-hidden=\"true\" />\n </Button>\n </CollapsibleTrigger>\n <CollapsibleContent>\n {/* place filter controls here */}\n <Text size=\"sm\" tone=\"muted\">Date range, entity, status…</Text>\n </CollapsibleContent>\n </Flex>\n </Collapsible>\n );\n}`}",
3
+ "group": "data-display",
4
+ "importPath": "@godxjp/ui/data-display",
5
+ "name": "Collapsible",
6
+ "props": [
7
+ {
8
+ "description": "Controlled open state. When provided, pair with onOpenChange to keep in sync. Omit for uncontrolled behaviour.",
9
+ "name": "open",
10
+ "type": "boolean"
11
+ },
12
+ {
13
+ "defaultValue": "false",
14
+ "description": "Initial open state when used uncontrolled. Useful for auto-expanding when a child is active (e.g. sidebar nav group).",
15
+ "name": "defaultOpen",
16
+ "type": "boolean"
17
+ },
18
+ {
19
+ "description": "Callback fired when the open state changes. Required in controlled mode.",
20
+ "name": "onOpenChange",
21
+ "type": "(open: boolean) => void"
22
+ },
23
+ {
24
+ "defaultValue": "false",
25
+ "description": "Prevents the trigger from toggling the content. The trigger is still rendered but inert.",
26
+ "name": "disabled",
27
+ "type": "boolean"
28
+ },
29
+ {
30
+ "description": "Applied to the root Collapsible element. Use for layout (e.g. sb-nav-group) — the root renders a div.",
31
+ "name": "className",
32
+ "type": "string"
33
+ },
34
+ {
35
+ "defaultValue": "false",
36
+ "description": "On CollapsibleTrigger only — merges Radix trigger behaviour onto the single child element (e.g. a godx-ui Button) instead of rendering a default button. The child must accept onClick and aria-* props.",
37
+ "name": "asChild (CollapsibleTrigger)",
38
+ "type": "boolean"
39
+ }
40
+ ],
41
+ "related": [
42
+ "Accordion (from @godxjp/ui/data-entry or Radix) — use Accordion when only ONE section can be open at a time across a group; use Collapsible when each section is independent and can be open simultaneously.",
43
+ "Popover — use Popover when the revealed content should float above the layout in a portal overlay; use Collapsible when the content should push surrounding content down inline.",
44
+ "Dialog/Sheet — use Dialog or Sheet for modal or slide-over panels that demand full user attention; Collapsible stays in-flow and non-modal.",
45
+ "Tree (@godxjp/ui/data-display) — use Tree for hierarchical data that expands, collapses and is navigated by keyboard; use Collapsible for ad-hoc single-level toggle regions."
46
+ ],
47
+ "rules": [
48
+ 3,
49
+ 6,
50
+ 23
51
+ ],
52
+ "storyPath": "data-display/Collapsible.stories.tsx",
53
+ "subParts": [
54
+ "CollapsibleContent",
55
+ "CollapsibleTrigger"
56
+ ],
57
+ "tagline": "Three-part compound (Collapsible + CollapsibleTrigger + CollapsibleContent) that toggles a region open/closed — never use just one part alone.",
58
+ "usage": [
59
+ "DO compose all three parts together: <Collapsible> wraps both <CollapsibleTrigger> and <CollapsibleContent>. Never render CollapsibleContent without a parent Collapsible — the open state lives on the root.",
60
+ "DO use asChild on CollapsibleTrigger when you want a godx-ui Button (or any styled element) to act as the trigger: <CollapsibleTrigger asChild><Button>Toggle</Button></CollapsibleTrigger>. Without asChild the trigger renders its own plain button.",
61
+ "DO pass defaultOpen={true} (uncontrolled) when the section should auto-expand on mount — for example, a sidebar nav group whose active child matches the current route.",
62
+ "DO use controlled mode (open + onOpenChange) when external UI — a separate button, route change, or search filter — needs to drive the open state independently of the trigger.",
63
+ "DON'T add hidden native <details>/<summary> as a fallback — the Radix primitive is already accessible (aria-expanded, aria-controls) out of the box.",
64
+ "DON'T put interactive controls (Buttons, links, inputs) inside CollapsibleTrigger itself unless using asChild — nested focusable elements break keyboard navigation. Put them inside CollapsibleContent instead."
65
+ ],
66
+ "useCases": [
67
+ "Sidebar navigation group: a top-level nav item with children collapses/expands its sub-items in the rail (used directly in the godx-ui Sidebar component with defaultOpen={active}).",
68
+ "Invoice line-item detail: an invoice row that expands inline to show tax breakdown, allocation notes, or audit trail without navigating away.",
69
+ "Filter panel section: a labelled group of filter controls (date range, entity, status) that can be collapsed to save vertical space in a dense accounting dashboard.",
70
+ "Read-more / long description: a truncated journal entry or payment memo that expands to full text on demand.",
71
+ "Settings sub-section: an optional advanced settings block that is hidden by default and revealed only when the user opts in.",
72
+ "Audit log detail: a compact log entry row that expands to show full diff, user, timestamp, and before/after values."
73
+ ]
74
+ }
@@ -0,0 +1,87 @@
1
+ {
2
+ "example": "import { useState } from \"react\";\nimport { ColorPicker, FormField } from \"@godxjp/ui/data-entry\";\n\nexport function BrandColorField() {\n const [color, setColor] = useState(\"#2563eb\");\n\n return (\n <FormField id=\"brand-color\" label=\"Brand color\" className=\"max-w-xs\">\n <ColorPicker\n id=\"brand-color\"\n value={color}\n onValueChange={setColor}\n />\n </FormField>\n );\n}\n\n// Compact swatch-only variant (no hex input)\nexport function SwatchOnly() {\n const [color, setColor] = useState(\"#16a34a\");\n return <ColorPicker value={color} onValueChange={setColor} showHexInput={false} />;\n}\n\n// Disabled state\nexport function DisabledColor() {\n return <ColorPicker value=\"#6b7280\" disabled />;\n}",
3
+ "group": "data-entry",
4
+ "importPath": "@godxjp/ui/data-entry",
5
+ "name": "ColorPicker",
6
+ "props": [
7
+ {
8
+ "description": "Initial uncontrolled color.",
9
+ "name": "defaultValue",
10
+ "type": "string"
11
+ },
12
+ {
13
+ "description": "Native form field name.",
14
+ "name": "name",
15
+ "type": "string"
16
+ },
17
+ {
18
+ "defaultValue": "\"#2563eb\"",
19
+ "description": "The current hex color string (3- or 6-digit, with leading #). Component auto-prepends # if missing. Invalid hex values are discarded and the previous valid value is kept.",
20
+ "name": "value",
21
+ "type": "string"
22
+ },
23
+ {
24
+ "defaultValue": "undefined",
25
+ "description": "Called with the normalized, validated hex string whenever the user commits a new color — via the native swatch picker or by pressing Enter / blurring the hex input. Not called for invalid hex drafts.",
26
+ "name": "onChange",
27
+ "type": "(hex: string) => void"
28
+ },
29
+ {
30
+ "defaultValue": "undefined",
31
+ "description": "Disables both the swatch input and the hex text input, preventing all user interaction.",
32
+ "name": "disabled",
33
+ "type": "boolean"
34
+ },
35
+ {
36
+ "defaultValue": "true",
37
+ "description": "When true (default), renders an editable godx-ui Input alongside the swatch that shows the current hex value and lets the user type a hex string. Set to false for a compact swatch-only control.",
38
+ "name": "showHexInput",
39
+ "type": "boolean"
40
+ },
41
+ {
42
+ "defaultValue": "undefined",
43
+ "description": "Extra CSS class(es) applied to the root wrapper div. Use for layout sizing; avoid overriding design-token colours.",
44
+ "name": "className",
45
+ "type": "string"
46
+ },
47
+ {
48
+ "defaultValue": "undefined",
49
+ "description": "DOM id applied to the hidden native <input type='color'>. Pass the FormField id here so the label's htmlFor targets this control correctly.",
50
+ "name": "id",
51
+ "type": "string"
52
+ },
53
+ {
54
+ "description": "Fires with the committed hex string.",
55
+ "name": "onValueChange",
56
+ "type": "(value: string) => void"
57
+ }
58
+ ],
59
+ "related": [
60
+ "Input — use for plain text/number entry; use ColorPicker when the value is specifically a color hex code and you want a visual swatch.",
61
+ "Select / SearchSelect — use for choosing from a fixed palette of named colors (e.g. 'Red', 'Blue'); use ColorPicker for freeform hex color entry."
62
+ ],
63
+ "rules": [
64
+ 2,
65
+ 3,
66
+ 6,
67
+ 13
68
+ ],
69
+ "storyPath": "data-entry/ColorPicker.stories.tsx",
70
+ "tagline": "Native color-swatch picker with an optional editable hex input — always pass a valid 3- or 6-digit hex `value`; invalid hex is silently ignored and the previous value is restored.",
71
+ "usage": [
72
+ "DO wrap in FormField when a label or validation message is needed — pass the same id to both FormField and ColorPicker so htmlFor wires up correctly: `<FormField id='brand' label='Brand color'><ColorPicker id='brand' value={v} onValueChange={setV} /></FormField>`.",
73
+ "DO use controlled mode (value + onChange) — there is no defaultValue/uncontrolled path; always supply value.",
74
+ "DON'T pass an invalid or empty string to value — the component will flash the invalid color on the preview swatch. Always initialize state to a valid 3- or 6-digit hex (e.g. '#2563eb').",
75
+ "The hex Input is a live draft field — onChange is NOT called until the user presses Enter or blurs; only then is the value validated and the parent notified. Do not rely on onChange firing on every keystroke.",
76
+ "Set showHexInput={false} only for compact/inline contexts (icon pickers, table cells) where space is tight and keyboard hex entry is not needed.",
77
+ "NEVER hand-roll a color picker with raw <input type='color'> — always use this component; it normalizes hex, debounces draft state, and respects the design-token control styles."
78
+ ],
79
+ "useCases": [
80
+ "Brand / campaign color selection in settings or campaign creation forms where users need to pick or type an exact hex value.",
81
+ "Invoice or document theme customization — letting users pick accent colors that are stored and applied to PDF output.",
82
+ "Accounting dashboard category tagging — assigning a color code to GL account categories or chart-of-accounts nodes for visual grouping.",
83
+ "Product or inventory label colors in admin panels where a compact swatch (showHexInput={false}) fits inside a table cell or sidebar.",
84
+ "Design-token or CSS variable editor pages where the user needs precise hex entry alongside a visual swatch preview.",
85
+ "User-profile or team avatar color personalization forms."
86
+ ]
87
+ }