@godxjp/ui 20.2.0 → 21.0.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 (60) hide show
  1. package/dist/components/data-display/chat-bubble.d.ts +30 -0
  2. package/dist/components/data-display/chat-bubble.js +229 -0
  3. package/dist/components/data-display/descriptions.js +4 -1
  4. package/dist/components/data-display/index.d.ts +4 -2
  5. package/dist/components/data-display/index.js +5 -2
  6. package/dist/components/data-display/popover.js +3 -2
  7. package/dist/components/data-display/scroll-area.js +26 -1
  8. package/dist/components/data-display/tree.d.ts +8 -0
  9. package/dist/components/data-display/tree.js +426 -0
  10. package/dist/components/data-entry/chat-composer.d.ts +50 -0
  11. package/dist/components/data-entry/chat-composer.js +163 -0
  12. package/dist/components/data-entry/chat-suggestion.d.ts +28 -0
  13. package/dist/components/data-entry/chat-suggestion.js +285 -0
  14. package/dist/components/data-entry/index.d.ts +4 -0
  15. package/dist/components/data-entry/index.js +4 -0
  16. package/dist/components/data-entry/textarea.js +3 -1
  17. package/dist/components/data-entry/tree-utils.d.ts +10 -48
  18. package/dist/components/data-entry/tree-utils.js +1 -154
  19. package/dist/components/layout/org-switcher.js +22 -2
  20. package/dist/i18n/messages/en.json +50 -0
  21. package/dist/i18n/messages/ja.json +48 -0
  22. package/dist/i18n/messages/vi.json +49 -0
  23. package/dist/lib/tree.d.ts +53 -0
  24. package/dist/lib/tree.js +155 -0
  25. package/dist/props/components/data-display.prop.d.ts +187 -1
  26. package/dist/props/components/data-entry.prop.d.ts +127 -0
  27. package/dist/props/registry.d.ts +140 -3
  28. package/dist/props/registry.js +202 -3
  29. package/dist/styles/control.css +7 -0
  30. package/dist/styles/data-display-layout.css +309 -55
  31. package/dist/styles/data-entry-layout.css +64 -0
  32. package/dist/styles/shell-layout.css +41 -11
  33. package/dist/tokens/base.css +3 -0
  34. package/dist/tokens/components/chat-bubble.css +36 -0
  35. package/dist/tokens/components/chat-composer.css +19 -0
  36. package/dist/tokens/components/data-display.css +0 -6
  37. package/dist/tokens/components/descriptions.css +4 -0
  38. package/dist/tokens/components/shell.css +13 -3
  39. package/dist/tokens/components/tree.css +27 -0
  40. package/docs/FRAME-COVERAGE-LEDGER.md +1 -1
  41. package/docs/FRAME-COVERAGE-REPORT.md +8 -3
  42. package/docs/data-display/chat-bubble.tsx +397 -0
  43. package/docs/data-display/timeline.tsx +46 -0
  44. package/docs/data-display/tree.tsx +394 -0
  45. package/docs/data-entry/chat-composer.tsx +464 -0
  46. package/docs/data-entry/chat-suggestion.tsx +301 -0
  47. package/docs/roadmap/ai-chat-components.md +207 -0
  48. package/docs/roadmap/antd-parity.md +154 -0
  49. package/docs/roadmap/badge-tag-chip-count.md +172 -0
  50. package/docs/roadmap/list-masonry.md +159 -0
  51. package/docs/roadmap/parity-audit-data-display-feedback.md +567 -0
  52. package/docs/roadmap/parity-audit-data-entry.md +344 -0
  53. package/docs/roadmap/parity-audit-layout-navigation-general.md +464 -0
  54. package/docs/roadmap/parity-backlog.md +79 -0
  55. package/docs/roadmap/tree-components.md +151 -0
  56. package/docs/showcase/table-tree-rows.tsx +4 -4
  57. package/package.json +5 -3
  58. package/dist/components/data-display/tree-list.d.ts +0 -13
  59. package/dist/components/data-display/tree-list.js +0 -26
  60. package/docs/data-display/tree-list.tsx +0 -107
@@ -0,0 +1,151 @@
1
+ # Tree components — audit + normalized spec
2
+
3
+ > **Status:** audit complete 2026-09-10. `Tree` is NOT implemented. Read this before touching
4
+ > anything under `src/components/**/tree-*`.
5
+ > **Contract:** `.claude/skills/godxjp-ui-component/SKILL.md` is the hard gate. This document only
6
+ > normalizes *what* to build; the skill owns *how*.
7
+
8
+ ## 1. What exists today (measured, not eyeballed)
9
+
10
+ | Thing | File | What it actually is |
11
+ | --- | --- | --- |
12
+ | `TreeSelect` | `src/components/data-entry/tree-select.tsx` (499 L) | A real tree, but only **inside a dropdown**. Ant-aligned API. |
13
+ | `TreeList` | `src/components/data-display/tree-list.tsx` (41 L) | **Not a tree.** A flat `<ul>` where `depth` is a number that only drives `margin-inline-start`. |
14
+ | `tree-utils` | `src/components/data-entry/tree-utils.ts` (216 L) | Normalize / flatten / filter / descendants. Sound, reusable. Currently private to `data-entry`. |
15
+ | `Tree` | — | **Does not exist.** |
16
+
17
+ ### 1a. `TreeSelect` is fine — leave it alone
18
+
19
+ It is genuinely modeled on Ant Design: `treeData`, `fieldNames`, `treeCheckable`, `treeCheckStrictly`,
20
+ `showCheckedStrategy` (`SHOW_PARENT` / `SHOW_CHILD` / `SHOW_ALL`), `loadData`, `treeTitleRender`,
21
+ `maxTagCount`, `notFoundContent`. Markup carries `role="tree"` / `role="treeitem"` with
22
+ `aria-expanded` / `aria-selected` / `aria-multiselectable`. It is not the problem.
23
+
24
+ ### 1b. `TreeList` is the problem — it promises a tree and delivers indentation
25
+
26
+ Verified against the source, the CSS (`src/styles/data-display-layout.css:282-334`) and its tests:
27
+
28
+ | Gap | Evidence |
29
+ | --- | --- |
30
+ | No nested data model | `items: TreeListItem[]` only — the caller must pre-flatten; there is no `children`. |
31
+ | No expand / collapse | No disclosure control anywhere in the component. NameThatUI calls this the **disclosure triangle**; an indented tree that expands is an **Outline View**. `TreeList` has neither. |
32
+ | No ARIA tree semantics | Only `aria-current`. No `role="tree"` / `role="treeitem"` / `aria-expanded` / `aria-level` / `aria-setsize` / `aria-posinset` / `aria-selected`. **Violates the mandatory WAI-ARIA APG gate.** |
33
+ | No keyboard | No arrows, Home/End, `*`, type-ahead. Rows are not focusable at all. |
34
+ | No selection contract | No `value` / `defaultValue` / `onValueChange`. **Violates the controlled-vocabulary rule (§2d).** |
35
+ | No `size`, no `ref`, no `className`/`...props` | Props are literally `{ items }`. **Violates §2d.** |
36
+ | Depth is uncapped but unstyled past 2 | Its own docs page says "Indentation is defined for depth 0-2, so flatten deeper branches". `tree-list-depth.test.tsx` asserts depth `5` sets the CSS var — which then renders at an indent nobody designed. |
37
+ | Missing every Ant affordance | no icons, no `showLine`, no drag & drop, no virtual scroll, no async `loadData`, no search/filter highlight, no `blockNode`, no DirectoryTree. |
38
+
39
+ **Conclusion:** the "tree components don't look like Ant Design" complaint is correct, and it is
40
+ localized: `TreeSelect` is fine, `TreeList` is a cosmetic indented list, and the standalone `Tree`
41
+ that every Ant-shaped app reaches for was never built.
42
+
43
+ ## 2. GATE 0 ledger — `Tree` (required before any `src/components/**` addition)
44
+
45
+ | # | Criterion | Verdict | Why |
46
+ | --- | --- | --- | --- |
47
+ | C1 | Universal, not design-specific | **PASS** | File explorers, org charts, category pickers, permission trees, nav outlines. |
48
+ | C2 | Encapsulates reusable behavior | **PASS** | Roving tabindex, arrow/Home/End/`*` navigation, type-ahead, expand state, tri-state check propagation, async load. |
49
+ | C3 | Not composable from existing primitives | **PASS** | `Accordion` is single-level disclosure; `Timeline`/`NavList`/`ListRow` are flat. No primitive owns tree keyboard navigation on a page. |
50
+ | C4 | Single responsibility + controlled-vocabulary API | **PASS** | One job (render + navigate a hierarchy); maps cleanly onto the triads in §3. |
51
+ | C5 | Fully token-themeable | **PASS** | Indent, rail, glyph, row height all become `--tree-*` component tokens. |
52
+ | C6 | Earns the international contract | **PASS** | Needs correct APG semantics and RTL indentation; used everywhere. |
53
+ | C7 | Earns its bundle cost | **PASS** | Broad; also lets `TreeSelect` and `Tree` share one node renderer. |
54
+
55
+ **ALL PASS → `Tree` is a framework component.**
56
+
57
+ ## 3. Normalized API — Ant Design name → godx controlled vocabulary
58
+
59
+ `Tree` mirrors Ant Design's *capabilities*, never its *prop names* where they conflict with
60
+ `docs/PROPS-VOCABULARY.md`. This mapping is the contract; do not invent a third spelling.
61
+
62
+ | Capability | Ant Design | **godx `Tree`** |
63
+ | --- | --- | --- |
64
+ | Data | `treeData` | `treeData: TreeOptionProp[]` (reuse the existing `TreeOptionProp` + `TreeFieldNamesProp`) |
65
+ | Field remap | `fieldNames` | `fieldNames` (unchanged — already in the registry) |
66
+ | Selection | `selectedKeys` / `defaultSelectedKeys` / `onSelect` | `value` / `defaultValue` / `onValueChange` |
67
+ | Multi-select | `multiple` | `multiple` |
68
+ | Checkboxes | `checkedKeys` / `onCheck` | `checkedValues` / `defaultCheckedValues` / `onCheckedValuesChange` |
69
+ | Checkbox mode | `checkable` | `checkable` |
70
+ | Independent checks | `checkStrictly` | `checkStrictly` |
71
+ | Expansion | `expandedKeys` / `onExpand` | `expandedValues` / `defaultExpandedValues` / `onExpandedValuesChange` |
72
+ | Expand all | `defaultExpandAll` | `defaultExpandAll` |
73
+ | Async children | `loadData` | `loadData` (same signature as `TreeSelect`'s) |
74
+ | Node label render | `titleRender` | `titleRender` |
75
+ | Connector lines | `showLine` | `showLine` |
76
+ | Node icons | `showIcon` / `icon` | `showIcon`, per-node `icon` |
77
+ | Full-width row | `blockNode` | *dropped* — always full-width row; that is the only correct hit area under WCAG 2.5.8 |
78
+ | Disclosure glyph | `switcherIcon` | *dropped* — the glyph is a token (`--tree-switcher-*`), not a prop |
79
+ | Density | — | `size: xs \| sm \| lg` (`md` is the default, never `"default"`) |
80
+ | Directory variant | `<DirectoryTree>` | `variant="directory"` |
81
+ | Drag & drop | `draggable` | **out of scope for v1** — file a follow-up issue |
82
+ | Virtual scroll | `virtual` / `height` | **out of scope for v1** — cap with `ScrollArea`; file a follow-up issue |
83
+
84
+ Plus the house rules: forward `ref`, spread `...props`, accept `className` + `id`, export
85
+ `TreeProp` and `TreeProp as TreeProps` from `src/props/components/data-display.prop.ts`, and
86
+ **register it in `src/props/registry.ts`**.
87
+
88
+ ## 4. Required semantics (WAI-ARIA APG "Tree View")
89
+
90
+ - Container `role="tree"`, `aria-multiselectable` when `multiple` or `checkable`.
91
+ - Each node `role="treeitem"` with `aria-level` (1-based), `aria-setsize`, `aria-posinset`,
92
+ `aria-selected`, and `aria-expanded` **only on nodes that have children**.
93
+ - Grouping wrapper `role="group"`.
94
+ - **Roving tabindex** — exactly one node has `tabIndex={0}`; all others `-1`.
95
+ - Keyboard: `↓`/`↑` next/previous *visible* node · `→` expand, then move to first child ·
96
+ `←` collapse, then move to parent · `Home`/`End` first/last visible · `Enter`/`Space` select
97
+ (or toggle the checkbox when `checkable`) · `*` expand all siblings at the current level ·
98
+ type-ahead jumps to the next node whose label starts with the typed characters.
99
+ - Under `dir="rtl"`, `→`/`←` swap meaning and indentation flips — logical CSS only
100
+ (`margin-inline-start`, `padding-inline-start`), never `ml-`/`pl-`/`left-`.
101
+ - Tri-state parent checkbox: checked / unchecked / **indeterminate** when only some descendants
102
+ are checked (skip propagation entirely when `checkStrictly`).
103
+ - Ships `tree.a11y.test.tsx` with `expectNoA11yViolations` — 0 violations.
104
+
105
+ ## 5. Tokens (tier: `src/tokens/components/tree.css`, `@import`ed from `src/tokens/base.css`)
106
+
107
+ Names must pass `pnpm check:token-tiers` (`--{component}-{part}-{property}`):
108
+ `--tree-node-height` (from the `--control-height` tier — never a literal), `--tree-indent-width`,
109
+ `--tree-switcher-size`, `--tree-switcher-color`, `--tree-line-color`, `--tree-node-selected-background`,
110
+ `--tree-node-hover-background`, `--tree-icon-size`. Row hit area ≥ 24×24px (WCAG 2.5.8).
111
+
112
+ ## 6. i18n keys (`src/i18n/messages/{en,vi,ja}.json`)
113
+
114
+ `tree.expand`, `tree.collapse`, `tree.loading`, `tree.empty`, `tree.selected` (sr-only status —
115
+ selection must never be colour-only, WCAG 1.4.1). Every `aria-label` goes through `t()`.
116
+
117
+ ## 7. `TreeList` — what happened to it
118
+
119
+ **Superseded here, then REMOVED in 21.0.0.** The plan above ("stays exported, it has consumers")
120
+ was written while it still had them. It stopped: the last two call sites in `godx-task`
121
+ (`pages/tests/show.tsx`, `pages/documents/index.tsx`) moved to `Tree`, and a sweep of all four
122
+ consumer repos (godx-task, godx-chat, ql, platform) found none left. A superseded export that
123
+ nobody calls is not a compatibility surface, it is a second answer to a question that already has
124
+ one — and the catalog blurb it shipped with promised a "chevron + package icon" the component
125
+ never rendered.
126
+
127
+ So it is gone, with no deprecated shim: component, types, barrel entries, tests, frame, catalog
128
+ entry, `--tree-item-*` tokens and `.ui-tree-item` CSS. `Tree` is the replacement, and the Tree
129
+ catalog entry carries the migration (`id`->`value`, `title`->`label`, `depth`->nesting).
130
+ `check-mcp-pattern-imports.mjs` now denylists an import of, or JSX for, the removed export, the
131
+ same way it denylists `Stack`/`Inline`.
132
+
133
+ ## 8. Shared code
134
+
135
+ Move `src/components/data-entry/tree-utils.ts` to a location both groups can import
136
+ (`src/lib/tree.ts`), re-export from the old path so `TreeSelect` keeps working, and have `Tree`
137
+ consume the same `normalizeTreeOptions` / `flattenVisibleTree` / `getDescendantValues`.
138
+ **One tree model, two surfaces** — do not fork the traversal logic.
139
+
140
+ ## 9. Definition of done
141
+
142
+ Cheap gates, then this component's tests only:
143
+
144
+ ```
145
+ pnpm typecheck && pnpm lint && pnpm run audit \
146
+ && pnpm check:prop-vocabulary && pnpm check:mcp-sync && pnpm check:mcp-orphans \
147
+ && pnpm check:token-tiers && pnpm check:control-sizing && pnpm check:example-imports
148
+ pnpm vitest run src/components/data-display/__tests__ --maxWorkers=2
149
+ ```
150
+
151
+ `pnpm test` / bare `pnpm vitest run` are **forbidden** — the full suite is CI's job.
@@ -3,10 +3,10 @@
3
3
  *
4
4
  * Tree / hierarchical rows inside the real @godxjp/ui DataTable.
5
5
  *
6
- * The lib's `TreeList` is a flat presentational list (fixed icons, no twirl, no
7
- * tabular columns) — it cannot express a *tabular* hierarchy with per-row metrics,
8
- * a parent-only disclosure twirl, and DataTable chrome (sticky header, density,
9
- * sortable columns). So this composes the behaviour from real primitives:
6
+ * The lib's `Tree` owns the standalone tree view, but it is single-column — it
7
+ * cannot express a *tabular* hierarchy with per-row metrics, a parent-only
8
+ * disclosure twirl, and DataTable chrome (sticky header, density, sortable
9
+ * columns). So this composes the behaviour from real primitives:
10
10
  *
11
11
  * row model ........ flatten an org tree to rows carrying { depth, hasChildren,
12
12
  * expanded }, then derive `visibleRows` from the open set.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@godxjp/ui",
3
- "version": "20.2.0",
4
- "godxUiMcp": "20.2.0",
3
+ "version": "21.0.0",
4
+ "godxUiMcp": "21.0.0",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -351,9 +351,11 @@
351
351
  "check:display-runtime-evidence": "node scripts/check-display-runtime-evidence.mjs",
352
352
  "check:data-table-pagination-wrap": "node scripts/check-data-table-pagination-wrap.mjs",
353
353
  "check:button-icon-xs": "node scripts/check-button-icon-xs.mjs",
354
+ "check:timeline-title-fill": "node scripts/check-timeline-title-fill.mjs",
355
+ "check:descriptions-label-value-step": "node scripts/check-descriptions-label-value-step.mjs",
354
356
  "check:frame-contracts": "pnpm check:component-api-manifest && pnpm audit:component-cases && pnpm check:frame-coverage && pnpm check:frame-coverage-ledger && pnpm check:screen-reader-evidence && pnpm check:data-entry-owner-source && pnpm check:display-runtime-evidence",
355
357
  "check:final-touch-rtl": "node scripts/check-final-touch-rtl.mjs",
356
- "check:frame-runtime": "pnpm check:data-entry-frame-runtime && pnpm check:data-entry-touch-aria && pnpm check:layout-nav-frames && pnpm check:provider-feedback-query-runtime && pnpm check:layout-nav-closure && pnpm check:final-touch-rtl && pnpm check:data-table-pagination-wrap && pnpm check:button-icon-xs",
358
+ "check:frame-runtime": "pnpm check:data-entry-frame-runtime && pnpm check:data-entry-touch-aria && pnpm check:layout-nav-frames && pnpm check:provider-feedback-query-runtime && pnpm check:layout-nav-closure && pnpm check:final-touch-rtl && pnpm check:data-table-pagination-wrap && pnpm check:button-icon-xs && pnpm check:timeline-title-fill && pnpm check:descriptions-label-value-step",
357
359
  "verify": "pnpm typecheck && pnpm lint && pnpm format && pnpm build && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:no-external-assets && pnpm check:token-scale-bypass && pnpm check:dist-tokens-resolve && pnpm check:no-hardcoded-geometry && pnpm check:no-hardcoded-css-values && pnpm check:no-inline-magic-numbers && pnpm check:no-tailwind-class-assertions && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-lockstep && pnpm check:mcp-sync && pnpm check:doc-prop-existence && pnpm check:mcp-catalog-coverage && pnpm check:mcp-orphans && pnpm check:mcp-pattern-imports && pnpm check:audit-sync && pnpm check:frame-coverage && pnpm test",
358
360
  "verify:static": "pnpm build && pnpm check:packed-public-contract && pnpm typecheck && pnpm typecheck:docs && pnpm lint && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:use-client && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:token-scale-bypass && pnpm check:dist-tokens-resolve && pnpm check:no-hardcoded-geometry && pnpm check:no-hardcoded-css-values && pnpm check:no-inline-magic-numbers && pnpm check:no-tailwind-class-assertions && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-lockstep && pnpm check:mcp-sync && pnpm check:doc-prop-existence && pnpm check:mcp-catalog-coverage && pnpm check:mcp-orphans && pnpm check:mcp-pattern-imports && pnpm check:audit-sync && pnpm check:mcp-prop-sync && pnpm check:contrast && pnpm check:visual-audit && pnpm test",
359
361
  "verify:ci": "pnpm verify:ci:static && pnpm check:frame-contracts && pnpm test",
@@ -1,13 +0,0 @@
1
- import type { ReactNode } from "react";
2
- export type TreeListItem = {
3
- id: string;
4
- title: ReactNode;
5
- description?: ReactNode;
6
- depth?: number;
7
- active?: boolean;
8
- badge?: ReactNode;
9
- };
10
- export type TreeListProps = {
11
- items: TreeListItem[];
12
- };
13
- export declare function TreeList({ items }: TreeListProps): import("react").JSX.Element;
@@ -1,26 +0,0 @@
1
- "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { Badge } from "./badge.js";
4
- function TreeList({ items }) {
5
- return /* @__PURE__ */ jsx("ul", { className: "ui-tree-list", children: items.map((item) => /* @__PURE__ */ jsxs(
6
- "li",
7
- {
8
- className: "ui-tree-item",
9
- "data-active": item.active ? "true" : void 0,
10
- "data-depth": Math.max(0, item.depth ?? 0),
11
- style: { "--tree-item-depth": Math.max(0, item.depth ?? 0) },
12
- "aria-current": item.active ? "true" : void 0,
13
- children: [
14
- /* @__PURE__ */ jsxs("div", { className: "ui-tree-item-body", children: [
15
- /* @__PURE__ */ jsx("div", { className: "ui-tree-item-title", children: item.title }),
16
- item.description ? /* @__PURE__ */ jsx("div", { className: "ui-tree-item-description", children: item.description }) : null
17
- ] }),
18
- item.badge != null ? /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: item.badge }) : null
19
- ]
20
- },
21
- item.id
22
- )) });
23
- }
24
- export {
25
- TreeList
26
- };
@@ -1,107 +0,0 @@
1
- import {
2
- Badge,
3
- Card,
4
- CardContent,
5
- CardDescription,
6
- CardHeader,
7
- CardTitle,
8
- EmptyState,
9
- TreeList,
10
- } from "@godxjp/ui/data-display";
11
- import { Flex, PageContainer } from "@godxjp/ui/layout";
12
- import { FolderTree } from "lucide-react";
13
-
14
- /**
15
- * TreeList — a flat array rendered as an indented hierarchy; depth is data-driven
16
- * (never nest DOM). active highlights a row (aria-current); badge surfaces a
17
- * secondary label. Indentation is defined for depth 0-2, so flatten deeper
18
- * branches before rendering. Composed only from real @godxjp/ui components.
19
- */
20
- const accounts = [
21
- { id: "1000", title: "資産", depth: 0, badge: "親科目" },
22
- { id: "1100", title: "流動資産", depth: 1, description: "1年以内に現金化" },
23
- {
24
- id: "1110",
25
- title: "現金及び預金",
26
- description: "普通・当座・小口",
27
- depth: 2,
28
- badge: "3 口座",
29
- active: true,
30
- },
31
- {
32
- id: "1120",
33
- title: "売掛金",
34
- description: "得意先への未回収債権",
35
- depth: 2,
36
- badge: (
37
- <Badge variant="outline" tone="warning">
38
- 要確認
39
- </Badge>
40
- ),
41
- },
42
- { id: "2000", title: "負債", depth: 0, badge: "親科目" },
43
- { id: "2100", title: "流動負債", depth: 1, description: "1年以内に支払" },
44
- { id: "2110", title: "買掛金", depth: 2, badge: "12 件" },
45
- ];
46
-
47
- // Independent data: active is allowed on any depth, including a top-level parent.
48
- const departments = [
49
- { id: "d0", title: "本社", depth: 0, active: true, badge: "選択中" },
50
- { id: "d1", title: "営業部", depth: 1, description: "首都圏・関西" },
51
- { id: "d2", title: "開発部", depth: 1, description: "プロダクト・基盤" },
52
- ];
53
-
54
- export default function Demo() {
55
- return (
56
- <PageContainer
57
- title="TreeList"
58
- subtitle="Hierarchical list · depth lives in the data, not the DOM"
59
- >
60
- <Flex direction="col" gap="lg">
61
- <Card>
62
- <CardHeader>
63
- <CardTitle level={2}>勘定科目ツリー</CardTitle>
64
- <CardDescription>
65
- Pre-filter server-side; each item still carries its depth (0-2). An active leaf
66
- carries aria-current; badges accept a string or a nested Badge node.
67
- </CardDescription>
68
- </CardHeader>
69
- <CardContent>
70
- <TreeList items={accounts} />
71
- </CardContent>
72
- </Card>
73
-
74
- <Card>
75
- <CardHeader>
76
- <CardTitle level={2}>組織ツリー(親を選択中)</CardTitle>
77
- <CardDescription>
78
- active is data-driven and works at any depth. Here the depth-0 parent is the current
79
- row.
80
- </CardDescription>
81
- </CardHeader>
82
- <CardContent>
83
- <TreeList items={departments} />
84
- </CardContent>
85
- </Card>
86
-
87
- <Card>
88
- <CardHeader>
89
- <CardTitle level={2}>空の状態</CardTitle>
90
- <CardDescription>
91
- An empty items={"{[]}"} array renders an empty list. Pair it with an EmptyState
92
- placeholder.
93
- </CardDescription>
94
- </CardHeader>
95
- <CardContent>
96
- <TreeList items={[]} />
97
- <EmptyState
98
- icon={FolderTree}
99
- title="科目がありません"
100
- description="フィルター条件に一致する勘定科目が見つかりませんでした。"
101
- />
102
- </CardContent>
103
- </Card>
104
- </Flex>
105
- </PageContainer>
106
- );
107
- }