@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,76 @@
1
+ {
2
+ "docPath": "data-display/thought-chain.tsx",
3
+ "example": "import { ThoughtChain } from \"@godxjp/ui/data-display\";\n\n<ThoughtChain\n label=\"思考の手順\"\n defaultExpandedKeys={[\"search\"]}\n items={[\n { key: \"read\", title: \"資料を読む\", description: \"3件\", status: \"success\" },\n {\n key: \"search\",\n title: \"社内規程を検索\",\n status: \"loading\",\n collapsible: true,\n blink: true,\n content: <pre>{hits}</pre>,\n },\n { key: \"write\", title: \"下書きを書く\", status: \"abort\" },\n ]}\n/>",
4
+ "group": "data-display",
5
+ "importPath": "@godxjp/ui/data-display",
6
+ "name": "ThoughtChain",
7
+ "props": [
8
+ {
9
+ "description": "The steps: { key?, icon?, title?, description?, content?, footer?, status?, collapsible?, blink?, destroyOnHidden? }. `icon: false` drops the glyph column; omitted, the step shows its 1-based ordinal (Ant Design X's own default).",
10
+ "name": "items",
11
+ "type": "ThoughtChainItemsProp[]"
12
+ },
13
+ {
14
+ "description": "Uncontrolled initially-open steps.",
15
+ "name": "defaultExpandedKeys",
16
+ "type": "string[]"
17
+ },
18
+ {
19
+ "description": "Controlled open steps.",
20
+ "name": "expandedKeys",
21
+ "type": "string[]"
22
+ },
23
+ {
24
+ "description": "Fires with the NEXT open set.",
25
+ "name": "onExpand",
26
+ "type": "(keys: string[]) => void"
27
+ },
28
+ {
29
+ "defaultValue": "true",
30
+ "description": "The connector drawn between steps. false draws none. (Ant Design X's own type spells the third with a stray U+200C, so `line=\"dotted\"` does not type-check there; the clean spelling is used here.)",
31
+ "name": "line",
32
+ "type": "boolean | \"solid\" | \"dashed\" | \"dotted\""
33
+ },
34
+ {
35
+ "description": "Accessible name of the chain (a plain string). Localized default otherwise.",
36
+ "name": "label",
37
+ "type": "string"
38
+ },
39
+ {
40
+ "description": "DOM id of the chain root.",
41
+ "name": "id",
42
+ "type": "string"
43
+ }
44
+ ],
45
+ "related": [
46
+ "Timeline — the same vertical rail for events that ALREADY happened. Use it when nothing is in flight.",
47
+ "Steps — a wizard's progress across a form. ThoughtChain is the assistant's own reasoning, not the user's path.",
48
+ "Accordion — a general disclosure list with no rail, no ordinal and no status.",
49
+ "ChatBubble — the answer the chain explains."
50
+ ],
51
+ "rules": [
52
+ 2,
53
+ 6,
54
+ 23,
55
+ 44,
56
+ 45
57
+ ],
58
+ "storyPath": "data-display/ThoughtChain.stories.tsx",
59
+ "subParts": [
60
+ "ThoughtChainItem"
61
+ ],
62
+ "tagline": "The assistant's reasoning, step by step (Ant Design X ThoughtChain): an ORDERED list of steps, each with an ordinal or a glyph, a status, and a body it can collapse — where Ant X's own step is a <div onClick> with no role and no aria-expanded.",
63
+ "usage": [
64
+ "DO give every step a stable `key` — it is what expandedKeys addresses and what onExpand reports.",
65
+ "DO set `collapsible` on a step whose `content` is long (a tool's raw output, a retrieved passage). The title then becomes a real disclosure button with aria-expanded, keyboard-reachable; without `collapsible` the body is simply always shown.",
66
+ "DO use `status` for how a step ENDED — loading / success / error / abort. The word rides along in a visually hidden span, so the state is never carried by the tint alone.",
67
+ "DO use `blink` while a step is still streaming; it pulses the title and body and collapses to nothing under prefers-reduced-motion.",
68
+ "DON'T reach for it for events that already happened — that is Timeline. A thought chain is a run IN PROGRESS, which is why it has loading and abort states and a body that opens.",
69
+ "DON'T expect `styles`/`classNames` from Ant Design X — retune through the --thought-chain-* tokens."
70
+ ],
71
+ "useCases": [
72
+ "An agent's tool calls under its answer: read the documents, search the policy, draft the reply — each with its output collapsed.",
73
+ "A long-running job's progress inside a chat: the current step blinking, the finished ones ticked, an aborted one greyed.",
74
+ "ThoughtChainItem alone: the chip an assistant drops inline to name the tool it just reached for."
75
+ ]
76
+ }
@@ -0,0 +1,70 @@
1
+ {
2
+ "docPath": "data-display/thumbnail.tsx",
3
+ "example": "import { Thumbnail } from \"@godxjp/ui/data-display\";\n\n<Flex gap=\"sm\" wrap align=\"start\">\n <Thumbnail src=\"/shot-portrait.png\" width={360} height={640} alt=\"モバイル版の一覧画面\" size=\"lg\" />\n <Thumbnail src=\"/shot-desktop.png\" width={960} height={540} alt=\"デスクトップ版のダッシュボード\" size=\"lg\" />\n</Flex>",
4
+ "group": "data-display",
5
+ "importPath": "@godxjp/ui/data-display",
6
+ "name": "Thumbnail",
7
+ "props": [
8
+ {
9
+ "description": "Image URL.",
10
+ "name": "src",
11
+ "required": true,
12
+ "type": "string"
13
+ },
14
+ {
15
+ "description": "Required by the type. Pass \"\" for a picture that carries no information the page does not already say — the empty string is a decision, a missing attribute is an omission (WCAG 1.1.1).",
16
+ "name": "alt",
17
+ "required": true,
18
+ "type": "string"
19
+ },
20
+ {
21
+ "defaultValue": "\"md\"",
22
+ "description": "Frame height — sm 64px (an attachment strip), md 96px (a gallery row), lg 160px (a review screen). The width follows the picture's own ratio.",
23
+ "name": "size",
24
+ "type": "\"sm\" | \"md\" | \"lg\""
25
+ },
26
+ {
27
+ "description": "The file's real pixel width. Pass it with `height` and the browser knows the ratio before the bytes land, so the frame takes its final width on the first paint instead of reflowing the row.",
28
+ "name": "width",
29
+ "type": "number"
30
+ },
31
+ {
32
+ "description": "The file's real pixel height. See `width`.",
33
+ "name": "height",
34
+ "type": "number"
35
+ },
36
+ {
37
+ "description": "Native img attribute, passed through. Every other img attribute passes through too.",
38
+ "name": "loading",
39
+ "type": "\"lazy\" | \"eager\""
40
+ },
41
+ {
42
+ "description": "Root class. The three heights, the hairline and the radius live in the --thumbnail-* tokens.",
43
+ "name": "className",
44
+ "type": "string"
45
+ }
46
+ ],
47
+ "related": [
48
+ "AspectRatio — a ratio-constrained slot at full width; use it when YOU choose the ratio, not when the picture does.",
49
+ "Avatar — an identity mark for a person, team or entity, with an initials fallback.",
50
+ "CardCover — the full-bleed media slot at the top of a Card.",
51
+ "Carousel — for a set too large to lay out at once; a wrap row of 2–5 thumbnails is not a carousel."
52
+ ],
53
+ "rules": [],
54
+ "storyPath": "data-display/Thumbnail.stories.tsx",
55
+ "tagline": "A framed picture at a FIXED height with its own INTRINSIC width — the shape a wrapping row of screenshots with different aspect ratios needs.",
56
+ "usage": [
57
+ "DO import from `@godxjp/ui/data-display`: `import { Thumbnail } from \"@godxjp/ui/data-display\";`",
58
+ "DO wrap a row of them in `<Flex gap=\"sm\" wrap align=\"start\">` — equal heights make the strip read as one row while each width stays natural.",
59
+ "DO pass the file's real `width` and `height` so the row does not reflow while the pictures load.",
60
+ "DON'T use AspectRatio for this: it spans `width: 100%` and pins ONE ratio, so a row of mixed-ratio screenshots comes out letterboxed or cropped. AspectRatio is for a slot whose ratio you choose.",
61
+ "DON'T use Avatar (an identity mark with an initials fallback) or Card (it pads the frame away from the picture). CardCover is the full-bleed media slot inside a Card, not a standalone thumbnail.",
62
+ "DON'T hand-roll `<img className=\"h-40 w-auto rounded-md border\" />` — `no-hand-rolled-surface` flags it, correctly: border + radius is a surface."
63
+ ],
64
+ "useCases": [
65
+ "A review screen showing a submission's screenshots, portrait and landscape in the same wrapping row.",
66
+ "An attachment strip beside a message or a ticket, at `size=\"sm\"`.",
67
+ "A gallery row of uploaded images where each picture must stay uncropped.",
68
+ "Any picture that needs a hairline so a light image is distinguishable from the card behind it."
69
+ ]
70
+ }
@@ -0,0 +1,200 @@
1
+ {
2
+ "example": "import { FormField, TimePicker } from \"@godxjp/ui/data-entry\";\nimport { Button } from \"@godxjp/ui/general\";\nimport { useState } from \"react\";\n\n// Controlled usage inside a React form\nexport function ShiftStartField() {\n const [startTime, setStartTime] = useState(\"09:00\");\n\n return (\n <FormField id=\"shift-start\" label=\"Shift start\" controlWidth=\"9rem\">\n <TimePicker\n id=\"shift-start\"\n name=\"shift_start\"\n value={startTime}\n onValueChange={setStartTime}\n minuteStep={15}\n />\n </FormField>\n );\n}\n\n// Uncontrolled usage inside a native form\nexport function CutoffTimeForm() {\n return (\n <form method=\"post\" action=\"/settings/cutoff\">\n <TimePicker\n id=\"cutoff\"\n name=\"cutoff_time\"\n defaultValue=\"17:00\"\n minuteStep={30}\n placeholder=\"hh:mm\"\n />\n <Button type=\"submit\">Save</Button>\n </form>\n );\n}",
3
+ "group": "data-entry",
4
+ "importPath": "@godxjp/ui/data-entry",
5
+ "name": "TimePicker",
6
+ "props": [
7
+ {
8
+ "description": "Opt-in wheel selection, skipping disabled entries without closing the panel. Defaults off.",
9
+ "name": "changeOnScroll",
10
+ "type": "boolean"
11
+ },
12
+ {
13
+ "description": "Controlled panel visibility.",
14
+ "name": "open",
15
+ "type": "boolean"
16
+ },
17
+ {
18
+ "description": "Initial panel visibility.",
19
+ "name": "defaultOpen",
20
+ "type": "boolean"
21
+ },
22
+ {
23
+ "description": "Panel visibility changes.",
24
+ "name": "onOpenChange",
25
+ "type": "(open: boolean) => void"
26
+ },
27
+ {
28
+ "description": "Validation appearance; error announces invalid state.",
29
+ "name": "status",
30
+ "type": "\"error\" | \"warning\""
31
+ },
32
+ {
33
+ "description": "Shared control surface.",
34
+ "name": "variant",
35
+ "type": "\"outlined\" | \"filled\" | \"borderless\""
36
+ },
37
+ {
38
+ "description": "Shared control sizing.",
39
+ "name": "size",
40
+ "type": "\"sm\" | \"md\" | \"lg\""
41
+ },
42
+ {
43
+ "description": "Disable typing while preserving panel selection.",
44
+ "name": "inputReadOnly",
45
+ "type": "boolean"
46
+ },
47
+ {
48
+ "description": "Keep invalid draft text on blur; never submit it as a committed value.",
49
+ "name": "preserveInvalidOnBlur",
50
+ "type": "boolean"
51
+ },
52
+ {
53
+ "description": "Logical popup placement.",
54
+ "name": "placement",
55
+ "type": "\"bottom-start\" | \"bottom-end\" | \"top-start\" | \"top-end\""
56
+ },
57
+ {
58
+ "description": "Additional panel footer content.",
59
+ "name": "renderExtraFooter",
60
+ "type": "() => ReactNode"
61
+ },
62
+ {
63
+ "description": "Ref to the editable input (range start).",
64
+ "name": "ref",
65
+ "type": "Ref<HTMLInputElement>"
66
+ },
67
+ {
68
+ "description": "Hour column step, default 1.",
69
+ "name": "hourStep",
70
+ "type": "number"
71
+ },
72
+ {
73
+ "description": "Second column step, default 1.",
74
+ "name": "secondStep",
75
+ "type": "number"
76
+ },
77
+ {
78
+ "description": "Enable seconds in the panel and canonical value.",
79
+ "name": "showSeconds",
80
+ "type": "boolean"
81
+ },
82
+ {
83
+ "description": "Override the locale hour cycle.",
84
+ "name": "use12Hours",
85
+ "type": "boolean"
86
+ },
87
+ {
88
+ "description": "HH:mm, HH:mm:ss, h:mm A or date-fns a. Canonical value stays HH:mm or HH:mm:ss.",
89
+ "name": "format",
90
+ "type": "string"
91
+ },
92
+ {
93
+ "description": "Forbid individual hours, minutes and seconds. Without it a 開始/終了 pair has no way to stop the end time being set before the start — the columns will happily offer it. Applies to BOTH routes into the value: a disabled option cannot be clicked, is skipped by the arrow keys, and a forbidden time typed into the field is rejected.",
94
+ "name": "disabledTime",
95
+ "type": "TimePickerDisabledTimeProp"
96
+ },
97
+ {
98
+ "defaultValue": "false",
99
+ "description": "Drop disabled options from the columns instead of greying them out (antd's default too). Greyed-out is usually better — a visible-but-refused option tells the reader the rule exists — but a column that is mostly forbidden reads better short.",
100
+ "name": "hideDisabledOptions",
101
+ "type": "boolean"
102
+ },
103
+ {
104
+ "defaultValue": "true",
105
+ "description": "Offer a \\u201cnow\\u201d action in the panel footer (antd's `showNow`). It is REFUSED, not hidden, when `disabledTime` forbids the current time — the same treatment a forbidden column option gets.",
106
+ "name": "showNow",
107
+ "type": "boolean"
108
+ },
109
+ {
110
+ "defaultValue": "false",
111
+ "description": "Hold the panel's choices as a DRAFT until a confirm action commits them (antd's `needConfirm`). Default `false` diverges from antd deliberately: this library has always committed on select and closed, and flipping the default would silently add a click to every existing time field. Opt in where the value is expensive to change (a saved shift, a published slot).",
112
+ "name": "needConfirm",
113
+ "type": "boolean"
114
+ },
115
+ {
116
+ "description": "Controlled value in HH:mm (24h) format. When provided the component is fully controlled — you must update it via `onValueChange`.",
117
+ "name": "value",
118
+ "type": "string"
119
+ },
120
+ {
121
+ "description": "Uncontrolled initial value in HH:mm format. Used only when `value` is not provided.",
122
+ "name": "defaultValue",
123
+ "type": "string"
124
+ },
125
+ {
126
+ "description": "Called with the canonical HH:mm string whenever the user commits a time (picks from columns or types and blurs/presses Enter). Not called for every keystroke.",
127
+ "name": "onValueChange",
128
+ "type": "(value: string) => void"
129
+ },
130
+ {
131
+ "description": "Native form field name. Formatted or staged controls manage a hidden canonical value internally; do not add a second hidden field.",
132
+ "name": "name",
133
+ "type": "string"
134
+ },
135
+ {
136
+ "description": "HTML id for the visible input — use with a `<label htmlFor>` for accessibility.",
137
+ "name": "id",
138
+ "type": "string"
139
+ },
140
+ {
141
+ "defaultValue": "hh:mm (i18n fallback)",
142
+ "description": "Placeholder text shown when the input is empty. Falls back to the i18n key `dataEntry.timePicker.placeholder`.",
143
+ "name": "placeholder",
144
+ "type": "string"
145
+ },
146
+ {
147
+ "defaultValue": "false",
148
+ "description": "Disables both the visible input and the clock-icon popover trigger.",
149
+ "name": "disabled",
150
+ "type": "boolean"
151
+ },
152
+ {
153
+ "defaultValue": "5",
154
+ "description": "Step for the minute column (1–60). Only multiples of this step appear in the picker; typed values are still free-form and normalized on blur.",
155
+ "name": "minuteStep",
156
+ "type": "number"
157
+ },
158
+ {
159
+ "description": "Extra Tailwind classes applied to the outer wrapper `<div>`. Use for width overrides (e.g. `w-32`).",
160
+ "name": "className",
161
+ "type": "string"
162
+ },
163
+ {
164
+ "defaultValue": "true",
165
+ "description": "Inline ✕ on the trigger that resets the value when one is set (Ant-style). Pass `false` to hide it (e.g. a required field).",
166
+ "name": "allowClear",
167
+ "type": "boolean"
168
+ }
169
+ ],
170
+ "related": [
171
+ "DatePicker — use for calendar date selection; combine with TimePicker in a flex row when you need a full datetime. DatePicker emits an ISO date string; TimePicker emits HH:mm.",
172
+ "Input — the raw primitive TimePicker wraps internally. Use Input directly only when you need a plain text field with no time semantics or popover.",
173
+ "ColorPicker — another popover-backed input primitive in the same group; structurally similar pattern but for hex colour values."
174
+ ],
175
+ "rules": [
176
+ 3,
177
+ 6,
178
+ 13,
179
+ 23
180
+ ],
181
+ "storyPath": "data-entry/TimePicker.stories.tsx",
182
+ "tagline": "Time combobox with hours, minutes, optional seconds, confirmation and 12-hour formatting. Native submission stays canonical 24-hour time.",
183
+ "usage": [
184
+ "One trailing icon: empty shows calendar/clock; filled and clearable shows only ×; allowClear=false retains the picker icon. Click the input or ArrowDown to open a filled picker.",
185
+ "DO give it a name in native forms. It submits HH:mm or HH:mm:ss, regardless of display format; the component manages any hidden canonical field.",
186
+ "DO use the controlled pattern (`value` + `onValueChange`) in React-managed forms (e.g. useForm). For simple HTML forms without React state, omit `value` and use `defaultValue` for the uncontrolled pattern.",
187
+ "DON'T pass a raw `<input type='time'>` alongside or instead — this component IS the input, fully accessible (role='combobox', aria-expanded, aria-haspopup) and e2e-testable by filling the text input directly.",
188
+ "DO pair with a `<label htmlFor={id}>` for screen-reader accessibility — the component renders a plain `<input>` internally that `id` connects to.",
189
+ "DON'T expect `onValueChange` on every keystroke — it fires only when a valid HH:mm is committed (column pick closes popover; typed value normalised on blur or Enter). Guard downstream logic accordingly.",
190
+ "DO adjust `minuteStep` for domain needs (e.g. `minuteStep={15}` for scheduling, `minuteStep={1}` for precise entry) — the minute column only shows multiples, but the type-in field accepts any valid HH:mm."
191
+ ],
192
+ "useCases": [
193
+ "Shift/schedule entry forms where workers select start and end times from a scrollable hour/minute grid (use `minuteStep={15}` or `minuteStep={30}`).",
194
+ "Invoice or transaction timestamp fields that require a 24h HH:mm time alongside a DatePicker — pair the two in a flex row.",
195
+ "Logistics cut-off time configuration (e.g. 'last order by') where the default `minuteStep={5}` aligns with typical operational granularity.",
196
+ "Admin settings panels that persist a canonical HH:mm string to the database — the `name` prop makes native form submission trivial.",
197
+ "Time-range pickers (from/to) — render two TimePicker instances side-by-side with separate controlled values and validate that `to > from` in `onValueChange`.",
198
+ "E2E-tested forms — test helpers can fill the text input directly (it accepts typed HH:mm) without needing to interact with the popover columns."
199
+ ]
200
+ }
@@ -0,0 +1,90 @@
1
+ {
2
+ "docPath": "docs/data-entry/time-range-picker.tsx",
3
+ "example": "import { TimeRangePicker } from \"@godxjp/ui/data-entry\";\n<TimeRangePicker aria-label=\"Shift\" defaultValue={[\"09:00\", \"18:00\"]} />",
4
+ "group": "data-entry",
5
+ "importPath": "@godxjp/ui/data-entry",
6
+ "name": "TimeRangePicker",
7
+ "props": [
8
+ {
9
+ "description": "Controlled canonical times.",
10
+ "name": "value",
11
+ "type": "[string,string]"
12
+ },
13
+ {
14
+ "description": "Uncontrolled initial range.",
15
+ "name": "defaultValue",
16
+ "type": "[string,string]"
17
+ },
18
+ {
19
+ "description": "Reports edited range.",
20
+ "name": "onValueChange",
21
+ "type": "(value: [string,string]) => void"
22
+ },
23
+ {
24
+ "description": "Sort times automatically; false allows overnight ranges.",
25
+ "name": "order",
26
+ "type": "boolean"
27
+ },
28
+ {
29
+ "description": "Permitted empty endpoints, default [true,true].",
30
+ "name": "allowEmpty",
31
+ "type": "[boolean,boolean]"
32
+ },
33
+ {
34
+ "description": "Native names are name_from and name_to.",
35
+ "name": "name",
36
+ "type": "string"
37
+ },
38
+ {
39
+ "description": "TimePicker display format.",
40
+ "name": "format",
41
+ "type": "string"
42
+ },
43
+ {
44
+ "description": "Shared time constraints.",
45
+ "name": "disabledTime",
46
+ "type": "TimePickerDisabledTimeProp"
47
+ },
48
+ {
49
+ "description": "Enable second precision.",
50
+ "name": "showSeconds",
51
+ "type": "boolean"
52
+ },
53
+ {
54
+ "description": "Minute column step.",
55
+ "name": "minuteStep",
56
+ "type": "number"
57
+ },
58
+ {
59
+ "description": "Hour column step.",
60
+ "name": "hourStep",
61
+ "type": "number"
62
+ },
63
+ {
64
+ "description": "Second column step.",
65
+ "name": "secondStep",
66
+ "type": "number"
67
+ },
68
+ {
69
+ "description": "Permit clear only for an endpoint also allowed empty.",
70
+ "name": "allowClear",
71
+ "type": "boolean"
72
+ }
73
+ ],
74
+ "related": [
75
+ "TimePicker",
76
+ "DatePicker"
77
+ ],
78
+ "rules": [
79
+ 9
80
+ ],
81
+ "storyPath": "data-entry/time-range-picker.tsx",
82
+ "tagline": "Ordered time range with optional endpoints and canonical native fields.",
83
+ "usage": [
84
+ "Use for a start/end time pair. Set order=false for overnight intervals.",
85
+ "Each endpoint follows the one-trailing-icon rule; allowEmpty=false suppresses its clear action."
86
+ ],
87
+ "useCases": [
88
+ "Shift scheduling and reception hours."
89
+ ]
90
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ "example": "import { Timeline } from \"@godxjp/ui/data-display\";\n\n// Default icon variant\n<Timeline items={[\n { title: \"注文受付\", time: \"2024-06-01 10:00\" },\n { title: \"発送準備中\", time: \"2024-06-01 14:00\" },\n { title: \"配送中\", current: true },\n]} />\n\n// Numbered route stepper (Pattern A)\n<Timeline variant=\"ordinal\" items={[\n { title: \"集荷\", location: \"東京 → 名古屋\", status: \"pending\" },\n { title: \"幹線輸送\", location: \"名古屋 → 大阪\", status: \"pending\" },\n]} />\n\n// Status tracker (Pattern B): done → check, current → dot, pending → number\n<Timeline variant=\"status\" items={[\n { title: \"請求書を発行\", status: \"done\" },\n { title: \"承認待ち\", status: \"current\" },\n { title: \"消費税を計上\", status: \"pending\" },\n]} />",
3
+ "group": "data-display",
4
+ "importPath": "@godxjp/ui/data-display",
5
+ "name": "Timeline",
6
+ "props": [
7
+ {
8
+ "description": "Array of `{ title, location?, time?, note?, current?, status?, icon? }`. `status` is the explicit 3-state ('done' | 'current' | 'pending'); `current: true` is shorthand for `status: 'current'`. `icon` (a LucideIcon) overrides the auto-glyph for that item.",
9
+ "name": "items",
10
+ "required": true,
11
+ "type": "TimelineItem[]"
12
+ },
13
+ {
14
+ "description": "Rail glyph strategy (default 'icon'). 'icon' = legacy look (Plane for current, CheckCircle2 otherwise). 'ordinal' = every glyph is its 1-based step number; status sets colour only. 'status' = glyph by status (done → check, current → filled dot, pending → step number).",
15
+ "name": "variant",
16
+ "type": "\"icon\" | \"ordinal\" | \"status\""
17
+ }
18
+ ],
19
+ "related": [
20
+ "Steps — use Steps (navigation group) when the user must actively progress through a wizard (interactive, shows step numbers/status, horizontal layout by default); use Timeline for read-only historical event sequences that have already happened.",
21
+ "Descriptions — use Descriptions to display a flat set of label/value metadata fields (e.g., invoice header); use Timeline when events are ordered chronologically and a connector rail communicates sequence and progress.",
22
+ "DataTable — use DataTable for multi-row, multi-column tabular event logs where sorting, filtering, and pagination are needed; use Timeline when the sequence/rail visual is the primary communication and there are fewer than ~10 events.",
23
+ "Badge — Badge is a single-item inline indicator; Timeline sequences multiple statuses with connectors. Compose Badge inside a Timeline `title` or `note` field for richer per-event context, but do not replace Timeline with a stack of Badges."
24
+ ],
25
+ "rules": [],
26
+ "storyPath": "data-display/Timeline.stories.tsx",
27
+ "tagline": "Vertical event list with an icon rail. Current item gets a highlighted glyph. `variant` switches the rail to numbered (ordinal) or status-driven glyphs, and each item carries a 3-state `status` (done/current/pending) plus an optional per-item `icon`. The whole progress column is ONE hue: done dot, current dot and travelled line all paint `--primary`, exactly as `Steps` paints `finish` and `process`.",
28
+ "usage": [
29
+ "DO pass an array of `TimelineItem` objects to `items`. Each item is `{ title, location?, time?, note?, current?, status?, icon? }`. All fields except `title` are optional. The only other prop is `variant`.",
30
+ "DO mark the in-progress event with `current: true` (or `status: 'current'`). In the default `variant='icon'`, the current item renders a `Plane` icon and every other item a `CheckCircle2`. Use `variant='ordinal'` for a numbered route stepper (1,2,3…) or `variant='status'` for a done→check / current→dot / pending→number tracker. Pass `status: 'done' | 'current' | 'pending'` per item to drive colour and (in the status variant) the glyph; pass `icon` (a LucideIcon) to override the glyph for a single item.",
31
+ "DO pass `ReactNode` to `title`, `location`, `time`, and `note` — you can embed formatted text, `<Badge>`, `<Badge>`, or `<span>` inside those fields. Use `formatDate` to pre-format timestamps before passing them as `time`.",
32
+ "DO NOT hand-roll a vertical event list with divs, icons, and connector lines — that is exactly what Timeline ships. Do not apply extra padding or wrapping outside the component; it manages its own rail and spacing internally.",
33
+ "DO NOT use Timeline for user-facing wizard progress (steps the user must complete in order) — use `Steps` for that. Timeline is read-only historical/status display; it has no interactive state, no `onClick`, and no concept of 'go to step'.",
34
+ "DO wrap Timeline in `<CardContent>` when placing it inside a `Card` — bare `Card` has no inner padding, so the rail will render flush against the card edge without `CardContent`.",
35
+ "THE PROGRESS COLUMN IS ONE HUE (gh#731). The done dot, the current dot and the travelled line all default to `hsl(var(--primary))` — the same contract `Steps` uses for `finish` + `process`, and antd's (only `error` leaves the primary hue). The current item is told apart by a ring (`--timeline-dot-current-ring-width`, `--steps-dot-process-ring-width`'s value), by `aria-current=\"step\"` + a localized sr-only prefix, and by a different glyph — never by a second colour role. Re-theme `--primary` and the whole rail follows. Measured light: done 2.18:1 → 6.31:1 against the card, glyph 6.31:1 on the fill; dark 7.22:1 → 9.84:1, glyph 10.72:1.",
36
+ "DON'T expect `--success` on a `status: 'done'` item — `done | current | pending` is POSITION IN A SEQUENCE, not status, and Timeline has no `tone` axis. Put a real status on the item's `title` or `note` with a `<Badge tone=\"success\">`, which is the surface that owns the status green.",
37
+ "TO RESTORE the pre-27.9 green/violet pairing, set the done dot's fill AND its ink together in your theme (global or `[data-tenant]`) — the two roles have opposite ink polarity, so the fill alone leaves a near-white glyph on 若竹 green at 2.18:1 (gh#643): `--timeline-dot-done-background: hsl(var(--success)); --timeline-dot-done-foreground: hsl(var(--success-foreground));`. `--timeline-dot-current-background` and `--timeline-line-completed-background` retint the other two surfaces the same way."
38
+ ],
39
+ "useCases": [
40
+ "Shipment / delivery tracking — showing a parcel's journey through 'Order placed → Packed → In transit → Delivered' with timestamps and a current-stop indicator.",
41
+ "Accounting document audit trail — rendering the lifecycle of an invoice or payment (Draft → Submitted → Approved → Paid) with the current approval stage highlighted.",
42
+ "Support ticket / task history — displaying a chronological log of status transitions (Open → Assigned → In Review → Closed) with agent names in the `note` field and timestamps in `time`.",
43
+ "MF sync log viewer — listing each sync run event (OAuth refresh, fetch, upsert) with timestamps and record counts so an operator can see what the last sync did.",
44
+ "Approval workflow status panel — showing a multi-stage approval chain where completed stages have CheckCircle2 icons and the pending stage has the Plane (in-flight) icon.",
45
+ "Order / purchase-order lifecycle in an admin detail page — placed alongside a `Descriptions` summary at the top of a `Card` to give a compact at-a-glance history."
46
+ ]
47
+ }
@@ -0,0 +1,92 @@
1
+ {
2
+ "example": "import { TimelineGrid } from \"@godxjp/ui/data-display\";\n\n<TimelineGrid\n label=\"週シフト 5月11日〜17日\"\n start=\"06:00\"\n end=\"24:00\"\n interval={2}\n now=\"14:35\"\n columns={[\n { id: \"05-13\", label: \"水 13\" },\n { id: \"05-14\", label: \"木 14\", current: true },\n ]}\n events={[\n { id: \"a\", columnId: \"05-14\", start: \"09:00\", end: \"17:30\", title: \"早番\", description: \"田中\" },\n { id: \"b\", columnId: \"05-14\", start: \"13:00\", end: \"22:00\", title: \"遅番\", description: \"高橋\" },\n { id: \"c\", columnId: \"05-14\", start: \"22:00\", end: \"06:00\", title: \"夜勤\", description: \"伊藤\" },\n ]}\n onEventSelect={(event) => openShift(event.id)}\n/>",
3
+ "group": "data-display",
4
+ "importPath": "@godxjp/ui/data-display",
5
+ "name": "TimelineGrid",
6
+ "props": [
7
+ {
8
+ "description": "Accessible name of the grid. Required, and a plain string: the grid is a focusable scrolling region, so its name has to survive as an `aria-label`.",
9
+ "name": "label",
10
+ "required": true,
11
+ "type": "string"
12
+ },
13
+ {
14
+ "description": "`{ id, label, description?, current? }` in render order. `label` is the column head AND the accessible name of that column's event list, so keep it text. `current: true` marks today's column: it takes the tint and hosts the `now` marker.",
15
+ "name": "columns",
16
+ "required": true,
17
+ "type": "TimelineGridColumnProp[]"
18
+ },
19
+ {
20
+ "description": "`{ id, columnId, start, end, title, description?, color? }` in any order. `start`/`end` are clock times in the column's own day, `\"HH:MM\"` 24-hour (`\"24:00\"` = end of day). An `end` at or before `start` continues into the next day (22:00–06:00 夜勤). `color` is the record's own colour, washed like `Badge color`.",
21
+ "name": "events",
22
+ "required": true,
23
+ "type": "TimelineGridEventProp[]"
24
+ },
25
+ {
26
+ "defaultValue": "the earliest event, on the hour",
27
+ "description": "First clock time on the axis, `\"HH:MM\"`. Left off, the axis is derived from the events, so a block can only fall outside an axis you PINNED.",
28
+ "name": "start",
29
+ "type": "string"
30
+ },
31
+ {
32
+ "defaultValue": "the latest event, on the hour",
33
+ "description": "Last clock time on the axis, `\"HH:MM\"`. A block the pinned axis cuts is drawn to the edge and carries `data-clipped`, and still prints its real range as text.",
34
+ "name": "end",
35
+ "type": "string"
36
+ },
37
+ {
38
+ "defaultValue": "1",
39
+ "description": "Hours between hour rules and axis labels. Use 2 or 3 when a long axis has to fit one screen.",
40
+ "name": "interval",
41
+ "type": "number"
42
+ },
43
+ {
44
+ "description": "Current clock time, `\"HH:MM\"`. Draws the now marker in every column marked `current`. The marker is decorative (`aria-hidden`): the hours it points at are already text on every block.",
45
+ "name": "now",
46
+ "type": "string"
47
+ },
48
+ {
49
+ "description": "Block click handler. Its PRESENCE turns every block into a real `button`, which is what makes the blocks keyboard-reachable; without it the grid is a read-only board.",
50
+ "name": "onEventSelect",
51
+ "type": "(event: TimelineGridEventProp) => void"
52
+ },
53
+ {
54
+ "description": "Extra classes on the scroll region.",
55
+ "name": "className",
56
+ "type": "string"
57
+ },
58
+ {
59
+ "description": "DOM id on the scroll region.",
60
+ "name": "id",
61
+ "type": "string"
62
+ }
63
+ ],
64
+ "related": [
65
+ "Timeline — one lane of ordered events with no scale (an audit trail, a shipment history). TimelineGrid is the same family with a measured time axis and one lane per column.",
66
+ "Table — the MONTH calendar is a real table (`bordered`, one row per week, one cell per day), not a TimelineGrid.",
67
+ "Calendar — the single-date PICKER in data-entry. Use it to jump to a month; it does not show events.",
68
+ "Sheet — the usual destination of `onEventSelect`: the block is the affordance, the drawer is the detail.",
69
+ "Badge — the same `color` wash for a record's own colour, on a chip instead of a block."
70
+ ],
71
+ "rules": [
72
+ 42,
73
+ 45
74
+ ],
75
+ "storyPath": "data-display/TimelineGrid.stories.tsx",
76
+ "tagline": "The time-axis half of the Timeline family: a vertical hour axis, one column per day (or room, or machine) and event blocks placed by start time and duration. Overlapping events are laid out side by side automatically. NOT a calendar — no month view, no navigation, no drag-to-create, no recurrence, no timezone conversion.",
77
+ "usage": [
78
+ "DO import from `@godxjp/ui/data-display`: `import { TimelineGrid } from \"@godxjp/ui/data-display\";`",
79
+ "DO give a shift/booking board one column per day and let the grid place the blocks. DON'T hand-roll a `relative` container with absolutely-positioned divs and percentage offsets — that is the exact shape this primitive replaces (#354 item 7), and it hides one of two overlapping shifts.",
80
+ "DO re-tune the rhythm with the tokens instead of a className: `--timeline-grid-hour-height` is the height of one hour (the knob that fits a 24-hour axis on one screen), `--timeline-grid-column-min-width` is the floor below which the grid scrolls instead of collapsing, `--timeline-grid-axis-width` is the hour rail, and `--timeline-grid-event-color` / `--timeline-grid-now-color` / `--timeline-grid-current-tint` are role-mirror colour knobs.",
81
+ "DO express a shift that crosses midnight as `start: \"22:00\", end: \"06:00\"` — an `end` at or before `start` means the next day. The block is drawn to the end of the window and marked `data-clipped`, and the text still reads 22:00–06:00.",
82
+ "DON'T reach for TimelineGrid for a MONTH calendar: a month grid is a real `Table`, one `TableRow` per week and one `TableCell` per day. TimelineGrid owns the continuous time axis, not the day matrix.",
83
+ "DON'T expect navigation, drag-to-create, recurrence or timezone conversion — none of it ships. `start`/`end` are clock times in the column's own day; which day a column stands for is yours to decide.",
84
+ "DON'T pass an event whose `columnId` matches no column, or one that falls entirely outside a pinned `start`/`end`: it is not drawn. Leave the axis unpinned and it is derived from the events instead."
85
+ ],
86
+ "useCases": [
87
+ "A weekly shift board (シフトカレンダー): seven day columns on a 06:00–24:00 axis, 早番 / 遅番 / 夜勤 blocks in the decorative wa-iro palette, `now` drawing the current-time line on today's column.",
88
+ "A day view of one team: one column per staff member, `interval={1}`, `onEventSelect` opening the shift detail in a Sheet.",
89
+ "Meeting-room booking for a single day: one column per room, the axis derived from the bookings themselves, overlapping holds side by side so a double-booking is visible instead of hidden.",
90
+ "Machine / bay utilisation on a shop floor: one column per machine, blocks coloured by job, the clipped marker showing a run that continues past the shift window."
91
+ ]
92
+ }