@godxjp/ui 28.9.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 (232) 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/props/components/data-entry.prop.d.ts +21 -2
  211. package/dist/props/components/layout.prop.d.ts +42 -0
  212. package/dist/props/registry.d.ts +9 -0
  213. package/dist/props/registry.js +6 -0
  214. package/dist/styles/card-layout.css +4 -4
  215. package/dist/styles/control.css +31 -2
  216. package/dist/styles/data-display-layout.css +1 -1
  217. package/dist/styles/layout.css +17 -0
  218. package/dist/styles/navigation-layout.css +3 -1
  219. package/dist/styles/shell-layout.css +2 -0
  220. package/dist/styles/table-layout.css +50 -9
  221. package/dist/tokens/components/segmented.css +5 -1
  222. package/dist/tokens/components/table.css +2 -1
  223. package/docs/COMPOSITION-VS-COMPONENT.md +41 -0
  224. package/docs/DESIGN-AUTHORITY.md +14 -0
  225. package/docs/DEVELOPMENT.md +81 -6
  226. package/docs/data-entry/tag-input.tsx +37 -0
  227. package/docs/layout/flex.tsx +40 -0
  228. package/docs/roadmap/website-components.md +34 -0
  229. package/docs/showcase/marketing-page.tsx +54 -45
  230. package/docs/showcase/table-pagination.tsx +88 -18
  231. package/docs/showcase/theme-customization.tsx +25 -2
  232. package/package.json +6 -4
@@ -0,0 +1,48 @@
1
+ {
2
+ "example": "import { Banner } from \"@godxjp/ui/feedback\";\nimport { Button } from \"@godxjp/ui/general\";\n\n<Banner tone=\"warning\">\n <Banner.Content>\n <Banner.Title>お支払いが確認できていません</Banner.Title>\n <Banner.Description>サービスの停止を避けるため、お支払い方法を更新してください。</Banner.Description>\n </Banner.Content>\n <Banner.Actions>\n <Button size=\"sm\" variant=\"outline\">お支払い方法を更新</Button>\n </Banner.Actions>\n</Banner>",
3
+ "group": "feedback",
4
+ "importPath": "@godxjp/ui/feedback",
5
+ "name": "Banner",
6
+ "props": [
7
+ {
8
+ "defaultValue": "\"default\"",
9
+ "description": "Semantic tone driving the surface colour, the default leading icon AND live-region politeness (\"destructive\"/\"warning\" announce assertively via role=\"alert\"; every other tone politely via role=\"status\").",
10
+ "name": "tone",
11
+ "type": "\"default\" | \"success\" | \"warning\" | \"destructive\" | \"info\" | \"muted\" | \"neutral\""
12
+ },
13
+ {
14
+ "description": "Renders the built-in localized dismiss button (top/inline-end). It sits LAST in DOM and focus order: content → actions → dismiss.",
15
+ "name": "onDismiss",
16
+ "type": "() => void | Promise<void>"
17
+ },
18
+ {
19
+ "description": "Override or hide (false) the tone's default leading icon.",
20
+ "name": "icon",
21
+ "type": "LucideIcon | false"
22
+ }
23
+ ],
24
+ "related": [
25
+ "Alert — the SAME primitive in its inline-card presentation; use inside a page section or Card for persistent local feedback. Banner is the full-bleed strip presentation for shell/page-level attention.",
26
+ "Toaster — transient auto-dismissing feedback (toast()). Banner is persistent until acted on or dismissed.",
27
+ "ErrorSurface — a whole-page semantic exception state (403/404/5xx) that REPLACES the page. Banner annotates a page that still works.",
28
+ "PageContainer — Banner sits ABOVE or as the first child of PageContainer, never inside the header slots; the page header's own status/meta belongs in PageContainer's `status` prop."
29
+ ],
30
+ "rules": [],
31
+ "storyPath": "feedback/Banner.stories.tsx",
32
+ "tagline": "Full-bleed page/shell attention strip (past-due subscription, support session, maintenance). Parts: Banner.Title/Description/Content/Actions.",
33
+ "usage": [
34
+ "CANONICAL BANNER CONTRACT: `Banner` is `Alert` with the structural axis fixed to `variant=\"banner\"` — same tone system, same slots, same dismiss/a11y behaviour, but STRIP geometry owned by the `--banner-*` tokens (square corners, hairline block-end rule, page-gutter inline inset). Never fake a banner by putting `className` overrides on an `Alert`, and never hand-roll a coloured div strip.",
35
+ "DO: Place a Banner FULL-BLEED at the top of the surface it warns about — directly under the Topbar inside AppShell's children for shell-wide attention (past-due subscription, active support session), or as the first child of a page for page-scoped notices. Its inline inset defaults to the page gutter (--space-page-active-x) so the text column aligns with page content.",
36
+ "DO: Compose text as `Banner.Title` + `Banner.Description` (group multi-part copy in `Banner.Content` when you add `Banner.Actions`). At >=640px actions sit in a trailing column; below the step they drop onto their own full-width WRAPPING line, so a 390px viewport wraps instead of clipping.",
37
+ "DO: Pass `onDismiss` for dismissible notices — the component renders its own accessible, localized dismiss button. DON'T hand-roll an × Button in `Banner.Actions`.",
38
+ "DON'T: Use Banner for transient feedback ('saved successfully') — that is `toast()` + `<Toaster>`. Banner is persistent and page/shell-scoped, and there should be at most ONE per surface; stack further messages inside the page as inline `Alert`s.",
39
+ "DON'T: Encode DXS business rules here (when past_due shows, who sees a support-session strip) — the app decides WHEN to render; Banner owns only presentation and behaviour."
40
+ ],
41
+ "useCases": [
42
+ "Past-due subscription strip across the console shell — `tone=\"warning\"` with a `Banner.Actions` \"お支払い方法を更新\" Button, rendered above the page slot until billing recovers.",
43
+ "Active support-session indicator — `tone=\"info\"` with the operator name in `Banner.Description` and a \"セッションを終了\" action; not dismissible while the session runs.",
44
+ "Scheduled maintenance notice — `tone=\"neutral\"` with `onDismiss` so the user can clear it for the session.",
45
+ "Read-only / archived-organization mode — `tone=\"muted\"` explaining why every mutation control on the page is disabled.",
46
+ "Degraded-service warning after a partial outage — `tone=\"destructive\"` with a status-page link in `Banner.Actions`."
47
+ ]
48
+ }
@@ -0,0 +1,108 @@
1
+ {
2
+ "example": "import { BarChart } from \"@godxjp/ui/charts\";\n\n<BarChart\n label={t(\"report.salesByRegion\")}\n data={data}\n categoryKey=\"region\"\n series={[{ dataKey: \"sales\", label: t(\"metric.sales\") }]}\n numberFormat={{ notation: \"compact\" }}\n/>",
3
+ "group": "data-display",
4
+ "importPath": "@godxjp/ui/charts",
5
+ "name": "BarChart",
6
+ "props": [
7
+ {
8
+ "description": "Row data: one category per row with a numeric value per series.",
9
+ "name": "data",
10
+ "required": true,
11
+ "type": "ChartDatum[]"
12
+ },
13
+ {
14
+ "description": "Plotted series: { dataKey, label?, color? }.",
15
+ "name": "series",
16
+ "required": true,
17
+ "type": "ChartSeriesProp[]"
18
+ },
19
+ {
20
+ "description": "Key into each datum holding the category label.",
21
+ "name": "categoryKey",
22
+ "required": true,
23
+ "type": "string"
24
+ },
25
+ {
26
+ "description": "Accessible name + visible caption.",
27
+ "name": "label",
28
+ "required": true,
29
+ "type": "string"
30
+ },
31
+ {
32
+ "defaultValue": "true",
33
+ "description": "Paint `label` as a visible caption. Set false when a CardTitle or section heading already says it — the caption stays in the DOM as sr-only, so role=img keeps its accessible name.",
34
+ "name": "showCaption",
35
+ "type": "boolean"
36
+ },
37
+ {
38
+ "description": "Extra context appended to the screen-reader description.",
39
+ "name": "description",
40
+ "type": "string"
41
+ },
42
+ {
43
+ "defaultValue": "\"md\"",
44
+ "description": "Canvas height preset. Ignored when `height` is set.",
45
+ "name": "size",
46
+ "type": "\"xs\" | \"sm\" | \"md\" | \"lg\""
47
+ },
48
+ {
49
+ "description": "Explicit canvas height in px (overrides `size`).",
50
+ "name": "height",
51
+ "type": "number"
52
+ },
53
+ {
54
+ "defaultValue": "true",
55
+ "description": "Show the series legend.",
56
+ "name": "showLegend",
57
+ "type": "boolean"
58
+ },
59
+ {
60
+ "defaultValue": "true",
61
+ "description": "Show the cartesian background grid.",
62
+ "name": "showGrid",
63
+ "type": "boolean"
64
+ },
65
+ {
66
+ "description": "Locale-aware formatting for ticks + tooltip values.",
67
+ "name": "numberFormat",
68
+ "type": "Intl.NumberFormatOptions"
69
+ },
70
+ {
71
+ "defaultValue": "false",
72
+ "description": "Stack series into one bar instead of grouping side by side.",
73
+ "name": "stacked",
74
+ "type": "boolean"
75
+ },
76
+ {
77
+ "defaultValue": "false",
78
+ "description": "Lay bars out horizontally (category on the y-axis).",
79
+ "name": "horizontal",
80
+ "type": "boolean"
81
+ },
82
+ {
83
+ "description": "Message shown when `data` is empty.",
84
+ "name": "emptyMessage",
85
+ "type": "string"
86
+ }
87
+ ],
88
+ "related": [
89
+ "LineChart — continuous trend rather than discrete comparison.",
90
+ "PieChart — single part-to-whole composition.",
91
+ "DataTable — exact tabular figures."
92
+ ],
93
+ "rules": [],
94
+ "storyPath": "charts/BarChart.stories.tsx",
95
+ "tagline": "Compare a value across categories — grouped or `stacked`, vertical or `horizontal`, with localized ticks/tooltips and a built-in text alternative. Data-visualization graph / plot / diagram.",
96
+ "usage": [
97
+ "DO import from the charts entry: `import { BarChart } from \"@godxjp/ui/charts\";` (recharts optional peer required).",
98
+ "DO import only the chart a screen uses — `import { BarChart } from \"@godxjp/ui/charts/bar-chart\";` — when the `./charts` barrel should not link the whole chart family. Without the `recharts` peer the build then fails ONCE, naming the package and the fix.",
99
+ "DO use `horizontal` when category labels are long (they read better on the y-axis).",
100
+ "DO use `stacked` for part-to-whole-per-category; keep grouped (default) for direct side-by-side comparison.",
101
+ "DON'T use BarChart for a single part-to-whole total — that is PieChart. DON'T fake bars with styled divs."
102
+ ],
103
+ "useCases": [
104
+ "Sales by region / category comparison.",
105
+ "Stacked composition per period (e.g. expense breakdown by month).",
106
+ "Ranking with long labels (horizontal)."
107
+ ]
108
+ }
@@ -0,0 +1,89 @@
1
+ {
2
+ "docPath": "data-entry/branch-scope-picker.tsx",
3
+ "example": "import { BranchScopePicker, FormField } from \"@godxjp/ui/data-entry\";\n\n<FormField label=\"適用範囲\" required error={errors.scope}>\n <BranchScopePicker\n branches={branches}\n value={scope}\n onValueChange={setScope}\n error={scope.mode === \"selected\" && !scope.branchIds?.length ? \"1件以上選択してください\" : undefined}\n />\n</FormField>",
4
+ "group": "data-entry",
5
+ "importPath": "@godxjp/ui/data-entry",
6
+ "name": "BranchScopePicker",
7
+ "props": [
8
+ {
9
+ "description": "Giá trị có kiểm soát: phạm vi đang chọn.",
10
+ "name": "value",
11
+ "type": "BranchScopeValueProp"
12
+ },
13
+ {
14
+ "description": "Giá trị khởi tạo khi không kiểm soát.",
15
+ "name": "defaultValue",
16
+ "type": "BranchScopeValueProp"
17
+ },
18
+ {
19
+ "description": "Phát khi phạm vi đổi.",
20
+ "name": "onValueChange",
21
+ "type": "(value: BranchScopeValueProp) => void"
22
+ },
23
+ {
24
+ "description": "The selectable branches — consumer domain data.",
25
+ "name": "branches",
26
+ "required": true,
27
+ "type": "{ id: string; name: string; description?: string; disabled?: boolean }[]"
28
+ },
29
+ {
30
+ "description": "The controlled triad; default { mode: \"all\" }. Mode flips PRESERVE branchIds so switching back to all never destroys a curated subset.",
31
+ "name": "value / defaultValue / onValueChange",
32
+ "type": "{ mode: \"all\" | \"selected\"; branchIds?: string[] }"
33
+ },
34
+ {
35
+ "description": "Field VALIDATION message — rendered under the control and wired via aria-invalid/aria-errormessage on the radiogroup. Collection read failures are `listError`, not this.",
36
+ "name": "error",
37
+ "type": "ReactNode"
38
+ },
39
+ {
40
+ "description": "`true` renders the built-in localized message.",
41
+ "name": "listError / denied / loading / empty",
42
+ "type": "boolean | ReactNode"
43
+ },
44
+ {
45
+ "defaultValue": "false",
46
+ "description": "Locked view: the current scope as a static summary (mode + branch badges).",
47
+ "name": "readOnly",
48
+ "type": "boolean"
49
+ },
50
+ {
51
+ "defaultValue": "false",
52
+ "description": "Controls visible but inert.",
53
+ "name": "disabled",
54
+ "type": "boolean"
55
+ },
56
+ {
57
+ "defaultValue": "true",
58
+ "description": "Built-in branch search above the checkbox list.",
59
+ "name": "searchable",
60
+ "type": "boolean"
61
+ },
62
+ {
63
+ "description": "Override the localized radio labels (e.g. domain wording like 全店舗).",
64
+ "name": "allLabel / selectedLabel",
65
+ "type": "ReactNode"
66
+ }
67
+ ],
68
+ "related": [
69
+ "CheckboxGroup / RadioGroup — the primitives underneath; use them directly for non-scope choices.",
70
+ "Transfer — large two-list assignment; BranchScopePicker is the compact all-vs-subset scope idiom.",
71
+ "TreeSelect — hierarchical selection when branches nest."
72
+ ],
73
+ "rules": [
74
+ 24
75
+ ],
76
+ "storyPath": "data-entry/BranchScopePicker.stories.tsx",
77
+ "tagline": "Canonical scope control: all branches vs an explicit subset.",
78
+ "usage": [
79
+ "DO treat scope as ONE form field: the single { mode, branchIds } value goes through FormField like any other control.",
80
+ "DO import it from @godxjp/ui/data-entry — never compose an ad-hoc radio+checkbox scope block per screen.",
81
+ "DO use `error` ONLY for validation (e.g. mode=selected with zero branches checked); a failed branch fetch is `listError`, a 403 is `denied`.",
82
+ "DO NOT preselect branches for the user — default is { mode: \"all\" }; an explicit subset is a user decision."
83
+ ],
84
+ "useCases": [
85
+ "Role/permission assignment scoped to branches (service role forms).",
86
+ "Report or notification audience: whole org vs selected branches.",
87
+ "Read-only scope display on a detail screen (readOnly)."
88
+ ]
89
+ }
@@ -0,0 +1,54 @@
1
+ {
2
+ "example": "import { Breadcrumb } from \"@godxjp/ui/layout\";\n\n<Breadcrumb items={[\n { label: \"ホーム\", to: \"/\" },\n { label: \"会員管理\", to: \"/members\" },\n { label: \"田中 太郎\" },\n]} />",
3
+ "group": "layout",
4
+ "importPath": "@godxjp/ui/layout",
5
+ "name": "Breadcrumb",
6
+ "props": [
7
+ {
8
+ "description": "Array of { label, to?, menu? } — omit `to` on the last (current) segment. `menu` (Ant Design `BreadcrumbItemType.menu`) hangs a sibling picker off that segment: `{ items: { value, label, to?, disabled? }[], onSelect? }`. The segment then renders as a menu button, not a link — an entry with `to` becomes a real anchor inside the menu while keeping `role=\"menuitem\"`.",
9
+ "name": "items",
10
+ "required": true,
11
+ "type": "BreadcrumbItemProp[]"
12
+ },
13
+ {
14
+ "description": "Ant Design `separator`. Defaults to the chevron glyph; a string (`\"/\"`) or any node replaces it and `\"\"` removes it. Always `aria-hidden` — the trail's structure is the `<ol>`/`<li>`, so a screen reader never reads the glyph.",
15
+ "name": "separator",
16
+ "type": "React.ReactNode"
17
+ },
18
+ {
19
+ "description": "Ant Design `itemRender`. Replaces ONE segment's body while Breadcrumb keeps owning the `<nav>` landmark, the `<ol>`/`<li>`, the separators and `aria-current`. Use it to hand the trail a router `<Link>` (Inertia, react-router) instead of a bare `<a>`.",
20
+ "name": "itemRender",
21
+ "type": "(item: BreadcrumbItemProp, info: { index: number; isLast: boolean; items: BreadcrumbItemProp[] }) => React.ReactNode"
22
+ },
23
+ {
24
+ "description": "Override the nav landmark's accessible name (defaults to a localized \"Breadcrumb\"). Required when more than one Breadcrumb renders on the same page/view — two nav landmarks sharing one name/role fail landmark-unique.",
25
+ "name": "aria-label",
26
+ "type": "string"
27
+ }
28
+ ],
29
+ "related": [
30
+ "PageContainer — accepts `breadcrumb` as `BreadcrumbItemProp[]` (raw array, not a ReactNode); use this when each page owns its own breadcrumb and you want it co-located with the page title, actions, and body.",
31
+ "AppShell — accepts `breadcrumb` as `ReactNode`; pass `<Breadcrumb items={…} />` here when the breadcrumb is a persistent shell-level strip that sits above all page content rather than being owned by individual pages.",
32
+ "Steps — use instead of Breadcrumb when showing progress through an ordered multi-step flow (wizard, checkout, onboarding); Steps conveys sequence and completion state, not spatial location.",
33
+ "PrefetchLink — if ancestor breadcrumb segments should prefetch their destination query on hover/focus, consider pairing the `to` values with `PrefetchLink` in a custom breadcrumb or pre-warming the cache on mount; Breadcrumb's internal links are plain react-router-dom `<Link>` with no prefetch behaviour."
34
+ ],
35
+ "rules": [],
36
+ "storyPath": "layout/Breadcrumb.stories.tsx",
37
+ "tagline": "Standalone breadcrumb nav rendering an ordered trail of page segments.",
38
+ "usage": [
39
+ "DO import from `@godxjp/ui/layout` (not from a navigation or general sub-path) and pass a single `items` prop — an ordered array of `{ label, to? }` objects. No children, no sub-components, no render-prop API.",
40
+ "DO omit `to` on the last (current-page) segment — the component automatically renders it as a `<span aria-current=\"page\">` instead of a router `<Link>`. Passing `to` on the last item does NOT make it a link; drop it intentionally.",
41
+ "DO pass the Breadcrumb node as a ReactNode to the `breadcrumb` prop of `AppShell` (or `AppShell`) for shell-level breadcrumbs, or to `PageContainer`'s `breadcrumb` prop (which accepts `BreadcrumbItemProp[]` directly — not a ReactNode). When passing to `PageContainer`, pass the raw array; when passing to `AppShell`, wrap it: `breadcrumb={<Breadcrumb items={…} />}`.",
42
+ "DON'T hand-roll a breadcrumb strip (divs with chevrons, anchors, separators) — Breadcrumb ships the `<nav aria-label=\"Breadcrumb\">` + `<ol>` + `aria-hidden` chevrons. Any custom trail is a violation of the no-hand-roll rule and will fail `npm run ui:audit`.",
43
+ "DON'T use Breadcrumb for tab-style or step-style navigation (multi-step forms, wizard progress). Those flows belong to `Steps`. Breadcrumb is strictly a spatial location trail, not a process indicator.",
44
+ "The component is fully uncontrolled and stateless — it renders whatever `items` you pass. Dynamic breadcrumbs (route-derived, breadcrumb context, etc.) must be assembled in the parent and passed down as a plain array; there is no internal routing awareness."
45
+ ],
46
+ "useCases": [
47
+ "Per-page location trail on any admin page deeper than two levels — e.g. Home → Accounting → Invoices → Invoice #1042 — passed to `PageContainer`'s `breadcrumb` prop so it appears above the page `<h1>`.",
48
+ "Persistent shell-level breadcrumb in a `AppShell` or `AppShell` layout that updates as the user navigates between Inertia/React Router pages; constructed from route params and passed as a ReactNode to `AppShell`'s `breadcrumb` prop.",
49
+ "Master-detail drill-down in an accounting app: the detail page (journal entry, partner, bank account) shows a breadcrumb back to the list and to the domain root, giving the user a one-click escape without using the browser back button.",
50
+ "Embedded sub-panel breadcrumb inside a `SplitPane` or `Sheet` where a secondary content area has its own navigable hierarchy and needs a compact location indicator.",
51
+ "Audit log or document history page where the entity being reviewed (invoice, payment) is the current segment and the parent module (Accounting, Receivables) is a clickable ancestor.",
52
+ "Prefetch pairing: wrap ancestor segments' `to` values with `PrefetchLink` semantics by putting them in `items` — each non-last item with `to` is already rendered as a router `<Link>`, so hovering naturally prefetches if `PrefetchLink` is used elsewhere on the same route."
53
+ ]
54
+ }
@@ -0,0 +1,133 @@
1
+ {
2
+ "example": "import { Button } from \"@godxjp/ui/general\";\nimport { Trash2 } from \"lucide-react\";\n\n<>\n <Button>保存</Button>\n <Button variant=\"outline\" size=\"sm\">編集</Button>\n <Button variant=\"ghost\" size=\"icon-sm\"><Trash2 className=\"size-4\" /></Button>\n</>",
3
+ "group": "general",
4
+ "importPath": "@godxjp/ui/general",
5
+ "name": "Button",
6
+ "props": [
7
+ {
8
+ "defaultValue": "\"default\"",
9
+ "description": "Visual style. `dashed` = outline with a dashed border (Ant-style add-row / placeholder action).",
10
+ "name": "variant",
11
+ "type": "\"default\" | \"destructive\" | \"outline\" | \"dashed\" | \"secondary\" | \"ghost\" | \"link\" | \"bare\""
12
+ },
13
+ {
14
+ "defaultValue": "\"default\"",
15
+ "description": "Size preset (height, padding, icon dims).",
16
+ "name": "size",
17
+ "type": "\"default\" | \"xs\" | \"sm\" | \"lg\" | \"icon\" | \"icon-xs\" | \"icon-sm\" | \"icon-lg\""
18
+ },
19
+ {
20
+ "defaultValue": "\"default\"",
21
+ "description": "Corner radius from the tokens — `default` (control radius), `pill` (fully rounded, --radius-pill), `sharp` (square, --radius-sharp). Use the prop instead of a `rounded-*` className.",
22
+ "name": "shape",
23
+ "type": "\"default\" | \"pill\" | \"sharp\""
24
+ },
25
+ {
26
+ "defaultValue": "false",
27
+ "description": "Span the full container width (`width:100%`) instead of sizing to content.",
28
+ "name": "fullWidth",
29
+ "type": "boolean"
30
+ },
31
+ {
32
+ "defaultValue": "false",
33
+ "description": "Take the space the siblings leave, and let a long label ELLIPSE instead of widening the row — the same axis Flex calls `fill`, for the same reason. Button ships flex-shrink: 0, which is right almost everywhere and wrong in a constrained bar: an account menu holding an avatar plus a person's name keeps its full width while the cluster clips it, so a keyboard user tabs to a control they cannot see (SC 2.4.7). Sets flex: 1 1 auto and min-inline-size: 0; pair it with a <Text truncate> label. This is what replaces className=\"min-w-0 flex-1\", which ui-audit blocks — and which this package's own Topbar guidance used to recommend.",
34
+ "name": "fill",
35
+ "type": "boolean"
36
+ },
37
+ {
38
+ "defaultValue": "false",
39
+ "description": "Allow multi-line text labels to grow the button height. Uses the active size tier as its minimum height; use with fullWidth in narrow collections.",
40
+ "name": "wrap",
41
+ "type": "boolean"
42
+ },
43
+ {
44
+ "defaultValue": "\"center\"",
45
+ "description": "Logical content alignment. Use start for full-width collection actions; respects RTL.",
46
+ "name": "align",
47
+ "type": "\"start\" | \"center\" | \"end\""
48
+ },
49
+ {
50
+ "defaultValue": "false",
51
+ "description": "Render as Radix Slot — merge props onto the child (<a>/<Link>).",
52
+ "name": "asChild",
53
+ "type": "boolean"
54
+ },
55
+ {
56
+ "description": "Disable the button.",
57
+ "name": "disabled",
58
+ "type": "boolean"
59
+ },
60
+ {
61
+ "defaultValue": "false",
62
+ "description": "In-flight state — shows a leading `Loader2` spinner (replaces a leading icon if present), sets `aria-busy=\"true\"`, and blocks activation (non-interactive, pointer-events disabled) while keeping the label visible so the width doesn't jump. Prefer this over a hand-rolled `<Loader2 className=\"animate-spin\">` inside the button. Ignored when `asChild` (Slot requires a single child).",
63
+ "name": "loading",
64
+ "type": "boolean"
65
+ },
66
+ {
67
+ "description": "Optional label to swap in while `loading` (pass the `t()`-translated string, e.g. `loadingText={t('saving')}`). When omitted the original children stay beside the spinner.",
68
+ "name": "loadingText",
69
+ "type": "string"
70
+ },
71
+ {
72
+ "description": "Click handler. Does not fire while `loading` or `disabled`.",
73
+ "name": "onClick",
74
+ "type": "React.MouseEventHandler<HTMLButtonElement>"
75
+ },
76
+ {
77
+ "description": "Trailing borderless counter pill after the label (filter tabs / segmented toggles, e.g. \"Chờ bay 18\"). Localized via `Intl.NumberFormat`; styled per variant — never nest a `Badge` in a Button for this. Ignored when `asChild`.",
78
+ "name": "count",
79
+ "type": "number"
80
+ },
81
+ {
82
+ "defaultValue": "99",
83
+ "description": "Cap for `count` (Ant Badge parity) — when `count` exceeds it the pill renders `{overflowCount}+` (e.g. `99+`).",
84
+ "name": "overflowCount",
85
+ "type": "number"
86
+ },
87
+ {
88
+ "defaultValue": "true",
89
+ "description": "Whether the pill renders when `count` is 0 (Ant Badge parity). Pass `false` to hide the pill at zero.",
90
+ "name": "showZero",
91
+ "type": "boolean"
92
+ },
93
+ {
94
+ "description": "Localized description of what `count` MEANS, folded into the accessible name — the SAME prop and the same contract Toggle has carried since gh#312, added here in gh#734 because a counted Button measured `\"Git3\"` in the accessibility tree, not \"Git, 3 pages\". The pill is aria-hidden and the spoken clause is an sr-only sibling, so a text button announces as `\"<label>, <count> <countLabel>\"`; with an explicit `aria-label` (an icon-only counted button) the clause is folded into that instead. Pass a t()-resolved string — the library does not own this wording. Even without it the name is now `\"Git, 3\"` rather than `\"Git3\"`; `countLabel` is what turns the digits into a unit.",
95
+ "name": "countLabel",
96
+ "type": "string"
97
+ }
98
+ ],
99
+ "related": [
100
+ "TopbarItem — the same trigger INSIDE a Topbar slot. A Button there is a --control-height pill floating in a taller bar, with its own hover fill and a ring around the pill instead of the cell; TopbarItem is the bar cell itself. Anywhere that is not a bar, Button is right.",
101
+ "DropdownMenu — when a button needs to reveal a list of actions (e.g. 'Actions ▾' in a DataTable row), wrap the Button as a `DropdownMenuTrigger` inside a `DropdownMenu` compound; don't open a Sheet/Dialog just to show a list of options.",
102
+ "ButtonRefetch — a pre-wired Button variant from `@godxjp/ui/query` that binds directly to a TanStack Query result (shows spinner, auto-disables while fetching, retries on click). Use it instead of a raw Button whenever the action is a query refetch — do not pass `onClick`/`disabled` to it manually.",
103
+ "AlertMutationFeedback — for surfacing mutation errors and a retry action; it renders its own retry Button internally. Do not add a separate Button alongside AlertMutationFeedback for the same mutation.",
104
+ "PrefetchLink — use when the goal is purely navigation with hover-prefetch (Inertia v3 prefetch); it renders as an `<a>` not a button. Only reach for `Button asChild + Link` when the navigation control must look like a button (primary CTA style)."
105
+ ],
106
+ "rules": [
107
+ 23
108
+ ],
109
+ "storyPath": "general/Button.stories.tsx",
110
+ "subParts": [
111
+ "ButtonRefetch"
112
+ ],
113
+ "tagline": "Core button with variant + size presets, built on cva and Radix Slot (asChild).",
114
+ "usage": [
115
+ "DO pick the right variant for intent: `default` (primary CTA, one per section), `destructive` (irreversible actions like delete/revoke), `outline` (secondary actions alongside a primary), `secondary` (less prominent actions), `ghost` (toolbar icon-only actions), `link` (inline text-style navigation without an underline by default).",
116
+ "DO use icon-only sizes (`icon`, `icon-xs`, `icon-sm`, `icon-lg`) exclusively for buttons that contain only an SVG — these sizes set equal width/height. For text+icon buttons use `default|sm|lg|xs` sizes; icons inside are auto-sized to 1rem via `[&_svg:not([class*='size-'])]:size-4`.",
117
+ "DO use `asChild` to render the button as a React Router/Inertia `<Link>` or native `<a>` while keeping all button styling and a11y: `<Button asChild variant=\"outline\"><Link href={route('invoices.show', id)}>詳細</Link></Button>`. Never wrap a `<button>` around an `<a>` — that is invalid HTML.",
118
+ "DON'T use raw `<button>` elements anywhere in the UI — always use this `Button`. The only exception is an `aria-hidden` native control used as an e2e/a11y hook paired with a visible godx-ui control.",
119
+ "DO set `type=\"submit\"` explicitly on form submit buttons (the default HTML button type inside `<form>` is already `submit`, but being explicit prevents accidental double-submissions when a `type=\"button\"` sibling exists). For cancel/reset actions set `type=\"button\"` to avoid accidental form submission.",
120
+ "DON'T apply raw padding, height, or `rounded-*` overrides to `Button` via `className` — the size variants encode the full box model. If a custom size is truly needed, use `buttonVariants` from `@godxjp/ui/general` to compose a new cva class rather than fighting the existing ones.",
121
+ "DO use the `loading` prop for async/pending actions instead of hand-rolling `<Loader2 className=\"animate-spin\">` inside the button — `loading` renders the spinner, sets `aria-busy`, and blocks activation for you; pair with `loadingText={t('saving')}` to swap the label. For a TanStack Query refetch use `ButtonRefetch` (it owns its own loading lifecycle) rather than wiring `loading` manually.",
122
+ "DO pass `countLabel` with every `count` — without it the number is read as a bare digit run glued to the label. `<Button count={3} countLabel={t('common.pages')}>Git</Button>` announces \"Git, 3 pages\".",
123
+ "DON'T reach for `<Button count aria-pressed>` to build a FILTER CHIP — Button paints no pressed state, so the chip looks identical selected and unselected. That is `<Toggle variant=\"soft\" shape=\"pill\" count countLabel>` (gh#734)."
124
+ ],
125
+ "useCases": [
126
+ "Primary form submission in a Dialog or Sheet (e.g. `<Button type=\"submit\" disabled={form.processing}>保存</Button>`) — the `disabled` prop greys it out and blocks pointer events, preventing double-submit during async operations.",
127
+ "Destructive confirmation inside a Dialog — pair `tone=\"destructive\"` Button as the confirm action and `variant=\"outline\"` as Cancel; never use `variant=\"default\"` for a delete action.",
128
+ "Icon-only toolbar actions in a DataTable column (edit, delete, copy) using `size=\"icon-sm\"` + `variant=\"ghost\"` + a Lucide icon child — gives equal-width square targets that don't distort the row.",
129
+ "Navigation links styled as buttons (e.g. 'New Invoice', 'Back to list') using `asChild` + Inertia `<Link>` — preserves SPA navigation while using the button's visual treatment.",
130
+ "Async mutation trigger in an accounting workflow (e.g. 'Sync from MF', 'Export CSV') — disable on processing state; pair with `AlertMutationFeedback` for error/retry UI rather than inline `try/catch` alerts.",
131
+ "Refetch / retry trigger when NOT using TanStack Query — for manual cache refresh inside a TanStack Query context use `ButtonRefetch` instead, which owns its own `disabled`/`onClick` lifecycle."
132
+ ]
133
+ }