@godxjp/ui 2.2.0 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/BRAND.md +39 -29
  2. package/CHANGELOG.md +566 -10
  3. package/README.md +143 -168
  4. package/config/eslint.js +54 -0
  5. package/config/prettier.cjs +20 -0
  6. package/config/tsconfig.base.json +22 -0
  7. package/config/vitest.base.ts +26 -0
  8. package/dist/MiniMonth-YAmPGEpC.d.ts +143 -0
  9. package/dist/Table.types-BbsxoIYE.d.ts +352 -0
  10. package/dist/color-DO0qqUAb.d.ts +38 -0
  11. package/dist/components/composites.d.ts +963 -0
  12. package/dist/components/composites.js +7340 -0
  13. package/dist/components/composites.js.map +1 -0
  14. package/dist/components/primitives.d.ts +2633 -163
  15. package/dist/components/primitives.js +7266 -165
  16. package/dist/components/primitives.js.map +1 -1
  17. package/dist/components/shell.d.ts +82 -12
  18. package/dist/components/shell.js +168 -162
  19. package/dist/components/shell.js.map +1 -1
  20. package/dist/hooks.d.ts +83 -8
  21. package/dist/hooks.js +497 -83
  22. package/dist/hooks.js.map +1 -1
  23. package/dist/i18n.d.ts +55 -3
  24. package/dist/i18n.js +456 -5
  25. package/dist/i18n.js.map +1 -1
  26. package/dist/index.d.ts +24 -5
  27. package/dist/index.js +12524 -267
  28. package/dist/index.js.map +1 -1
  29. package/dist/padding-DY0JV5Ja.d.ts +16 -0
  30. package/dist/preferences.d.ts +132 -0
  31. package/dist/preferences.js +262 -0
  32. package/dist/preferences.js.map +1 -0
  33. package/dist/props.d.ts +86 -0
  34. package/dist/props.js +16 -0
  35. package/dist/props.js.map +1 -0
  36. package/dist/size-CQwNvOWd.d.ts +19 -0
  37. package/dist/{data.d.ts → types-LTj-2bl-.d.ts} +7 -12
  38. package/dist/useTableViews-D5NIAJ7h.d.ts +154 -0
  39. package/package.json +92 -35
  40. package/src/tokens/tailwind.css +158 -0
  41. package/dist/components/screens.d.ts +0 -51
  42. package/dist/components/screens.js +0 -806
  43. package/dist/components/screens.js.map +0 -1
  44. package/dist/data.js +0 -93
  45. package/dist/data.js.map +0 -1
  46. package/src/tokens/tokens-ext.css +0 -401
  47. package/src/tokens/tokens.css +0 -765
package/CHANGELOG.md CHANGED
@@ -3,18 +3,570 @@
3
3
  All notable changes to `@godxjp/ui`. Follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
4
4
  and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5
5
 
6
+ ## [5.0.1] — 2026-05-18
7
+
8
+ ### Fixed
9
+
10
+ - **`<Col>` no longer wipes `flex-basis` on default-span renders.** React
11
+ 19 serializes `flex: undefined` as `element.style.flex = ""`, and
12
+ because `flex` is a CSS shorthand it clears the `flex-basis: ${span}%`
13
+ longhand set on the line above. Result: every `<Row gutter><Col xs=
14
+ {24} md={12}>` was collapsing to content width instead of the
15
+ half-width the API promised. Conditional spread keeps the `flex` key
16
+ out of the style object unless actually defined (#70).
17
+
18
+ ## [5.0.0] — 2026-05-18
19
+
20
+ ### BREAKING CHANGES
21
+
22
+ - **`<Table>` chrome props removed.** The legacy "data-table page"
23
+ props moved off the primitive into the `<DataTable>` composite.
24
+ TypeScript compilation will fail for any call site that passes:
25
+ `toolbar`, `views`, `batchActions`, `filters`, `onFiltersChange`,
26
+ `filterBar`, `onResetFilters`, `pagination`, `tableKey`. See
27
+ ADR-0007 and `docs/how-to/migrate-to-data-table.md` for the
28
+ required migration (1:1 prop-to-hook diff for every removed prop).
29
+ - **`<Table batchActions>` → `<Table selection>`.** Consumers that
30
+ used the primitive's batch-actions config strictly for the
31
+ checkbox column switch to the slimmer `selection` prop. Same
32
+ `selectedRowKeys` / `onSelectedRowKeysChange` /
33
+ `getCheckboxDisabled` shape; the batch action band UI moves to
34
+ the composite.
35
+ - **`Table.persistence.ts` relocated** to
36
+ `src/components/composites/data-table/persistence.ts`. The slim
37
+ primitive no longer reads or writes localStorage; the composite
38
+ threads persistence through `useDataTable`.
39
+
40
+ ### Changed
41
+
42
+ - **`Table.tsx`: 1,842 → 901 lines** (~51% reduction). Forking the
43
+ primitive in place (rule 4) is achievable again.
44
+ - **`DataTable.tsx`: 86 → ~280 lines.** The composite renders view
45
+ tabs, toolbar bar, batch action band, filter chip bar, pagination
46
+ band, column manager Sheet, and save-view Dialog directly.
47
+ TanStack `useReactTable` lives in `useDataTable`; the primitive
48
+ accepts the instance via a new `instance?` prop and falls back to
49
+ a local hook only when standalone.
50
+ - **CSS split** — chrome rules moved from
51
+ `src/styles/shell/40-table.css` into a new
52
+ `src/styles/shell/41-data-table.css`. `shell.css` imports the new
53
+ file directly after the old one so cascade order is unchanged.
54
+ - **Story migration** — `WithToolbar`, `InteractionRegression`,
55
+ `Pagination_Numbered`, `Pagination_LoadMore`, `Pagination_Cursor`
56
+ moved from `data-display/Table.stories.tsx` to
57
+ `composites/DataTable.stories.tsx`. Bare-primitive stories that
58
+ passed chrome props (`StickyColumns`) updated to drop them.
59
+ `Table.stories::BulkActions` deleted (covered by the composite
60
+ story of the same name).
61
+
62
+ ### Migration
63
+
64
+ - See [`docs/how-to/migrate-to-data-table.md`](docs/how-to/migrate-to-data-table.md)
65
+ for the required v5 codemod. Each removed prop has a 1:1
66
+ composite + hook equivalent — there is no functionality loss.
67
+ - Consumers on v4 that still pass chrome props see a once-per-prop
68
+ `console.warn` from the primitive (introduced in
69
+ 4.0.x → 5.0.0-prep). The warning text links to the migration guide.
70
+
71
+ ## [Unreleased]
72
+
73
+ ### Added
74
+
75
+ - **`<DataTable>` composite + table hooks** (ADR-0006). New
76
+ ergonomic surface for the "data-table page" pattern. Pairs the
77
+ `<Table>` primitive with hook-based state slices:
78
+ - `useTablePagination` — page + pageSize slice with unified
79
+ `onChange`, `resetPage`, `reset`.
80
+ - `useTableSelection` — row selection with single / multiple mode +
81
+ `toggle` / `select` / `deselect` / `clear` helpers.
82
+ - `useTableViews` — saved-view state for tabbed table headers;
83
+ optional localStorage persistence via `storageKey`.
84
+ - `useTableState` — versioned localStorage useState (storageKey,
85
+ version, migrate, custom storage adapter). The canonical
86
+ persistence helper — industry-standard pattern (TanStack / MRT /
87
+ MantineRT).
88
+ - `useDataTable` — composite-level config builder that threads the
89
+ slices into a typed instance ready for `<DataTable table={…}>`.
90
+ Exported from `@godxjp/ui` (hooks) and `@godxjp/ui/components/composites`
91
+ (composite). See [`docs/reference/composites/DataTable.md`](docs/reference/composites/DataTable.md)
92
+ and [`docs/how-to/migrate-to-data-table.md`](docs/how-to/migrate-to-data-table.md).
93
+ - **`<Pagination variant="embedded">`** — table-footer layout
94
+ (info + page-size changer + numeric pager with optional first / last
95
+ chevron buttons). Reused inside `<Table pagination=…>`. New props on
96
+ the existing `<Pagination>`: `defaultPageSize` / `onPageSizeChange`,
97
+ `pageSizeOptions`, `showSizeChanger`, `showFirstLast`,
98
+ `hideOnSinglePage`, `boundary`, `firstPageLabel` / `previousPageLabel`
99
+ / `nextPageLabel` / `lastPageLabel` / `pageSizeLabel`. Exported
100
+ helper `computePageRange(current, total, sibling, boundary)`.
101
+ - **i18n key `table.lastPage`** added to all four locales
102
+ (ja / en / vi / fil) for the new last-page button.
103
+ - **ADR-0006** documenting the Table primitive vs DataTable
104
+ composite split.
105
+
106
+ ### Changed
107
+
108
+ - **`<Table>` file split** — extracted types + ColumnMeta
109
+ augmentation into `Table.types.ts` and localStorage helpers into
110
+ `Table.persistence.ts`. Public API unchanged; existing
111
+ `from "@godxjp/ui"` imports of any Table-related symbol continue
112
+ to resolve. Source file dropped from 2,353 → 1,838 lines (~22%).
113
+ - **`<Pagination>` is now the single pagination primitive** —
114
+ the inline numbered renderer that lived inside `<Table>` is gone;
115
+ `<Table pagination={{ type: "numbered", … }}>` now renders
116
+ `<Pagination variant="embedded">` under the hood. Cardinal rule 32
117
+ (no redundant components) is now satisfied.
118
+ - **`.tbl-pagination` numbered styles** migrated to
119
+ `.pagination[data-variant="embedded"]` in `90-navigation.css`.
120
+ `.tbl-pagination` remains the layout wrapper for the load-more and
121
+ cursor pagination variants only.
122
+ - **Lucide icons** replace the inline SVG chevrons inside
123
+ `<Pagination>` (rule 14 — locked stack).
124
+ - **`<Select>` gained `searchable`** + `searchPlaceholder`, `emptyLabel`,
125
+ `loading`, `loadingLabel` props. When `searchable` is set the
126
+ primitive flips from Radix Select to a cmdk + Popover render tree
127
+ with a filter input above the list; value semantics stay constrained
128
+ to `options[i].value`.
129
+ - **Docs consolidation** — moved the five canonical specs from
130
+ `new-docs/` to `docs/specs/` so the framework ships ONE
131
+ documentation tree. The umbrella binding table, CLAUDE.md
132
+ trigger table, AGENTS.md routing table, and every doc /
133
+ story / source comment that referenced `new-docs/*` now
134
+ cite `docs/specs/*`. Pruned outdated `docs/explanation/`
135
+ pages (brand-bible, compatibility, versioning,
136
+ tokens-architecture) that duplicated specs/BRAND.md/CLAUDE.md.
137
+
138
+ ### Fixed
139
+
140
+ - **Tour spotlight cutout** — the target area now uses an SVG mask
141
+ cutout so the active element stays undimmed while the rest of the
142
+ viewport is subdued.
143
+ - **Tree React Aria foundation** — `Tree` now delegates ARIA tree
144
+ keyboard navigation, selection, expansion, and disabled state to
145
+ `react-aria-components` while preserving the single public `Tree`
146
+ primitive. Row content customization now goes through `renderItem`;
147
+ local row spacing uses the shared `density` vocabulary, and
148
+ connector lines are rendered from tree structure instead of guessed
149
+ from the flattened React Aria DOM.
150
+
151
+ ### Added
152
+
153
+ - **Table A5 — sort + resize** — `sort` accepts
154
+ `TableSort | TableSort[] | null`; shift-click on a sortable header
155
+ extends the multi-sort list and the header renders a numbered
156
+ priority badge (1 / 2 / 3) at the right edge. `resizable` enables
157
+ a 4px right-edge grip on each header; double-click auto-fits via
158
+ TanStack `column.resetSize()`.
159
+ - **Table A6 — expand row** — `expandable` adds a 32px first cell
160
+ with a ▶ toggle; the detail panel sits in a full-width row with
161
+ the canonical 3px primary left border. Exclusive by default;
162
+ `allowMultiple` keeps prior opens.
163
+ - **Table A7 — inline editing** — `editing` carries `rowId` (current
164
+ editing row), `dirtyRowIds` / `dirtyCellIds` (warning-dot
165
+ tracking), `renderEditCell`, `isRowReadOnly`, and a built-in
166
+ footer banner (`.tbl-footer[data-state="dirty"]`) with Save-all /
167
+ Cancel-all when any row is dirty. Confirmed rows are read-only
168
+ via `isRowReadOnly` — double-click is suppressed.
169
+ - **Table A8 — grouped + tree rows** — `groupBy` buckets rows by
170
+ key, emits a full-width `.group-row` header with title + count
171
+ badge + right-floated total. `tree.children` walks data
172
+ recursively, emitting 14px / level indent and a twirl button on
173
+ parent rows.
174
+ - **Table A9 — column-manager lock toggle** — the column-manager
175
+ Sheet renders a 🔒 / 🔓 button next to each row to pin / unpin
176
+ columns at runtime; changes fire through `onColumnPinningChange`
177
+ (TanStack-canonical `ColumnPinningState`).
178
+ - **Table A10 — pagination variants** — `TablePaginationVariantConfig`
179
+ discriminates on `type`: `numbered` (default + back-compat),
180
+ `load-more` (feed lists with `hasMore` + `onLoadMore`), and
181
+ `cursor` (time-series jump-to-month via `value` + `inputType`).
182
+ - **Table A11 — Import / Export composite** — new
183
+ `TableImportFlow` (4-step stepper + file card + error preview)
184
+ and `TableExportDialog` (format / range / hidden-column toggles)
185
+ in `@godxjp/ui/components/composites`. Separate from the Table
186
+ primitive per cardinal rule 32 (no redundant props on Table).
187
+ - **Table saved views** — `TableViewsConfig` now lets saved-view tabs
188
+ apply `filters`, `sort`, and `columnVisibility` snapshots while
189
+ keeping persistence in consumer state. The Table story opens a
190
+ naming dialog before saving and warns when another view already
191
+ has the same filters and column visibility. Views can opt into
192
+ deletion with `deletable` + `onDeleteView`, while built-in views
193
+ remain protected by default. `getTableViewsStorageKey` provides
194
+ the localStorage namespace next to column visibility.
195
+ - **`GodxConfigProvider` + format helpers** — canonical alias of
196
+ `PreferencesProvider` per ADR 0005. The provider now wraps
197
+ children in React Aria's `<I18nProvider>` so every date / time /
198
+ number primitive picks up the locale automatically. Three thin
199
+ helper files (`src/i18n/format.ts`, `src/i18n/relative.ts`,
200
+ `src/hooks/useFormatters.ts`) wrap native `Intl` APIs +
201
+ `@internationalized/date` values; no new runtime dependency. The
202
+ legacy `PreferencesProvider` / `usePreferences` names remain as
203
+ deprecated aliases until v4.0.0.
204
+ - **`currency` preference + `setCurrency`** — `Preferences.currency`
205
+ carries an ISO 4217 default for `formatCurrency()`. Persisted to
206
+ the same storage backend as locale / timezone.
207
+ - **Timeline `time` accepts temporal values** — `time` now takes
208
+ `Date | CalendarDate | CalendarDateTime | ZonedDateTime` (in
209
+ addition to `ReactNode`). The active provider's locale + timezone
210
+ format it via `useFormatters` per the new `timeFormat` prop
211
+ (`"relative" | "datetime" | "date" | "time"`, default
212
+ `"relative"` for `feed`, `"datetime"` elsewhere).
213
+ - **Separator labels** — horizontal `Separator` now accepts
214
+ `children`, `titlePlacement`, `orientationMargin`, and `variant`
215
+ for Ant Design-style labeled dividers, replacing manual Flex +
216
+ two-separator composition. Prop vocabulary docs and the
217
+ Storybook vocabulary catalogue now include those concepts.
218
+ - **Descriptions data API** — `Descriptions` now renders from
219
+ `items` and supports `renderItem` for custom rows. The
220
+ `Descriptions.Item` sub-component shape was removed so consumers
221
+ use one component consistently.
222
+ - **Table data API** — `Table` is now a single-component TanStack
223
+ Table wrapper. Legacy table subcomponent exports were removed
224
+ from the public surface; use `columns`, `data`, `ColumnDef.cell`,
225
+ and the `toolbar` prop.
226
+ - **Statistic loading + animation** — `loading` renders skeleton
227
+ placeholders with `aria-busy`, while `animated` /
228
+ `animationDuration` count finite numeric values from zero /
229
+ previous value and respect `prefers-reduced-motion`.
230
+ - **Cardinal rule 32 — no redundant props.** A new top-level prop /
231
+ item field / variant is rejected at review if an existing prop /
232
+ item field / variant already covers the use case. Lifted from the
233
+ Timeline `pending` audit; future PRs must justify every new prop
234
+ against the existing surface.
235
+ - **Timeline `connector` prop** — `boolean`, default `true`. Toggles
236
+ the vertical line that joins markers in `list` + `branching`
237
+ variants. `feed` variant has no connector by design.
238
+ - **Timeline per-item `animate` field** — `TimelineItem.animate:
239
+ boolean` adds a pulsing ring around the marker dot for that single
240
+ item, replacing the previous top-level `animate` Timeline-level
241
+ prop (now removed — animate is a per-item concept). Honours
242
+ `prefers-reduced-motion`.
243
+ - **Storybook test gate** — `@storybook/addon-vitest` wired with
244
+ Playwright (browser-mode Chromium) so every `play()` runs as a
245
+ Vitest test. `pnpm test:stories` → 419 tests / 89 files / ~7s.
246
+ Interactive primitives now ship with regression-pinned focus, click,
247
+ hover, type, open/close flows (PR #18 + extended in #19, #20).
248
+ - **Code panel default on Story view** — `@storybook/addon-docs`
249
+ `parameters.docs.codePanel: true` so consumers see runnable JSX
250
+ beside Controls / Actions / Interactions without click-through.
251
+ - **Actions panel auto-spy** — `parameters.actions.argTypesRegex:
252
+ "^on[A-Z].*"` logs every `on*` callback invocation globally.
253
+ - **Cardinal rule 30** — story `render` must return JSX directly. No
254
+ `<XyzDemo />` wrapper components, no parameterised helpers. Storybook
255
+ source view stays copy-pasteable.
256
+ - **Parity scripts + pre-commit gate** —
257
+ `scripts/check-stories-parity.mjs` (rule 17) +
258
+ `scripts/check-docs-parity.mjs` (rule 18). Husky pre-commit runs
259
+ `lint:tokens` + both parity checks + `sync:skills` + `type-check`
260
+ in ~5s; CI re-runs them on push.
261
+ - **DatePicker stories** — `Placeholder`, `Granularity_DateTime`
262
+ (hour / minute via `granularity` + `hourCycle`), `MinMaxConstrained`,
263
+ `Format_Locales` (ja-JP / en-US / de-DE segment order via
264
+ `I18nProvider`).
265
+ - **`Select` `options` prop** — Ant / MUI / Mantine canonical
266
+ data-driven API. `<Select options={[{value,label}]} />`. Children
267
+ API remains for advanced layouts (groups / dividers / custom item
268
+ rendering).
269
+ - **40 reference doc stubs** — `docs/reference/<group>/<Name>.md`
270
+ draft scaffold for the previously undocumented primitives (Flex,
271
+ Form, Transfer, Field, LocaleTabs, Checklist, Spinner, IconButton,
272
+ PageHeader, SegmentedControl, Statistic, Empty, Tag, Alert, Result,
273
+ Typography, Descriptions, Radio, Slider, Watermark, Popconfirm,
274
+ Anchor, Menu, Pagination, Steps, Progress, DatePicker,
275
+ AutoComplete, Cascader, Tree, ColorPicker, Rate, Carousel, Collapse,
276
+ List, Image, QRCode, Tooltip, Timeline, Tour). `check:docs-parity`
277
+ now exits clean at 63/63.
278
+
279
+ ### Fixed
280
+
281
+ - **Separator vertical styling** — vertical separators now render via
282
+ `.divider-vertical` instead of inline style, so Card divider stories
283
+ can compose the Separator primitive without raw `<hr>` elements.
284
+ - **Skeleton default animation** — ported Ant Design's active
285
+ skeleton gradient pattern (`25% / 37% / 63%`, `400% 100%`,
286
+ `1.4s ease`) to godx tokens, with reduced-motion fallback.
287
+ - **Skeleton shape atoms** — `.sk-line` / `.sk-block` now have
288
+ explicit full-width defaults and `.sk-circle` keeps its 34px
289
+ width in flex rows, fixing list/table loading stories.
290
+ - **Sidebar collapsed labels** — collapsed mode now omits nav label
291
+ and badge nodes from the DOM while preserving `aria-label` /
292
+ `title`, so standalone Sidebar stories cannot leak clipped text
293
+ when the wrapper selector changes.
294
+ - **SegmentedControl WAI-ARIA roving-tabindex** — radiogroup now ships
295
+ the APG-compliant keyboard pattern: only the active radio carries
296
+ `tabIndex={0}`; Arrow keys (Left/Right or Up/Down per the new
297
+ `orientation` prop) move focus + selection; Home / End jump to
298
+ first / last enabled item; disabled items are skipped. Root reflects
299
+ `aria-orientation`. Replaces the previous native-Tab-order fallback
300
+ that the docs claimed but didn't implement.
301
+ - **IconButton accessible-name warn** — dev-mode `console.warn` when
302
+ none of `aria-label` / `aria-labelledby` / `title` is supplied
303
+ (`process.env.NODE_ENV !== "production"` only — production bundles
304
+ strip the check). Catches the most common a11y regression on
305
+ icon-only controls without forcing a breaking TS signature.
306
+ - **Tooltip nested-provider double-wrap** — data-driven `<Tooltip>`
307
+ detects an ancestor `<TooltipProvider>` (via a private React
308
+ marker context the framework's Provider populates) and skips its
309
+ inner Provider so the outer `delayDuration` / other Provider
310
+ config is no longer silently overridden. Falls back to the
311
+ previous double-wrap when the ancestor is Radix's Provider imported
312
+ directly (not the framework's re-export) — documented in the
313
+ Tooltip reference doc.
314
+ - **AutoComplete focus closing the dropdown** —
315
+ `onFocusOutside={preventDefault}` so opening on focus survives the
316
+ focus-leaves-anchor lifecycle.
317
+ - **AutoComplete label vs value** — input shows the selected option's
318
+ `label`; `onValueChange` reports the option's `value` (Ant / shadcn
319
+ convention).
320
+ - **`<List>` and `<Menu>` nested `<li>`** — `List` renderItem no
321
+ longer wraps in an extra `<li>`; `Menu` switched from
322
+ `<li role="none">` to `<div role="group">` (ARIA-compliant).
323
+ - **`Collapse` Tailwind utility collision** — root class renamed
324
+ `.collapse` → `.collapse-root` so Tailwind v4's
325
+ `.collapse { visibility: collapse }` utility no longer hides the
326
+ subtree.
327
+ - **Carousel vertical** — `height: 100%` cascades through `.carousel`
328
+ / `-viewport` / `-track`, clipping to one slide at a time.
329
+ - **Card banner double-border + radius** (B3 / C1) — `.ph.striped`
330
+ resets the inherited `.ph` chrome (border / radius / margin-bottom).
331
+ - **Card B3 stats footer** — uses `.card-footer-block` primitive class
332
+ instead of inline `borderTop` + manual padding.
333
+ - **Card H8 tabs underline rounding** — `<button>` instead of
334
+ `<Button>` for tab elements + `border-radius: 0` explicit on
335
+ `.card-header-tabs .tab` so an accidental `<Button>` doesn't
336
+ contaminate the underline.
337
+ - **Card H13 / H14 / H17 stories** — `<div className="card-body-block">` /
338
+ `<Card footer block>` sub-component pattern instead of raw
339
+ `<div className="card-body">` (rule 29).
340
+ - **Card H17 sticky-shadow scroll** — `max-height: 140 + overflow-y:
341
+ auto` instead of `height: 80 + overflow: hidden` so the story
342
+ actually demonstrates scrolling.
343
+ - **Descriptions bordered title overflow** — gap-as-border trick (1px
344
+ body bg) so the outer frame wraps the body only, title sits above.
345
+ - **Checkbox + Radio sizing** — 1rem (16px @ base) matching
346
+ shadcn / Ant / Tailwind canon, not the density-element scale
347
+ intended for full-height controls.
348
+ - **Checkbox glyph stroke** — `strokeWidth=3` +
349
+ `absoluteStrokeWidth` so the check / minus glyphs read at 12px.
350
+ - **Image fallback visible** — fills wrapper 100% with secondary bg
351
+ - border instead of 64×64 inline-flex chip against near-white body.
352
+ - **PageHeader `padding` prop** — vocabulary aligned with Card per
353
+ rule 23 §B (`tight` / `default` / `cozy` / `none`). Stacked variant
354
+ releases the fixed `--header-height` so breadcrumb + title get
355
+ vertical room.
356
+ - **Slider / InputSearch / Textarea controlled-uncontrolled props** —
357
+ conditional spread so the inner `<input>` never receives both
358
+ `value` and `defaultValue`.
359
+ - **TweaksPanel Dialog a11y** — `aria-describedby={undefined}` on
360
+ `Dialog.Content` since the panel doesn't use `Dialog.Description`.
361
+ - **Drawer Left story** — added `<DrawerDescription>` for a11y.
362
+ - **Sidebar collapsed text overflow** — CSS selectors broadened from
363
+ `.app-root[data-collapsed]` to `[data-collapsed]`, and Sidebar
364
+ wraps children in `<div data-collapsed style="display: contents">`
365
+ so the collapsed-state rules apply in both AppShell and standalone
366
+ contexts.
367
+ - **Storybook Docs source chip rendering** — `preview.css` forces
368
+ `.prismjs .token { display: inline; border: 0 }` to defeat
369
+ Storybook 10's per-token-pill style; consumers now see plain
370
+ syntax-highlighted JSX.
371
+ - **Storybook Docs canvas height** — `.sb-stage` no longer
372
+ `min-height: 100vh` so each story preview shrinks to content
373
+ instead of 707px frames.
374
+ - **Build warnings** — removed broken `banner: { js: '"use client"' }`
375
+ from `tsup.config.ts` (never reached output, only produced 7×
376
+ "module-level directive ignored" warnings per build). Posture now
377
+ matches MUI / Radix / shadcn (consumers mark App Router boundary
378
+ themselves).
379
+
380
+ ### Changed
381
+
382
+ - **Card story display names** — stripped section-code prefixes
383
+ (`A1·`, `B3·`, `H13·`, etc.) from 50 `name:` fields. URL slug
384
+ (const name) still carries the code for dev reference.
385
+ - **Story render demos inlined** — sweep of 14 stories in
386
+ `data-entry/` that wrapped their body in `<XyzDemo />` (DefaultDemo
387
+ / ControlledDemo / ValidatedDemo / PrefectureDemo / etc.) — bodies
388
+ now inline in `render: function StoryName() {…}` so Storybook's
389
+ dynamic source shows real JSX. `<ExampleForm disabled />` exemption
390
+ also removed.
391
+ - **`Card.stories.tsx` raw card-body / card-footer divs** —
392
+ ~27 occurrences replaced with `<div className="card-body-block">` / `<Card footer
393
+ block>` React sub-components per rule 29.
394
+ - **`docs.source.type`** — `"dynamic"` (was `"code"`) so the source
395
+ view renders the JSX, not the wrapping story object.
396
+ - **`docs.canvas.sourceState`** — `"hidden"` (was attempted `"shown"`)
397
+ so the Docs view doesn't auto-expand every story's source
398
+ (bloated 5-story pages to thousands of px).
399
+
400
+ ### Removed
401
+
402
+ - **Dialog legacy compositional API** — removed the multi-part modal
403
+ surface. `Dialog` is now the single public component with `trigger`,
404
+ `title`, `description`, `children`, `footer`, and optional `form`
405
+ props.
406
+ - **`Timeline pending` prop** — removed. The trailing "ongoing"
407
+ marker is now expressed as a regular item with
408
+ `{ animate: true, color: "primary", title: "…" }`. Per cardinal
409
+ rule 32 (no redundant props), a separate top-level prop was a
410
+ duplicate of the items-array shape.
411
+ - **`Timeline animate` Timeline-level prop** — removed. `animate`
412
+ is a per-item concept: set `items[i].animate = true` on the items
413
+ that should pulse. The previous Timeline-level prop animated only
414
+ the `current` item, which couldn't express trailing-pending
415
+ markers or multi-item indication.
416
+ - **`docs/reference/primitives` advisory drift** — 40 stubs landed,
417
+ parity now strict at 63/63.
418
+ - **`<Step color>` prop + `StepColor` type** — the prop was declared
419
+ but never read; per-step state is locked to the dxs-kintai canon
420
+ (`done` → `--success`, `cur` → `--primary`, future → `--muted-foreground`)
421
+ and not overridable. Consumers needing per-event colour should use
422
+ `<Timeline>` instead. No release migration needed — the prop had no
423
+ runtime effect.
424
+
425
+ ## [3.0.0] — 2026-05-16
426
+
427
+ `@godxjp/ui` v3 is a clean-break major that fulfils the **zero-config professional
428
+ framework** promise described in the umbrella's frontend-architecture spec. Services
429
+ upgrading from 2.x gain a complete toolchain preset and a fourth mandatory locale
430
+ (`fil`) with no API removals beyond the deprecated symbol renames below.
431
+
432
+ ### Added
433
+
434
+ - **Filipino (`fil`) locale** — `src/i18n/locales/fil.ts`. Full key parity with
435
+ `ja`. Mandatory per the umbrella frontend-architecture spec §6 (all four
436
+ locales: `ja`, `en`, `vi`, `fil`).
437
+ - **`GodxLocale` type** — replaces the Forge-branded `ForgeLocale`. Both are
438
+ exported; `ForgeLocale` is `@deprecated` but still resolves to the same type so
439
+ existing consumers compile without changes.
440
+ - **`GODX_LOCALE_STORAGE_KEY`** — replaces `FORGE_LOCALE_STORAGE_KEY`. Old name
441
+ re-exported as deprecated alias.
442
+ - **Zero-config toolchain presets** under `config/` — consumed via sub-path exports:
443
+ - `@godxjp/ui/eslint-config` → ESLint 9 flat config (typescript-eslint strict,
444
+ jsx-a11y, react-hooks rules). Service `eslint.config.js` = one line.
445
+ - `@godxjp/ui/prettier-config` → Prettier 3 config. Service `.prettierrc` = one
446
+ string.
447
+ - `@godxjp/ui/tsconfig` → TypeScript 6 strict base (`exactOptionalPropertyTypes`,
448
+ `noUncheckedIndexedAccess`, `verbatimModuleSyntax`).
449
+ - `@godxjp/ui/vitest-config` → Vitest 4 base with `jsdom` + 75%/70% coverage
450
+ thresholds.
451
+ - **Vitest test runner** added to devDependencies. `pnpm test` now works in the
452
+ package itself.
453
+ - **Locale parity smoke test** at `src/i18n/__tests__/locales.test.ts` — ensures
454
+ every key in `ja` is present in `en`, `vi`, and `fil` (test ID: GDXUI-I-LOCALE-001).
455
+ - **`ForgeProduct.tenant` type broadened** from a closed literal union to `string`
456
+ — makes the framework deployable by operators who define their own tenant slugs
457
+ without forking the package. The four built-in PRODUCTS fixtures remain unchanged.
458
+
459
+ ### Changed
460
+
461
+ - **package.json `description`** updated from Forge-specific wording to generic
462
+ professional framework copy.
463
+ - **`useTweaks` storage key** changed from `"forge.tweaks"` to `"godx.tweaks"`.
464
+ On first load after upgrade, the stored tweaks key is not found and falls back
465
+ to defaults (density/theme/tenant reset to defaults). User-visible tweaks
466
+ (density, theme, tenant) persist again on next save.
467
+ - **`initI18n` detection key** changed from `"forge.locale"` to `"godx.locale"`.
468
+ User locale preference is reset to browser/navigator default on first load after
469
+ upgrade. User re-selects locale via TweaksPanel and it persists under new key.
470
+ - **README** rewritten as professional framework intro (≥300 words) with import
471
+ surface table, primitives table with a11y column, adoption tracker, zero-config
472
+ quick start, and npm/license/types badges.
473
+ - **`sideEffects`** in `package.json` already `["**/*.css"]` — confirmed correct.
474
+ JS entries remain tree-shakable.
475
+
476
+ ### Deprecated
477
+
478
+ - `ForgeLocale` — use `GodxLocale`. Will be removed in v4.
479
+ - `FORGE_LOCALE_STORAGE_KEY` — use `GODX_LOCALE_STORAGE_KEY`. Will be removed in v4.
480
+
481
+ ### Migration guide (2.x → 3.0.0)
482
+
483
+ 1. **Locale storage key reset (non-breaking but visible):** The first page load
484
+ after upgrade will not find the old `"forge.tweaks"` key and will reset tweaks
485
+ to defaults. This is a one-time reset; the user re-selects density/theme/tenant
486
+ once and the new key persists.
487
+
488
+ 2. **`ForgeLocale` → `GodxLocale`:** No compile error — `ForgeLocale` still
489
+ exports. Update to `GodxLocale` at your own pace; it will be removed in v4.
490
+ Search and replace: `ForgeLocale` → `GodxLocale`.
491
+
492
+ 3. **`FORGE_LOCALE_STORAGE_KEY` → `GODX_LOCALE_STORAGE_KEY`:** Same pattern.
493
+ The old name still re-exports the same string constant.
494
+
495
+ 4. **Add `fil` locale to service `addResourceBundle` calls:** If your service
496
+ uses `i18n.addResourceBundle(locale, "my-ns", {…})` for all four locales,
497
+ add `fil`. Missing `addResourceBundle` calls for `fil` produce a silent fallback
498
+ to the base `fil` dictionary; no crash.
499
+
500
+ 5. **Zero-config toolchain (optional, strongly recommended):**
501
+ Adopt the new preset exports to reduce per-service boilerplate:
502
+
503
+ ```bash
504
+ # eslint.config.js — replace existing content with:
505
+ # export { default } from "@godxjp/ui/eslint-config"
506
+ #
507
+ # .prettierrc.json — replace with:
508
+ # "@godxjp/ui/prettier-config"
509
+ #
510
+ # tsconfig.json — extend:
511
+ # { "extends": "@godxjp/ui/tsconfig", "compilerOptions": { "paths": {...} } }
512
+ ```
513
+
514
+ 6. **`ForgeProduct.tenant` type:** If you were using the closed literal union
515
+ `"godx" | "kintai" | "tempo" | "betoya" | "restaurant"` for type narrowing,
516
+ the type is now `string`. Add your own type guard if needed:
517
+ ```ts
518
+ const KNOWN_TENANTS = ["godx", "kintai", "tempo", "betoya"] as const;
519
+ type KnownTenant = (typeof KNOWN_TENANTS)[number];
520
+ function isKnownTenant(t: string): t is KnownTenant {
521
+ return KNOWN_TENANTS.includes(t as KnownTenant);
522
+ }
523
+ ```
524
+
525
+ ## [2.4.0] — 2026-05-16
526
+
527
+ ### Added
528
+
529
+ - **Toaster** + **`toast`** — thin wrapper around `sonner` with token
530
+ class names (default `unstyled` so chrome comes from `.toast*` in
531
+ `tokens.css`). Optional **`@godxjp/ui/sonner.css`** import (after
532
+ tokens) pulls in sonner’s stacking / motion stylesheet and resets
533
+ toaster `font-family` to inherit.
534
+ - New `.combobox-*` atoms in `tokens.css` (filter list / item / empty
535
+ styles shared by `AutoComplete`, `Cascader`, `TreeSelect`).
536
+ - Dependency: **`sonner`** (`cmdk` already present).
537
+
538
+ ## [2.3.0] — 2026-05-16
539
+
540
+ ### Added
541
+
542
+ - **Dialog** family — Radix Dialog + `.dialog-*` in `tokens.css`.
543
+ - **Sheet** family (Radix Dialog; `Sheet` with `side` + `.sheet-*`
544
+ animation tokens).
545
+ - **AlertDialog** family (`AlertDialog*`, `AlertDialog` / `Cancel`
546
+ use `.btn` / `.btn-primary` / `.btn-secondary`).
547
+ - **Select** family (`Select*`, `SelectPortal`, scroll buttons, separator).
548
+ - **Switch**, **Checkbox** (Radix) with `.switch-*` / `.checkbox-*`.
549
+ - **Table** data display primitive using the `.table` atom.
550
+ - Dependencies: `@radix-ui/react-alert-dialog`, `@radix-ui/react-checkbox`.
551
+
552
+ ### Fixed
553
+
554
+ - Removed invalid `composes:` from `.popover-content` in `tokens.css`
555
+ (plain CSS does not support CSS-modules `composes`).
556
+
6
557
  ## [2.1.0] — 2026-05-13
7
558
 
8
559
  ### Added
9
- - **Popover** primitive (`Popover`, `PopoverTrigger`, `PopoverContent`,
10
- `PopoverAnchor`) wrapping `@radix-ui/react-popover`. Visual contract
560
+
561
+ - **Popover** primitive (`Popover`, `Popover`, `Popover`,
562
+ `Popover`) wrapping `@radix-ui/react-popover`. Visual contract
11
563
  in the new `.popover-content` class in `tokens.css` — brand-tokenised
12
564
  surface (`--popover`), border, and elevation.
13
- - **DropdownMenu** primitive (`DropdownMenu`, `DropdownMenuTrigger`,
14
- `DropdownMenuContent`, `DropdownMenuItem`, `DropdownMenuSeparator`,
15
- `DropdownMenuLabel`, `DropdownMenuShortcut`, `DropdownMenuGroup`,
16
- `DropdownMenuPortal`, `DropdownMenuSub`, `DropdownMenuRadioGroup`)
17
- wrapping `@radix-ui/react-dropdown-menu`. `<DropdownMenuItem>`
565
+ - **DropdownMenu** primitive (`DropdownMenu`, `DropdownMenu`,
566
+ `DropdownMenu`, `DropdownMenu`, `DropdownMenu`,
567
+ `DropdownMenu`, `DropdownMenu`, `DropdownMenu`,
568
+ `DropdownMenu`, `DropdownMenu`, `DropdownMenu`)
569
+ wrapping `@radix-ui/react-dropdown-menu`. `<DropdownMenu>`
18
570
  supports `variant="destructive"` + `inset` matching the public v0.2
19
571
  surface so call sites migrate by dep bump only.
20
572
  - **Calendar** primitive — `react-day-picker` themed via the new
@@ -29,6 +581,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
29
581
  - `react-day-picker` added as a dependency.
30
582
 
31
583
  ### Notes
584
+
32
585
  - This release fills the gap that blocked
33
586
  `services/forge-service/frontend/` from migrating off the public
34
587
  TempoFast `@godxjp/ui@0.2.0`. After 2.1.0 every primitive forge
@@ -57,6 +610,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
57
610
  ### Added
58
611
 
59
612
  ### Added
613
+
60
614
  - **BRAND.md** — the brand bible (locked 2026-05-13 from Claude Design
61
615
  handoff bundle). Spells out the 渋み / 間 / 簡素 design philosophy
62
616
  and lists the forbidden patterns reviewers reject.
@@ -65,14 +619,15 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
65
619
  - **`design/godx-admin-2026-05-13.tar.gz`** — original archive from
66
620
  `api.anthropic.com/v1/design/h/7Ya1OxEEfiaI2SWojzuP9A`. Kept so the
67
621
  brand can be re-extracted on any fresh checkout.
68
- - **Atomic primitives**: `Badge`, `Button`, `Card` (+ `CardHeader`,
69
- `CardTitle`, `CardSubtitle`, `CardContent`), `Input`, `Textarea`,
70
- `Label`, `Tabs` (+ `TabsList`, `TabsTrigger`, `TabsContent`),
622
+ - **Atomic primitives**: `Badge`, `Button`, `Card` (+ `Card header`,
623
+ `Card title`, `Card subtitle`, `Card content`), `Input`, `Textarea`,
624
+ `Label`, `Tabs` (+ `Tabs`, `Tabs`, `Tabs`),
71
625
  `Avatar`, `Separator`. Each maps onto a canonical CSS class from
72
626
  `tokens.css` — no Tailwind utility re-encoding.
73
627
  - **`./components/primitives` export path** for explicit imports.
74
628
 
75
629
  ### Changed
630
+
76
631
  - **`tokens.css` is now the single CSS entry point.** The handoff's
77
632
  `tokens.css` + `tokens-ext.css` were merged so consumers do one
78
633
  import (`@godxjp/ui/tokens`). The split is preserved verbatim under
@@ -85,6 +640,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
85
640
  consumers can `import { Badge, Button } from "@godxjp/ui"`.
86
641
 
87
642
  ### Removed
643
+
88
644
  - `src/tokens/tokens-ext.css` (merged into `tokens.css`).
89
645
  - `src/tokens/index.css` (no longer needed — `tokens.css` is the entry).
90
646