@godxjp/ui 23.3.0 → 23.4.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 (79) hide show
  1. package/dist/components/data-display/card.d.ts +87 -1
  2. package/dist/components/data-display/card.js +88 -15
  3. package/dist/components/data-display/index.d.ts +5 -1
  4. package/dist/components/data-display/index.js +5 -0
  5. package/dist/components/data-display/thought-chain.d.ts +42 -0
  6. package/dist/components/data-display/thought-chain.js +177 -0
  7. package/dist/components/data-display/welcome.d.ts +26 -0
  8. package/dist/components/data-display/welcome.js +37 -0
  9. package/dist/components/data-entry/attachments.d.ts +19 -0
  10. package/dist/components/data-entry/attachments.js +322 -0
  11. package/dist/components/data-entry/index.d.ts +2 -0
  12. package/dist/components/data-entry/index.js +2 -0
  13. package/dist/components/feedback/dialog.d.ts +10 -7
  14. package/dist/components/feedback/dialog.js +40 -17
  15. package/dist/components/feedback/index.d.ts +1 -1
  16. package/dist/components/general/actions.d.ts +59 -0
  17. package/dist/components/general/actions.js +253 -0
  18. package/dist/components/general/activity.js +1 -0
  19. package/dist/components/general/float-button.d.ts +41 -0
  20. package/dist/components/general/float-button.js +336 -0
  21. package/dist/components/general/index.d.ts +6 -2
  22. package/dist/components/general/index.js +12 -1
  23. package/dist/components/general/typography.d.ts +79 -4
  24. package/dist/components/general/typography.js +598 -54
  25. package/dist/components/layout/draggable-panel.d.ts +18 -0
  26. package/dist/components/layout/draggable-panel.js +189 -0
  27. package/dist/components/layout/index.d.ts +2 -0
  28. package/dist/components/layout/index.js +2 -0
  29. package/dist/components/navigation/conversations.d.ts +39 -0
  30. package/dist/components/navigation/conversations.js +371 -0
  31. package/dist/components/navigation/index.d.ts +2 -0
  32. package/dist/components/navigation/index.js +2 -0
  33. package/dist/components/ui/card.js +1 -0
  34. package/dist/i18n/messages/en.json +53 -0
  35. package/dist/i18n/messages/ja.json +53 -0
  36. package/dist/i18n/messages/vi.json +53 -0
  37. package/dist/props/components/data-display.prop.d.ts +143 -1
  38. package/dist/props/components/data-entry.prop.d.ts +76 -0
  39. package/dist/props/components/feedback.prop.d.ts +34 -1
  40. package/dist/props/components/general.prop.d.ts +440 -3
  41. package/dist/props/components/index.d.ts +2 -2
  42. package/dist/props/components/layout.prop.d.ts +63 -1
  43. package/dist/props/components/navigation.prop.d.ts +150 -0
  44. package/dist/props/registry.d.ts +426 -0
  45. package/dist/props/registry.js +546 -0
  46. package/dist/props/vocabulary/index.d.ts +1 -1
  47. package/dist/props/vocabulary/interaction.prop.d.ts +113 -0
  48. package/dist/styles/card-layout.css +30 -0
  49. package/dist/styles/core.css +1 -0
  50. package/dist/styles/data-display-layout.css +236 -0
  51. package/dist/styles/float-button-layout.css +168 -0
  52. package/dist/styles/index.css +1 -0
  53. package/dist/styles/layout.css +196 -0
  54. package/dist/styles/navigation-layout.css +139 -0
  55. package/dist/styles/text-layout.css +156 -0
  56. package/dist/tokens/base.css +7 -0
  57. package/dist/tokens/components/actions.css +14 -0
  58. package/dist/tokens/components/attachments.css +15 -0
  59. package/dist/tokens/components/conversations.css +28 -0
  60. package/dist/tokens/components/draggable-panel.css +25 -0
  61. package/dist/tokens/components/float-button.css +39 -0
  62. package/dist/tokens/components/text.css +13 -0
  63. package/dist/tokens/components/thought-chain.css +31 -0
  64. package/dist/tokens/components/welcome.css +19 -0
  65. package/dist/tokens/foundation.css +2 -0
  66. package/docs/DESIGN-AUTHORITY.md +89 -0
  67. package/docs/FRAME-COVERAGE-REPORT.md +5 -2
  68. package/docs/data-display/card/examples/tab-list.tsx +97 -0
  69. package/docs/data-display/thought-chain.tsx +176 -0
  70. package/docs/data-display/welcome.tsx +115 -0
  71. package/docs/data-entry/attachments.tsx +160 -0
  72. package/docs/feedback/dialog.tsx +50 -0
  73. package/docs/general/actions.tsx +175 -0
  74. package/docs/general/float-button.tsx +133 -0
  75. package/docs/general/typography.tsx +63 -1
  76. package/docs/layout/draggable-panel.tsx +127 -0
  77. package/docs/navigation/conversations.tsx +176 -0
  78. package/docs/roadmap/parity-audit-layout-navigation-general.md +17 -16
  79. package/package.json +3 -3
@@ -181,6 +181,8 @@
181
181
  --heading-h3: var(--font-size-base);
182
182
  --heading-h4: var(--font-size-xs);
183
183
 
184
+ --heading-h5: var(--font-size-2xs);
185
+
184
186
  --font-weight-normal: 400;
185
187
  --font-weight-medium: 500;
186
188
 
@@ -248,6 +248,95 @@ in page CSS.
248
248
  replace the rendered markup. This library answers that layer with tokens (cardinal rule #45), so
249
249
  those are deliberately NOT adopted — adopting them would re-open the hole the token tiers close.
250
250
 
251
+ ## One `Dialog`, not two families — and the rule a consumer picks by
252
+
253
+ **Status:** accepted · 2026-09-12 · gh#567
254
+
255
+ ### The measurement that forced it
256
+
257
+ On `dist/components/feedback/dialog.d.ts` at `23.2.0`, the feedback group published **26** things:
258
+ **14** `Dialog*`, **12** `AlertDialog*`, **12 name-pairs**, **0** parts that only `AlertDialog`
259
+ had, and 2 that only `Dialog` had (`DialogBody`, `DialogClose`). `AlertDialog` carried no part of
260
+ its own; it was a full mirror minus two.
261
+
262
+ The real difference was two internal props on one shared shell — `role` and `isDismissable` — and
263
+ `AlertDialogRoot` is literally that shell with `role="alertdialog"` and `isDismissable={false}`.
264
+ Twelve exports were the price of publishing one ARIA attribute.
265
+
266
+ **A sweep of the whole public surface says this was the only place it happened.** Scanning the 270
267
+ callable exports in `component-api-manifest.json` for a prefixed mirror of another export
268
+ (`Alert*`, `Compact*`, `Simple*`, `Mini*`, `Basic*`, `Confirm*`, `Destructive*`) returns **11
269
+ pairs, all 11 of them this one family**. There is no second drifted pair to find.
270
+
271
+ ### Why antd wins here
272
+
273
+ antd has **one** `Modal`. Danger is a prop — `okType="danger"`, `okButtonProps`, with
274
+ `Modal.confirm()` as the flat preset alongside `info/success/error/warning`. antd has no
275
+ `AlertModal`. The split came from Radix, which ships `@radix-ui/react-dialog` and
276
+ `@radix-ui/react-alert-dialog` as two packages — and this library no longer runs on Radix.
277
+ react-aria-components has a single `Dialog` whose `role` is an ordinary prop, so the shape that
278
+ made two families necessary is gone from the implementation as well as from the authority.
279
+
280
+ ### The decision
281
+
282
+ `Dialog` takes **`variant`** (`"default" | "destructive"`), on the root or on `DialogContent`, and
283
+ that one prop decides three things that always travel together in practice:
284
+
285
+ | `variant` | ARIA role | outside click | primary action |
286
+ | --------------------- | ------------- | ------------- | --------------------------------------------- |
287
+ | `"default"` (default) | `dialog` | dismisses | default emphasis |
288
+ | `"destructive"` | `alertdialog` | ignored | destructive emphasis (antd `okType="danger"`) |
289
+
290
+ The 12 `AlertDialog*` exports **stay and keep working unchanged**. Deleting them is a breaking
291
+ change and belongs in a major; nothing here retints or re-roles an existing tree, because the new
292
+ prop defaults to `"default"` and no existing `AlertDialog*` call site passes it.
293
+
294
+ ### The rule for choosing — answer these in order
295
+
296
+ 1. **Is it dangerous or irreversible?** No → plain `Dialog`, no `variant`. Yes → keep going.
297
+ 2. **Does the flat preset cover it?** Title, description, confirm/cancel labels, an optional typed
298
+ challenge, an optional step-up re-auth, a pending state, and nothing else in the body → use the
299
+ `AlertDialog` **preset**. It is one element and it already forces the destructive tone.
300
+ 3. **Does the body need anything else** — a required reason field, a summary table, a diff, a
301
+ nested list? → `Dialog` with `variant="destructive"`. You get `role="alertdialog"` and the
302
+ non-dismissable scrim, plus `DialogBody` and `DialogClose`, which the `AlertDialog*` family
303
+ never had.
304
+ 4. **Are you writing new code with the `AlertDialog*` compound parts?** Don't. They are the legacy
305
+ spelling of step 3. Existing code stays valid.
306
+
307
+ That third row is the reported case: a destructive confirmation with a **required free-text reason**
308
+ that still has to be announced as an alert dialog. Before this, `Dialog` gave the form and lost the
309
+ role, `AlertDialog` gave the role and forced the footer to be rebuilt, and either way it was a
310
+ rewrite rather than a prop.
311
+
312
+ ### Four places this deliberately departs from the issue's proposal
313
+
314
+ 1. **The prop is `variant`, not `severity`.** antd has no name for a one-knob-three-effects switch,
315
+ so there is nothing to port verbatim. But the axis already exists here as `ConfirmVariantProp`
316
+ and the `AlertDialog` preset already spells it `variant` — and "this library's controlled
317
+ vocabulary wins on values" is the rule two sections up. `check:prop-vocabulary` maps a field
318
+ named `variant` to a `*VariantProp` type for exactly this reason.
319
+ 2. **Escape still closes a `destructive` dialog.** The issue wanted the prop to govern Escape too.
320
+ It does not, because Escape-closes-an-alertdialog is the behaviour the 12 existing exports have
321
+ today, with a test measuring it (`dialog-alert-primitives.test.tsx` · "closes on Escape and
322
+ restores focus"). Making the new prop disable Escape would make `variant="destructive"` differ
323
+ from `AlertDialogContent`, which is the one thing it must not do. antd agrees: `keyboard`
324
+ defaults to `true`. The prop governs the outside click; `maskClosable` is antd's name for that
325
+ same switch.
326
+ 3. **The corner ✕ defaults off under `destructive`.** It is a fourth effect, and it follows from
327
+ the second: a ✕ is an accidental-dismiss affordance like the scrim. It keeps
328
+ `DialogContent variant="destructive"` byte-identical to `AlertDialogContent`, and
329
+ `showCloseButton` still overrides it either way.
330
+ 4. **The header band tone is NOT forced.** `DialogHeader tone` is a separate published axis with
331
+ seven values; the preset is where a destructive tone is imposed on both the band and the button
332
+ at once. Forcing it from `variant` would put two props on the same pixel.
333
+
334
+ ### And the `Sheet` question in the same issue
335
+
336
+ Asked, measured, no change. antd keeps `Drawer` and `Modal` as two components and splits them by
337
+ **where the surface comes from**, not by danger — which is exactly the `Sheet` / `Dialog` boundary
338
+ here. That pair never drifted from the authority, so there is nothing to merge.
339
+
251
340
  ## Derived colour is AUTHORED, and MEASUREMENT is what makes it authoritative
252
341
 
253
342
  **Twenty values, in `src/tokens/derived.css`:** `--primary-hover`, `--primary-active`,
@@ -3,8 +3,8 @@
3
3
  > Generated by `scripts/frame-coverage.mjs` (issue #163). Do not edit by hand — run `pnpm check:frame-coverage`.
4
4
  > Standard: [FRAME-COVERAGE-STANDARD.md](./FRAME-COVERAGE-STANDARD.md). A missing dimension is **UNTESTED**, never a pass.
5
5
 
6
- - Public components: **150**
7
- - With ≥1 frame: **134** · zero-frame: **16**
6
+ - Public components: **152**
7
+ - With ≥1 frame: **135** · zero-frame: **17**
8
8
  - Fully covered (every contract axis declared): **0**
9
9
 
10
10
  ## UNTESTED — no `/frame/**` route
@@ -22,6 +22,7 @@
22
22
  - [ ] `SkeletonAvatar`
23
23
  - [ ] `SkeletonButton`
24
24
  - [ ] `SkeletonInput`
25
+ - [ ] `SkeletonForm`
25
26
  - [ ] `SkeletonNode`
26
27
  - [ ] `SkeletonImage`
27
28
  - [ ] `ChatBubbleList`
@@ -57,6 +58,7 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
57
58
  | ErrorSurface | ✓ | ✓ | N/A | N/A | · | · | · | · | · | · |
58
59
  | LegalDocumentShell | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
59
60
  | Breadcrumb | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
61
+ | FloatButton | ✓ | · | · | · | · | · | · | · | · | · |
60
62
  | Button | ✓ | ✓ | · | · | · | · | · | · | · | · |
61
63
  | Text | ✓ | ✓ | N/A | N/A | · | · | · | · | · | · |
62
64
  | Heading | ✓ | ✓ | N/A | N/A | · | · | · | · | · | · |
@@ -141,6 +143,7 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
141
143
  | SkeletonAvatar | **✗** | ✓ | N/A | N/A | · | · | · | · | · | · |
142
144
  | SkeletonButton | **✗** | ✓ | N/A | N/A | · | · | · | · | · | · |
143
145
  | SkeletonInput | **✗** | ✓ | N/A | N/A | · | · | · | · | · | · |
146
+ | SkeletonForm | **✗** | N/A | N/A | N/A | · | · | · | · | · | · |
144
147
  | SkeletonNode | **✗** | N/A | N/A | N/A | · | · | · | · | · | · |
145
148
  | SkeletonImage | **✗** | N/A | N/A | N/A | · | · | · | · | · | · |
146
149
  | Toggle | ✓ | ✓ | · | N/A | · | · | · | · | · | · |
@@ -0,0 +1,97 @@
1
+ import { useState } from "react";
2
+
3
+ import {
4
+ Badge,
5
+ Card,
6
+ CardContent,
7
+ CardFooter,
8
+ CardHeader,
9
+ CardTitle,
10
+ DataTable,
11
+ Descriptions,
12
+ type CardTabItemProp,
13
+ } from "@godxjp/ui/data-display";
14
+ import { Button, Text } from "@godxjp/ui/general";
15
+ import { Flex, PageContainer } from "@godxjp/ui/layout";
16
+
17
+ /**
18
+ * Card `tabList` — Ant Design's card-head tab strip.
19
+ *
20
+ * The strip lives INSIDE the card's head: under the title, on the same surface, inside the same
21
+ * border, so the card and its tabs read as one object. The card's children are the selected tab's
22
+ * body — here a `DataTable` in a `CardContent flush`, which is what lets the table reach the card
23
+ * edge instead of sitting in a second, narrower frame.
24
+ *
25
+ * What NOT to reach for instead: a `Tabs` parked on the page above a card (the strip floats off
26
+ * the card and the two read as two objects), or a `Card` repeated inside every tab (the same
27
+ * header and body shell copied once per view).
28
+ */
29
+ const tabList: CardTabItemProp[] = [
30
+ { key: "members", tab: "メンバー" },
31
+ { key: "invitations", tab: "招待" },
32
+ { key: "settings", tab: "設定" },
33
+ ];
34
+
35
+ const members = [
36
+ { id: "1", name: "佐藤 花子", email: "sato@example.co.jp", role: "管理者" },
37
+ { id: "2", name: "鈴木 一郎", email: "suzuki@example.co.jp", role: "編集者" },
38
+ { id: "3", name: "高橋 美咲", email: "takahashi@example.co.jp", role: "閲覧者" },
39
+ ];
40
+
41
+ const invitations = [{ id: "4", name: "田中 健", email: "tanaka@example.co.jp", role: "編集者" }];
42
+
43
+ export default function Demo() {
44
+ const [activeTabKey, setActiveTabKey] = useState("members");
45
+
46
+ return (
47
+ <PageContainer title="組織設定" subtitle="株式会社ベトヤ">
48
+ <Card
49
+ tabList={tabList}
50
+ activeTabKey={activeTabKey}
51
+ onTabChange={setActiveTabKey}
52
+ extra={<Button size="sm">メンバーを招待</Button>}
53
+ >
54
+ <CardHeader>
55
+ <CardTitle level={2}>チーム</CardTitle>
56
+ </CardHeader>
57
+
58
+ {activeTabKey === "settings" ? (
59
+ <CardContent>
60
+ <Descriptions>
61
+ <Descriptions.Item label="組織名">株式会社ベトヤ</Descriptions.Item>
62
+ <Descriptions.Item label="ドメイン">example.co.jp</Descriptions.Item>
63
+ <Descriptions.Item label="既定の権限">閲覧者</Descriptions.Item>
64
+ </Descriptions>
65
+ </CardContent>
66
+ ) : (
67
+ <CardContent flush>
68
+ <DataTable
69
+ data={activeTabKey === "members" ? members : invitations}
70
+ getRowId={(row) => row.id}
71
+ columns={[
72
+ { key: "name", header: "名前" },
73
+ { key: "email", header: "メール" },
74
+ {
75
+ key: "role",
76
+ header: "権限",
77
+ render: (row) => <Badge tone="info">{row.role}</Badge>,
78
+ },
79
+ ]}
80
+ />
81
+ </CardContent>
82
+ )}
83
+
84
+ <CardFooter separated>
85
+ <Flex direction="row" justify="between" align="center" gap="sm">
86
+ <Text tone="muted" size="sm">
87
+ {activeTabKey === "invitations" ? "1件の保留中の招待" : "3名のメンバー"}
88
+ </Text>
89
+ <Button variant="outline" size="sm">
90
+ CSV で書き出す
91
+ </Button>
92
+ </Flex>
93
+ </CardFooter>
94
+ </Card>
95
+ </PageContainer>
96
+ );
97
+ }
@@ -0,0 +1,176 @@
1
+ import { useState } from "react";
2
+
3
+ import { ChatBubble, ThoughtChain, ThoughtChainItem } from "@godxjp/ui/data-display";
4
+ import { Text } from "@godxjp/ui/general";
5
+ import {
6
+ AppShell,
7
+ Flex,
8
+ PageContainer,
9
+ Sidebar,
10
+ type SidebarSectionProp,
11
+ Topbar,
12
+ } from "@godxjp/ui/layout";
13
+ import { Bot, MessageSquare, Search, Settings, Users } from "lucide-react";
14
+
15
+ /**
16
+ * ThoughtChain — the assistant's reasoning, step by step (Ant Design X `ThoughtChain`).
17
+ *
18
+ * Each card is one axis at rest: the chain as it appears above an answer, the four statuses, the
19
+ * three connector strokes, and the standalone `ThoughtChainItem` chip in its three variants.
20
+ *
21
+ * The step that collapses is a real disclosure button, so this page is drivable from the keyboard
22
+ * alone; Ant X's own step is a `<div onClick>`.
23
+ *
24
+ * Composed only from real @godxjp/ui components.
25
+ */
26
+ const sections: SidebarSectionProp[] = [
27
+ {
28
+ label: "アシスタント",
29
+ items: [
30
+ { id: "chat", label: "チャット", icon: MessageSquare },
31
+ { id: "agents", label: "エージェント", icon: Bot },
32
+ { id: "members", label: "メンバー", icon: Users },
33
+ ],
34
+ },
35
+ { label: "管理", items: [{ id: "settings", label: "設定", icon: Settings }] },
36
+ ];
37
+
38
+ export default function ThoughtChainDoc() {
39
+ const [open, setOpen] = useState<string[]>(["search"]);
40
+
41
+ return (
42
+ <AppShell
43
+ sidebar={
44
+ <Sidebar
45
+ activeId="chat"
46
+ sections={sections}
47
+ onSelect={() => {}}
48
+ product={{ name: "CoreDesk", role: "アシスタント", color: "hsl(var(--primary))" }}
49
+ />
50
+ }
51
+ topbar={<Topbar />}
52
+ >
53
+ <PageContainer
54
+ title="思考の手順"
55
+ subtitle="ThoughtChain · 回答の前に何をしたのか。畳める手順は本物の開閉ボタン。"
56
+ >
57
+ {/* IN PLACE: above the answer it explains. */}
58
+ <Flex direction="col" gap="sm">
59
+ <Text size="sm" weight="medium">
60
+ in place · 回答の前
61
+ </Text>
62
+ <ThoughtChain
63
+ label="思考の手順"
64
+ expandedKeys={open}
65
+ onExpand={setOpen}
66
+ items={[
67
+ {
68
+ key: "read",
69
+ title: "添付の請求書を読む",
70
+ description: "3件",
71
+ status: "success",
72
+ },
73
+ {
74
+ key: "search",
75
+ title: "社内規程を検索",
76
+ description: "「支払期日」",
77
+ status: "success",
78
+ collapsible: true,
79
+ content: (
80
+ <Text size="xs" tone="muted">
81
+ 第4章 支払 — 請求書の支払期日は受領月の翌月末日とする。
82
+ </Text>
83
+ ),
84
+ },
85
+ {
86
+ key: "write",
87
+ title: "差分をまとめる",
88
+ status: "loading",
89
+ blink: true,
90
+ },
91
+ ]}
92
+ />
93
+ <ChatBubble placement="start" variant="filled">
94
+ 差分は3件でした。金額、支払期日、宛名のうちどれから直しますか。
95
+ </ChatBubble>
96
+ </Flex>
97
+
98
+ {/* THE FOUR STATUSES. */}
99
+ <Flex direction="col" gap="sm">
100
+ <Text size="sm" weight="medium">
101
+ status · loading · success · error · abort
102
+ </Text>
103
+ <Text size="xs" tone="muted">
104
+ 状態は字にもなる。読み上げでは各手順のあとに「完了」「失敗」などが続く。
105
+ </Text>
106
+ <ThoughtChain
107
+ label="状態の一覧"
108
+ items={[
109
+ { key: "a", title: "実行中の手順", status: "loading" },
110
+ { key: "b", title: "終わった手順", status: "success" },
111
+ { key: "c", title: "失敗した手順", status: "error" },
112
+ { key: "d", title: "中断した手順", status: "abort" },
113
+ ]}
114
+ />
115
+ </Flex>
116
+
117
+ {/* THE CONNECTOR. */}
118
+ <Flex direction="col" gap="sm">
119
+ <Text size="sm" weight="medium">
120
+ line · solid · dashed · none
121
+ </Text>
122
+ <ThoughtChain
123
+ label="実線"
124
+ line="solid"
125
+ items={[
126
+ { key: "a", title: "一歩目" },
127
+ { key: "b", title: "二歩目" },
128
+ ]}
129
+ />
130
+ <ThoughtChain
131
+ label="破線"
132
+ line="dashed"
133
+ items={[
134
+ { key: "a", title: "一歩目" },
135
+ { key: "b", title: "二歩目" },
136
+ ]}
137
+ />
138
+ <ThoughtChain
139
+ label="線なし"
140
+ line={false}
141
+ items={[
142
+ { key: "a", title: "一歩目" },
143
+ { key: "b", title: "二歩目" },
144
+ ]}
145
+ />
146
+ </Flex>
147
+
148
+ {/* THE STANDALONE CHIP. */}
149
+ <Flex direction="col" gap="sm">
150
+ <Text size="sm" weight="medium">
151
+ ThoughtChainItem · solid · outlined · text
152
+ </Text>
153
+ <Text size="xs" tone="muted">
154
+ 押せる手順は本物のボタンとして描かれる。押せないものは div のまま。要素が実体に従う。
155
+ </Text>
156
+ <Flex gap="sm">
157
+ <ThoughtChainItem
158
+ variant="solid"
159
+ icon={<Search />}
160
+ title="社内規程を検索"
161
+ description="3件ヒット"
162
+ status="success"
163
+ />
164
+ <ThoughtChainItem variant="outlined" icon={<Search />} title="再検索" />
165
+ <ThoughtChainItem
166
+ variant="text"
167
+ icon={<Search />}
168
+ title="詳細を見る"
169
+ onClick={() => setOpen(["search"])}
170
+ />
171
+ </Flex>
172
+ </Flex>
173
+ </PageContainer>
174
+ </AppShell>
175
+ );
176
+ }
@@ -0,0 +1,115 @@
1
+ import { useState } from "react";
2
+
3
+ import { Welcome } from "@godxjp/ui/data-display";
4
+ import { Button, Text } from "@godxjp/ui/general";
5
+ import {
6
+ AppShell,
7
+ Flex,
8
+ PageContainer,
9
+ Sidebar,
10
+ type SidebarSectionProp,
11
+ Topbar,
12
+ } from "@godxjp/ui/layout";
13
+ import { Bot, MessageSquare, Settings, Sparkles, Users } from "lucide-react";
14
+
15
+ /**
16
+ * Welcome — the greeting block at the head of an empty conversation (Ant Design X `Welcome`).
17
+ *
18
+ * It is the first thing an assistant says, so every slot on this page is one Ant X slot at rest:
19
+ * the full block, the two variants, the block with no glyph, and the `icon`-as-URL rule that Ant
20
+ * ports from a string beginning with `http`.
21
+ *
22
+ * Composed only from real @godxjp/ui components.
23
+ */
24
+ const sections: SidebarSectionProp[] = [
25
+ {
26
+ label: "アシスタント",
27
+ items: [
28
+ { id: "chat", label: "チャット", icon: MessageSquare },
29
+ { id: "agents", label: "エージェント", icon: Bot },
30
+ { id: "members", label: "メンバー", icon: Users },
31
+ ],
32
+ },
33
+ { label: "管理", items: [{ id: "settings", label: "設定", icon: Settings }] },
34
+ ];
35
+
36
+ export default function WelcomeDoc() {
37
+ const [dismissed, setDismissed] = useState(false);
38
+
39
+ return (
40
+ <AppShell
41
+ sidebar={
42
+ <Sidebar
43
+ activeId="chat"
44
+ sections={sections}
45
+ onSelect={() => {}}
46
+ product={{ name: "CoreDesk", role: "アシスタント", color: "hsl(var(--primary))" }}
47
+ />
48
+ }
49
+ topbar={<Topbar />}
50
+ >
51
+ <PageContainer
52
+ title="あいさつ"
53
+ subtitle="Welcome · 会話がまだ一件もない画面の先頭に置く四つのスロット"
54
+ >
55
+ {/* THE WHOLE BLOCK. `extra` sits on the title row, which is the placement a hand-roll
56
+ usually gets wrong (it lands under the description instead). */}
57
+ <Flex direction="col" gap="sm">
58
+ <Text size="sm" weight="medium">
59
+ icon · title · description · extra
60
+ </Text>
61
+ {dismissed ? (
62
+ <Text size="xs" tone="muted">
63
+ 閉じました。
64
+ </Text>
65
+ ) : (
66
+ <Welcome
67
+ icon={<Sparkles />}
68
+ title="こんにちは、何からはじめますか"
69
+ description="請求、経費、勤怠のことならお手伝いできます。左の履歴から続きを開くこともできます。"
70
+ extra={
71
+ <Button variant="ghost" size="sm" onClick={() => setDismissed(true)}>
72
+ 閉じる
73
+ </Button>
74
+ }
75
+ />
76
+ )}
77
+ </Flex>
78
+
79
+ {/* THE TWO VARIANTS, side by side. */}
80
+ <Flex direction="col" gap="sm">
81
+ <Text size="sm" weight="medium">
82
+ variant · filled と borderless
83
+ </Text>
84
+ <Welcome
85
+ variant="filled"
86
+ icon={<Bot />}
87
+ title="filled"
88
+ description="自分の地色と髪の毛一本分の境界を持つ。カードの中に置いても沈まない。"
89
+ />
90
+ <Welcome
91
+ variant="borderless"
92
+ icon={<Bot />}
93
+ title="borderless"
94
+ description="ページの地の上にそのまま置く。上下に他の要素が続くときはこちら。"
95
+ />
96
+ </Flex>
97
+
98
+ {/* NO GLYPH, AND AN IMAGE GLYPH. */}
99
+ <Flex direction="col" gap="sm">
100
+ <Text size="sm" weight="medium">
101
+ icon · 省略と URL
102
+ </Text>
103
+ <Welcome
104
+ title="アイコンなし"
105
+ description="スロットを渡さなければ、その列自体が出ない。"
106
+ />
107
+ <Text size="xs" tone="muted">
108
+ http で始まる文字列は装飾画像として描かれる(Ant Design X と同じ規則、ただし alt
109
+ は空)。
110
+ </Text>
111
+ </Flex>
112
+ </PageContainer>
113
+ </AppShell>
114
+ );
115
+ }