@godxjp/ui 19.3.1 → 19.4.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.
- package/dist/components/data-display/badge.d.ts +9 -1
- package/dist/components/data-display/badge.js +3 -2
- package/dist/components/data-display/index.d.ts +2 -0
- package/dist/components/data-display/index.js +2 -0
- package/dist/components/data-display/popover.d.ts +13 -1
- package/dist/components/data-display/popover.js +3 -1
- package/dist/components/data-display/table.d.ts +19 -2
- package/dist/components/data-display/table.js +4 -1
- package/dist/components/data-display/timeline-grid.d.ts +18 -0
- package/dist/components/data-display/timeline-grid.js +222 -0
- package/dist/components/data-entry/cascader.js +4 -6
- package/dist/components/data-entry/checkbox.js +1 -1
- package/dist/components/data-entry/search-select.js +5 -7
- package/dist/components/data-entry/select.js +32 -28
- package/dist/components/data-entry/tree-select.js +4 -6
- package/dist/components/general/inert-background.d.ts +5 -0
- package/dist/components/general/inert-background.js +48 -0
- package/dist/components/layout/auth-shell.d.ts +4 -2
- package/dist/components/layout/auth-shell.js +7 -1
- package/dist/components/layout/centered-shell.d.ts +2 -2
- package/dist/components/layout/flex.d.ts +1 -1
- package/dist/components/layout/flex.js +2 -1
- package/dist/components/layout/index.d.ts +3 -0
- package/dist/components/layout/index.js +2 -0
- package/dist/components/layout/mobile-shell.d.ts +21 -0
- package/dist/components/layout/mobile-shell.js +43 -0
- package/dist/components/layout/sidebar-link.d.ts +1 -1
- package/dist/components/navigation/context-menu.js +13 -9
- package/dist/components/navigation/dropdown-menu.js +17 -13
- package/dist/inertia/index.d.ts +1 -1
- package/dist/lib/variants.d.ts +3 -3
- package/dist/lib/variants.js +1 -0
- package/dist/props/components/data-display.prop.d.ts +65 -0
- package/dist/props/components/data-entry.prop.d.ts +1 -1
- package/dist/props/components/layout.prop.d.ts +93 -6
- package/dist/props/registry.d.ts +109 -2
- package/dist/props/registry.js +143 -0
- package/dist/props/vocabulary/data.prop.d.ts +6 -0
- package/dist/props/vocabulary/index.d.ts +3 -3
- package/dist/props/vocabulary/layout.prop.d.ts +17 -2
- package/dist/props/vocabulary/shared.prop.d.ts +7 -0
- package/dist/styles/control.css +18 -1
- package/dist/styles/data-display-layout.css +167 -0
- package/dist/styles/layout.css +7 -0
- package/dist/styles/shell-layout.css +148 -0
- package/dist/styles/table-layout.css +23 -4
- package/dist/tokens/components/control.css +1 -0
- package/dist/tokens/components/data-display.css +20 -0
- package/dist/tokens/components/shell.css +22 -0
- package/dist/tokens/components/table.css +2 -0
- package/docs/FRAME-A11Y-CI.md +99 -17
- package/docs/FRAME-COVERAGE-REPORT.md +4 -2
- package/docs/SPACING.md +19 -6
- package/docs/charts/compact-bar-trend.tsx +5 -6
- package/docs/data-display/avatar.tsx +7 -9
- package/docs/data-display/badge.tsx +1 -1
- package/docs/data-display/card/index.tsx +6 -4
- package/docs/data-display/data-table/examples/approval-queue.tsx +1 -1
- package/docs/data-display/data-table/index.tsx +1 -1
- package/docs/data-display/permission-matrix.tsx +2 -2
- package/docs/data-display/popover.tsx +4 -1
- package/docs/data-display/scroll-area.tsx +1 -1
- package/docs/data-display/table.tsx +1 -1
- package/docs/data-display/timeline-grid.tsx +119 -0
- package/docs/data-entry/branch-scope-picker.tsx +1 -1
- package/docs/data-entry/date-picker.tsx +2 -1
- package/docs/data-entry/form-field/index.tsx +2 -2
- package/docs/data-entry/input-otp.tsx +1 -1
- package/docs/data-entry/select-matrix.tsx +2 -1
- package/docs/data-entry/select.tsx +3 -1
- package/docs/data-entry/textarea.tsx +1 -1
- package/docs/data-entry/toggle-count.tsx +1 -1
- package/docs/feedback/alert.tsx +1 -1
- package/docs/feedback/banner.tsx +1 -1
- package/docs/feedback/dialog.tsx +2 -1
- package/docs/feedback/sheet.tsx +2 -1
- package/docs/foundation/email-tokens.tsx +1 -1
- package/docs/general/activity.tsx +1 -1
- package/docs/layout/app-shell.tsx +4 -4
- package/docs/layout/auth-account-summary.tsx +1 -1
- package/docs/layout/auth-recovery/examples/mobile-390.tsx +1 -1
- package/docs/layout/auth-recovery/examples/password-recovery.tsx +0 -2
- package/docs/layout/auth-shell-context.tsx +1 -1
- package/docs/layout/auth-shell-device.tsx +2 -2
- package/docs/layout/auth-shell-registration.tsx +1 -1
- package/docs/layout/auth-shell.tsx +1 -1
- package/docs/layout/master-detail.tsx +2 -2
- package/docs/layout/mobile-shell.tsx +101 -0
- package/docs/layout/page-container.tsx +6 -6
- package/docs/layout/responsive-grid.tsx +5 -5
- package/docs/layout/separator.tsx +2 -2
- package/docs/layout/service-role-panel.tsx +1 -1
- package/docs/layout/sidebar.tsx +9 -9
- package/docs/layout/split-pane.tsx +5 -6
- package/docs/layout/topbar.tsx +2 -8
- package/docs/navigation/context-menu.tsx +6 -1
- package/docs/navigation/dropdown-menu.tsx +2 -1
- package/docs/navigation/filter-bar.tsx +2 -2
- package/docs/navigation/pagination.tsx +2 -2
- package/docs/navigation/steps.tsx +1 -1
- package/docs/navigation/tabs.tsx +3 -3
- package/docs/showcase/acme-portal.tsx +11 -12
- package/docs/showcase/acme-website.tsx +7 -7
- package/docs/showcase/case1-warehouse-dashboard.tsx +11 -12
- package/docs/showcase/case2-employee-me.tsx +10 -16
- package/docs/showcase/case4-login.tsx +144 -156
- package/docs/showcase/case5-shift-calendar.tsx +181 -280
- package/docs/showcase/case6-agency-handy.tsx +446 -443
- package/docs/showcase/futurelastic-web.tsx +9 -8
- package/docs/showcase/org-switcher.tsx +18 -11
- package/docs/showcase/permission-matrix.tsx +13 -13
- package/docs/showcase/public-landing.tsx +1 -1
- package/docs/showcase/settings-account-sections.tsx +4 -4
- package/docs/showcase/settings-security-mfa.tsx +3 -3
- package/docs/showcase/table-approval-queue.tsx +1 -1
- package/docs/showcase/table-bulk-actions.tsx +49 -52
- package/docs/showcase/table-conditional-format.tsx +1 -1
- package/docs/showcase/table-crud-list.tsx +1 -1
- package/docs/showcase/table-expandable-rows.tsx +101 -98
- package/docs/showcase/table-filter-chips.tsx +78 -66
- package/docs/showcase/table-footer-totals.tsx +23 -19
- package/docs/showcase/table-grouped-subtotals.tsx +7 -4
- package/docs/showcase/table-master-detail.tsx +13 -15
- package/docs/showcase/table-states.tsx +34 -29
- package/docs/showcase/table-sticky-columns.tsx +3 -2
- package/docs/showcase/table-tree-rows.tsx +22 -15
- package/docs/showcase/table-view-tabs.tsx +12 -14
- package/package.json +7 -6
|
@@ -23,10 +23,12 @@ import { MoreHorizontal } from "lucide-react";
|
|
|
23
23
|
|
|
24
24
|
import coverTerrain from "../../assets/cover-terrain.svg";
|
|
25
25
|
|
|
26
|
-
/*
|
|
26
|
+
/*
|
|
27
|
+
* A committed SVG under docs/assets, imported so the bundler rewrites the URL against
|
|
27
28
|
* PREVIEW_BASE. It replaces a picsum.photos fetch that hung `networkidle` and timed this page out
|
|
28
|
-
* at 30s in CI
|
|
29
|
-
* unreadable characters in the middle of the example a consumer is meant to copy.
|
|
29
|
+
* at 30s in CI; it was briefly an inline data: URI, which fixed the hang but put 700
|
|
30
|
+
* unreadable characters in the middle of the example a consumer is meant to copy.
|
|
31
|
+
*/
|
|
30
32
|
|
|
31
33
|
/**
|
|
32
34
|
* Card — surface container. Body content ALWAYS goes in CardContent (a bare Card
|
|
@@ -131,7 +133,7 @@ export default function Demo() {
|
|
|
131
133
|
</ResponsiveGrid>
|
|
132
134
|
</Flex>
|
|
133
135
|
|
|
134
|
-
{/* accentPlacement="perimeter" — the semantic attention border
|
|
136
|
+
{/* accentPlacement="perimeter" — the semantic attention border */}
|
|
135
137
|
<Flex direction="col" gap="sm">
|
|
136
138
|
<Text as="div" weight="medium">
|
|
137
139
|
Accent · accentPlacement="perimeter" (全周のアテンションボーダー)
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
import { ClipboardCheck, LayoutDashboard, MoreHorizontal, ScrollText } from "lucide-react";
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* Access-approval queue (SCR-105 /
|
|
22
|
+
* Access-approval queue (SCR-105 / ) — the canonical five-column approval collection driven
|
|
23
23
|
* by the TanStack-powered DataTable, at 1440 · 1024 · 390 with ONLY public API.
|
|
24
24
|
*
|
|
25
25
|
* The whole responsive contract is two props: `preset="action-collection"` on the DataTable and a
|
|
@@ -230,7 +230,7 @@ export default function Demo() {
|
|
|
230
230
|
<DataTable data={[]} columns={columns} getRowId={(row) => row.id} />
|
|
231
231
|
</Flex>
|
|
232
232
|
|
|
233
|
-
{/*
|
|
233
|
+
{/* — the two failure states, in the same table grid as empty/loading. */}
|
|
234
234
|
<Flex direction="col" gap="sm">
|
|
235
235
|
<Text as="div" weight="medium">
|
|
236
236
|
エラー(error · role="alert" · onRetry で再試行を表示)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* PermissionMatrix — 権限マトリクス (canonical RBAC role × permission grid,
|
|
2
|
+
* PermissionMatrix — 権限マトリクス (canonical RBAC role × permission grid, ).
|
|
3
3
|
*
|
|
4
|
-
* A REAL export from `@godxjp/ui/data-display` (the
|
|
4
|
+
* A REAL export from `@godxjp/ui/data-display` (the lesson: a consumer cannot import a
|
|
5
5
|
* docs page). Read-only ✓/— by default; `onGrantChange` switches to editable checkbox cells with
|
|
6
6
|
* locked roles kept read-only; compare + 差分のみ come from `lib/permission-grid`; lifecycle
|
|
7
7
|
* states follow the DataTable #216 vocabulary. Domain data below is demo-only — the library
|
|
@@ -135,7 +135,10 @@ export default function Demo() {
|
|
|
135
135
|
<Flex direction="row" wrap gap="sm">
|
|
136
136
|
<Popover>
|
|
137
137
|
<PopoverTrigger asChild>
|
|
138
|
-
|
|
138
|
+
{/* data-axe-open: opened by check-frame-axe before its overlay scan. */}
|
|
139
|
+
<Button data-axe-open variant="outline">
|
|
140
|
+
side=top
|
|
141
|
+
</Button>
|
|
139
142
|
</PopoverTrigger>
|
|
140
143
|
<PopoverContent side="top" aria-label="上側の配置例">
|
|
141
144
|
<PopoverDescription>上に開きます。</PopoverDescription>
|
|
@@ -27,7 +27,7 @@ const entries = Array.from(
|
|
|
27
27
|
const shortEntries = entries.slice(0, 3);
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* The live-stream screen
|
|
30
|
+
* The live-stream screen. A deterministic clock: the demo never reads `Date.now()`, so the
|
|
31
31
|
* frame is stable, and every timestamp still goes through `Intl.DateTimeFormat` (IANA tz, 24h).
|
|
32
32
|
*/
|
|
33
33
|
const STREAM_EPOCH = Date.UTC(2026, 2, 3, 0, 30, 0);
|
|
@@ -131,7 +131,7 @@ export default function Demo() {
|
|
|
131
131
|
</CardContent>
|
|
132
132
|
</Card>
|
|
133
133
|
|
|
134
|
-
{/* ── The flush full-bleed FRAME contract
|
|
134
|
+
{/* ── The flush full-bleed FRAME contract ───────────────────────────
|
|
135
135
|
Four cards, side by side, so the whole rule is visible at once: which edges a
|
|
136
136
|
full-bleed table keeps inside a card, and who draws the line under the header. */}
|
|
137
137
|
<Card>
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Card,
|
|
3
|
+
CardContent,
|
|
4
|
+
CardDescription,
|
|
5
|
+
CardHeader,
|
|
6
|
+
CardTitle,
|
|
7
|
+
TimelineGrid,
|
|
8
|
+
type TimelineGridColumnProp,
|
|
9
|
+
type TimelineGridEventProp,
|
|
10
|
+
} from "@godxjp/ui/data-display";
|
|
11
|
+
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* TimelineGrid — a vertical hour axis, one column per day, and event blocks placed by start time
|
|
15
|
+
* and duration. It is the time-axis half of the Timeline family; Timeline itself is one lane of
|
|
16
|
+
* ordered events with no scale.
|
|
17
|
+
*/
|
|
18
|
+
const WEEK: TimelineGridColumnProp[] = [
|
|
19
|
+
{ id: "05-11", label: "月 11" },
|
|
20
|
+
{ id: "05-12", label: "火 12" },
|
|
21
|
+
{ id: "05-13", label: "水 13" },
|
|
22
|
+
{ id: "05-14", label: "木 14", description: "本日", current: true },
|
|
23
|
+
{ id: "05-15", label: "金 15" },
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
const SHIFTS: TimelineGridEventProp[] = [
|
|
27
|
+
{ id: "s1", columnId: "05-11", start: "09:00", end: "22:00", title: "通し", description: "佐藤" },
|
|
28
|
+
{ id: "s2", columnId: "05-12", start: "06:00", end: "22:00", title: "有給", description: "鈴木" },
|
|
29
|
+
{ id: "s3", columnId: "05-14", start: "09:00", end: "17:30", title: "早番", description: "田中" },
|
|
30
|
+
{ id: "s4", columnId: "05-14", start: "13:00", end: "22:00", title: "遅番", description: "高橋" },
|
|
31
|
+
// end at or before start = the shift runs into the next day (夜勤 22:00–06:00).
|
|
32
|
+
{ id: "s5", columnId: "05-14", start: "22:00", end: "06:00", title: "夜勤", description: "伊藤" },
|
|
33
|
+
{ id: "s6", columnId: "05-15", start: "09:00", end: "17:30", title: "早番", description: "佐藤" },
|
|
34
|
+
{ id: "s7", columnId: "05-15", start: "18:00", end: "21:00", title: "残業", description: "鈴木" },
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
// One column, a finer axis, and a colour carried by the record itself — the day view of the same
|
|
38
|
+
// data. `color` is decorative: the block still prints its hours and its title as text.
|
|
39
|
+
const ROOMS: TimelineGridColumnProp[] = [
|
|
40
|
+
{ id: "a", label: "会議室 A", description: "12名" },
|
|
41
|
+
{ id: "b", label: "会議室 B", description: "6名" },
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
const BOOKINGS: TimelineGridEventProp[] = [
|
|
45
|
+
{
|
|
46
|
+
id: "b1",
|
|
47
|
+
columnId: "a",
|
|
48
|
+
start: "09:30",
|
|
49
|
+
end: "10:30",
|
|
50
|
+
title: "定例会",
|
|
51
|
+
description: "営業部",
|
|
52
|
+
color: "var(--wa-gunjo)",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: "b2",
|
|
56
|
+
columnId: "a",
|
|
57
|
+
start: "10:00",
|
|
58
|
+
end: "11:00",
|
|
59
|
+
title: "面談",
|
|
60
|
+
description: "人事",
|
|
61
|
+
color: "var(--wa-akane)",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: "b3",
|
|
65
|
+
columnId: "b",
|
|
66
|
+
start: "13:00",
|
|
67
|
+
end: "14:30",
|
|
68
|
+
title: "設計レビュー",
|
|
69
|
+
description: "開発部",
|
|
70
|
+
color: "var(--wa-wakatake)",
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
export default function Demo() {
|
|
75
|
+
return (
|
|
76
|
+
<PageContainer title="TimelineGrid" subtitle="時間軸に沿って予定ブロックを置く週/日グリッド">
|
|
77
|
+
<Flex direction="col" gap="lg">
|
|
78
|
+
<Card>
|
|
79
|
+
<CardHeader>
|
|
80
|
+
<CardTitle level={2}>週シフト</CardTitle>
|
|
81
|
+
<CardDescription>
|
|
82
|
+
start / end で軸を 06:00–24:00 に固定し、interval=2
|
|
83
|
+
で2時間ごとに目盛りを引きます。木曜の早番と遅番は時間が重なるため、自動で横に並びます。
|
|
84
|
+
</CardDescription>
|
|
85
|
+
</CardHeader>
|
|
86
|
+
<CardContent flush>
|
|
87
|
+
<TimelineGrid
|
|
88
|
+
label="週シフト 2026年5月11日〜15日"
|
|
89
|
+
columns={WEEK}
|
|
90
|
+
events={SHIFTS}
|
|
91
|
+
start="06:00"
|
|
92
|
+
end="24:00"
|
|
93
|
+
interval={2}
|
|
94
|
+
now="14:35"
|
|
95
|
+
/>
|
|
96
|
+
</CardContent>
|
|
97
|
+
</Card>
|
|
98
|
+
|
|
99
|
+
<Card>
|
|
100
|
+
<CardHeader>
|
|
101
|
+
<CardTitle level={2}>会議室の予約</CardTitle>
|
|
102
|
+
<CardDescription>
|
|
103
|
+
start / end を省略すると、軸は予定の範囲から自動で決まります。onEventSelect
|
|
104
|
+
を渡すと各ブロックが button になり、キーボードでも選べます。
|
|
105
|
+
</CardDescription>
|
|
106
|
+
</CardHeader>
|
|
107
|
+
<CardContent flush>
|
|
108
|
+
<TimelineGrid
|
|
109
|
+
label="会議室の予約 5月14日"
|
|
110
|
+
columns={ROOMS}
|
|
111
|
+
events={BOOKINGS}
|
|
112
|
+
onEventSelect={() => {}}
|
|
113
|
+
/>
|
|
114
|
+
</CardContent>
|
|
115
|
+
</Card>
|
|
116
|
+
</Flex>
|
|
117
|
+
</PageContainer>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* BranchScopePicker — 適用範囲 (all branches vs an explicit subset
|
|
2
|
+
* BranchScopePicker — 適用範囲 (all branches vs an explicit subset).
|
|
3
3
|
*
|
|
4
4
|
* One controlled `{ mode, branchIds }` value; real RadioGroup + CheckboxGroup + SearchInput
|
|
5
5
|
* underneath. `error` is FIELD VALIDATION (aria-errormessage); a failed branch read is
|
|
@@ -33,7 +33,8 @@ export default function Demo() {
|
|
|
33
33
|
形式に整形され、 解釈できない入力は元の値へ復帰する。
|
|
34
34
|
</CardDescription>
|
|
35
35
|
</CardHeader>
|
|
36
|
-
|
|
36
|
+
{/* data-axe-open: check-frame-axe opens the calendar before scanning. */}
|
|
37
|
+
<CardContent data-axe-open>
|
|
37
38
|
<FormField id="issue-date" label="発行日" required>
|
|
38
39
|
<DatePicker
|
|
39
40
|
id="issue-date"
|
|
@@ -130,7 +130,7 @@ export default function Demo() {
|
|
|
130
130
|
|
|
131
131
|
<Card>
|
|
132
132
|
<CardHeader>
|
|
133
|
-
<CardTitle level={2}>Field identity · data-field
|
|
133
|
+
<CardTitle level={2}>Field identity · data-field</CardTitle>
|
|
134
134
|
<CardDescription>
|
|
135
135
|
項目キーを control の data-field に出す。既定は id から導出。id が DOM
|
|
136
136
|
一意化のためのもので項目キーと違う場合だけ field を明示する。AppProvider
|
|
@@ -176,7 +176,7 @@ export default function Demo() {
|
|
|
176
176
|
|
|
177
177
|
<Card>
|
|
178
178
|
<CardHeader>
|
|
179
|
-
<CardTitle level={2}>Static value · mixed with editable fields
|
|
179
|
+
<CardTitle level={2}>Static value · mixed with editable fields</CardTitle>
|
|
180
180
|
<CardDescription>
|
|
181
181
|
staticText renders a read-only VALUE as a FormField itself: Descriptions.Item's exact
|
|
182
182
|
value typography, no control, no id/aria-* wiring. An immutable name/email row and an
|
|
@@ -140,7 +140,7 @@ export default function Demo() {
|
|
|
140
140
|
</CardContent>
|
|
141
141
|
</Card>
|
|
142
142
|
|
|
143
|
-
{/*
|
|
143
|
+
{/* Align — the centred challenge, without a consumer wrapper div */}
|
|
144
144
|
<Card>
|
|
145
145
|
<CardHeader>
|
|
146
146
|
<CardTitle level={2}>中央寄せ(align="center")</CardTitle>
|
|
@@ -142,7 +142,8 @@ export default function Demo() {
|
|
|
142
142
|
references. The internal search textbox has its own visible-purpose accessible name.
|
|
143
143
|
</CardDescription>
|
|
144
144
|
</CardHeader>
|
|
145
|
-
|
|
145
|
+
{/* data-axe-open: check-frame-axe opens the searchable panel before scanning. */}
|
|
146
|
+
<CardContent data-axe-open>
|
|
146
147
|
<FormField
|
|
147
148
|
id="searchable-invalid"
|
|
148
149
|
label="担当拠点"
|
|
@@ -82,7 +82,9 @@ export default function Demo() {
|
|
|
82
82
|
Pass an options array; name= submits the value with the form.
|
|
83
83
|
</CardDescription>
|
|
84
84
|
</CardHeader>
|
|
85
|
-
|
|
85
|
+
{/* data-axe-open: check-frame-axe opens this Select before scanning, so the
|
|
86
|
+
overlay-open a11y state is measured. See docs/FRAME-A11Y-CI.md. */}
|
|
87
|
+
<CardContent data-axe-open>
|
|
86
88
|
<FormField id="status" label="状態">
|
|
87
89
|
<Select
|
|
88
90
|
id="status"
|
|
@@ -18,7 +18,7 @@ const SEED_MESSAGES: Message[] = [
|
|
|
18
18
|
];
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* The godx-chatter composer
|
|
21
|
+
* The godx-chatter composer. One line at rest, grows line by line, scrolls itself past
|
|
22
22
|
* eight rows, and collapses back to one line the moment the post is sent — the send button just
|
|
23
23
|
* resets the controlled value, and `autoGrow` follows it without a single line of layout code.
|
|
24
24
|
*/
|
|
@@ -14,7 +14,7 @@ import { Button, Text } from "@godxjp/ui/general";
|
|
|
14
14
|
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* Toggle `count` — the counted, PRESSED chip
|
|
17
|
+
* Toggle `count` — the counted, PRESSED chip.
|
|
18
18
|
*
|
|
19
19
|
* `Button` owns the counter-pill vocabulary (`count` / `overflowCount` / `showZero`) and `Toggle`
|
|
20
20
|
* owns the pressed state, so a faceted filter chip ("未対応 42", selected or not) and a reaction
|
package/docs/feedback/alert.tsx
CHANGED
|
@@ -139,7 +139,7 @@ export default function Demo() {
|
|
|
139
139
|
</CardContent>
|
|
140
140
|
</Card>
|
|
141
141
|
|
|
142
|
-
{/* Banner — the SAME component at the page measure
|
|
142
|
+
{/* Banner — the SAME component at the page measure. variant="banner" swaps only
|
|
143
143
|
the box: square, edge-to-edge, ruled on the block-end edge, measured by the --banner-*
|
|
144
144
|
tokens. Every tone, the icon, the actions grid and the dismiss ✕ are inherited from the
|
|
145
145
|
inline alert above, so there is nothing new to learn and nothing duplicated.
|
package/docs/feedback/banner.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import { Button } from "@godxjp/ui/general";
|
|
|
5
5
|
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Banner · full-bleed page/shell attention strip
|
|
8
|
+
* Banner · full-bleed page/shell attention strip — the Alert
|
|
9
9
|
* primitive with the structural axis fixed to variant="banner". Persistent,
|
|
10
10
|
* page/shell-scoped, at most one per surface. tone owns colour + icon +
|
|
11
11
|
* live-region politeness; onDismiss renders the built-in dismiss (last in focus
|
package/docs/feedback/dialog.tsx
CHANGED
|
@@ -109,7 +109,8 @@ export default function Demo() {
|
|
|
109
109
|
<CardContent>
|
|
110
110
|
<Dialog open={detailOpen} onOpenChange={setDetailOpen}>
|
|
111
111
|
<DialogTrigger asChild>
|
|
112
|
-
|
|
112
|
+
{/* data-axe-open: opened by check-frame-axe before its overlay scan. */}
|
|
113
|
+
<Button data-axe-open variant="outline" size="sm">
|
|
113
114
|
取引詳細を見る
|
|
114
115
|
</Button>
|
|
115
116
|
</DialogTrigger>
|
package/docs/feedback/sheet.tsx
CHANGED
|
@@ -213,7 +213,8 @@ export default function Demo() {
|
|
|
213
213
|
<CardContent>
|
|
214
214
|
<Sheet open={editOpen} onOpenChange={setEditOpen}>
|
|
215
215
|
<SheetTrigger asChild>
|
|
216
|
-
|
|
216
|
+
{/* data-axe-open: opened by check-frame-axe before its overlay scan. */}
|
|
217
|
+
<Button data-axe-open variant="ghost" size="sm">
|
|
217
218
|
取引先を編集
|
|
218
219
|
</Button>
|
|
219
220
|
</SheetTrigger>
|
|
@@ -25,7 +25,7 @@ import { Flex, PageContainer, ResponsiveGrid } from "@godxjp/ui/layout";
|
|
|
25
25
|
import { buildEmailSpecimenHtml } from "./_email-specimen";
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* Email tokens · the `@godxjp/ui/email` contract
|
|
28
|
+
* Email tokens · the `@godxjp/ui/email` contract.
|
|
29
29
|
*
|
|
30
30
|
* A transactional email is rendered by Blade/Twig/MJML, by clients that strip `<style>`, ignore
|
|
31
31
|
* CSS custom properties and block remote images — so neither the React components nor the CSS
|
|
@@ -12,7 +12,7 @@ import { Flex, PageContainer, Separator } from "@godxjp/ui/layout";
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Activity · the official AMBIENT-motion primitive: a continuous, unbounded "something is happening
|
|
15
|
-
* right now, elsewhere". The LOOP counterpart to `Reveal`'s one-shot entrance
|
|
15
|
+
* right now, elsewhere". The LOOP counterpart to `Reveal`'s one-shot entrance.
|
|
16
16
|
*
|
|
17
17
|
* Reads the DS motion tokens (`--activity-interval`, `--activity-stagger-step`,
|
|
18
18
|
* `--activity-mark-offset`, `--activity-color`, `--ease-standard`) so a consumer never hand-rolls a
|
|
@@ -282,8 +282,8 @@ export default function Demo() {
|
|
|
282
282
|
を切り替え、sidebar・topbar・page actions・grid・split pane
|
|
283
283
|
の変換を同じ実用構成で確認する。900px 以下ではドックされたサイドバーが隠れ、
|
|
284
284
|
AppShell 所有のモバイルドロワー(トップバー左のハンバーガー → フォーカストラップ付き
|
|
285
|
-
Sheet · Esc で閉じてトリガーへフォーカス復帰)が navigation
|
|
286
|
-
|
|
285
|
+
Sheet · Esc で閉じてトリガーへフォーカス復帰)が navigation を提供する。 このデモは
|
|
286
|
+
mobileNav を渡していないため、同じ Sidebar がドロワーに再利用される。
|
|
287
287
|
</CardDescription>
|
|
288
288
|
<CardDescription>
|
|
289
289
|
「トップバーなし(チャット型)」を押すと topbar / topbarLeft / topbarRight / logo の
|
|
@@ -297,8 +297,8 @@ export default function Demo() {
|
|
|
297
297
|
で代用しないこと ― それは 4 スロットが埋まった状態と同じで、バーの行は残る。
|
|
298
298
|
</CardDescription>
|
|
299
299
|
<CardDescription>
|
|
300
|
-
横方向のページ余白軸の持ち主は <code>--space-page-x</code>
|
|
301
|
-
|
|
300
|
+
横方向のページ余白軸の持ち主は <code>--space-page-x</code> ひとつ。 トップバーは{" "}
|
|
301
|
+
<code>.app-main</code> と同じグリッド列に載っている ―
|
|
302
302
|
つまりバー先頭のコントロールとページタイトルは同じ縦線に並ぶべきもので、
|
|
303
303
|
<code>--app-shell-bar-inset</code> はその持ち主を読む (
|
|
304
304
|
<code>--app-shell-bar-inset-compact</code> も同様に
|
|
@@ -8,7 +8,7 @@ import { AuthAccountSummary, AuthStack, PageContainer } from "@godxjp/ui/layout"
|
|
|
8
8
|
* the account address, and exactly one ghost action. Everything else is consumer data.
|
|
9
9
|
*
|
|
10
10
|
* The address CLIPS with an ellipsis, so it declares its own line box rather than inheriting one
|
|
11
|
-
|
|
11
|
+
*: a tight inherited line-height makes the clip box shorter than the font's ascent plus
|
|
12
12
|
* descent and shears Vietnamese tone marks and Latin descenders off, while the DOM text stays
|
|
13
13
|
* correct. The Vietnamese row below is the regression case for that.
|
|
14
14
|
*/
|
|
@@ -9,7 +9,7 @@ import { AppSettingPicker } from "@godxjp/ui/navigation";
|
|
|
9
9
|
/**
|
|
10
10
|
* Viewport fixture — 390x844 (mobile). THE MOBILE CONTRACT, decided here.
|
|
11
11
|
*
|
|
12
|
-
* ⚠️ The 390 canonical reference supplied with
|
|
12
|
+
* ⚠️ The 390 canonical reference supplied with is a desktop 2x2 COMPOSITE that overflows and
|
|
13
13
|
* crops horizontally. It is not a route-level mobile artboard and it was NOT traced. The behaviour
|
|
14
14
|
* below is a decided, documented contract — see the Overview page.
|
|
15
15
|
*
|
|
@@ -28,8 +28,6 @@ export default function Demo() {
|
|
|
28
28
|
const [password, setPassword] = useState("Godx-2026");
|
|
29
29
|
const [confirmation, setConfirmation] = useState("Godx-202");
|
|
30
30
|
|
|
31
|
-
// The address is masked by the SERVER before it reaches the panel — the library never
|
|
32
|
-
// reconstructs an identifier, it only renders the string the consumer sends.
|
|
33
31
|
const maskedEmail = "h*****@example.co.jp";
|
|
34
32
|
|
|
35
33
|
return (
|
|
@@ -16,7 +16,7 @@ import { AuthFooter, AuthIdentity, AuthShell, Flex } from "@godxjp/ui/layout";
|
|
|
16
16
|
import { AppSettingPicker } from "@godxjp/ui/navigation";
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* AuthShell preset="context-selection"
|
|
19
|
+
* AuthShell preset="context-selection" — the canonical organisation / context picker.
|
|
20
20
|
*
|
|
21
21
|
* The preset owns the whole page measure: a 25rem card at 1440/1024 and an edge-to-edge card at
|
|
22
22
|
* 390 (0 inline gutter), plus the vertical rhythm between the three direct sections of the auth
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
import { AppSettingPicker, Steps } from "@godxjp/ui/navigation";
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* AuthShell preset="device-authorization"
|
|
21
|
+
* AuthShell preset="device-authorization" — the canonical OAuth device-grant screen.
|
|
22
22
|
*
|
|
23
23
|
* The whole page measure is owned by the preset: a 380px card at 1440/1024 and a 5px inline page
|
|
24
24
|
* gutter at 390 (card x=5px, width=380px). Nothing here sets a width, an inset or a colour — a
|
|
@@ -28,7 +28,7 @@ import { AppSettingPicker, Steps } from "@godxjp/ui/navigation";
|
|
|
28
28
|
* `variant="canonical"` still owns control density + heading size; the preset only re-measures.
|
|
29
29
|
* Verify at 1440x900 · 1024x900 · 390x844.
|
|
30
30
|
*
|
|
31
|
-
*
|
|
31
|
+
* The preset also owns the CODE FIELD now: `--otp-slot-{inline,block}-size` come from
|
|
32
32
|
* `--auth-shell-device-otp-slot-*`, so each 4-slot grouped box measures the canonical 112x54
|
|
33
33
|
* instead of the 146x38 the square control tier produced. Nothing on this page sets it. The row is
|
|
34
34
|
* centred with `align="center"` (not a wrapper div) and the progress marker is the canonical
|
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
import { AppSettingPicker } from "@godxjp/ui/navigation";
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
* AuthShell preset="registration"
|
|
36
|
+
* AuthShell preset="registration" — the canonical sign-up measure.
|
|
37
37
|
*
|
|
38
38
|
* The preset owns the whole page geometry: a 360px (22.5rem) form measure at 1440/1024, a 15px
|
|
39
39
|
* inline gutter at 390 (card x=15, width=360 — the same page rhythm as preset="login", so
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
* SCR-001 Login visual contract. `?state=standalone|one-line|wrapped` drives the package visual
|
|
15
15
|
* test; all three keep the same card anchor without consumer CSS or fake requester data.
|
|
16
16
|
*
|
|
17
|
-
* The composition mirrors the documented consumer page exactly
|
|
17
|
+
* The composition mirrors the documented consumer page exactly: NO top brand bar (the
|
|
18
18
|
* canonical SCR-001 artboard has none — the in-flow AuthIdentity mark IS the brand), a header-less
|
|
19
19
|
* `<CardContent solo>` body, `AuthFooter` as the third direct child (the login preset's third grid
|
|
20
20
|
* row), and a plain 12px text-link row like the artboard's.
|
|
@@ -102,7 +102,7 @@ const COLLAPSE_STEPS = ["token", "sm", "md", "lg", "xl", "false"] as const;
|
|
|
102
102
|
const MASTER_VIEWPORTS = ["auto", "compact", "standard"] as const;
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
|
-
*
|
|
105
|
+
* 実サービスの「長い」コレクション。auto のままだと一覧が数千 px に伸び、
|
|
106
106
|
* 積み重なった 390px 画面では詳細がフォールドの遥か下に押し出される。
|
|
107
107
|
*/
|
|
108
108
|
const MEMBERS = Array.from({ length: 60 }, (_, i) => ({
|
|
@@ -339,7 +339,7 @@ export default function Demo() {
|
|
|
339
339
|
</Card>
|
|
340
340
|
</MasterDetail>
|
|
341
341
|
|
|
342
|
-
{/* ── 3. masterViewport —
|
|
342
|
+
{/* ── 3. masterViewport — 長い実コレクションを境界付きビューポートに収める。
|
|
343
343
|
auto: 一覧が 60 行ぶん伸び、390px では詳細がフォールドの遥か下に落ちる。
|
|
344
344
|
compact / standard: --master-detail-master-viewport-* が block サイズを
|
|
345
345
|
上限とし、コレクションは region の中でスクロールする。
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Inbox, Package, ScanLine, Truck } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
import { Badge, Card, CardContent } from "@godxjp/ui/data-display";
|
|
5
|
+
import { Button, Heading, Text } from "@godxjp/ui/general";
|
|
6
|
+
import { Flex, MobileShell } from "@godxjp/ui/layout";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* MobileShell — the handheld app shell: a status band, an app bar, ONE scroll region, a sticky
|
|
10
|
+
* action bar and a bottom tab bar. The two things a composed `Card` stack cannot do are exactly
|
|
11
|
+
* what the shell owns: the root is one screen tall so the DOCUMENT never scrolls (the tab bar can
|
|
12
|
+
* never slide away under a collapsing URL bar), and every band pads itself out of the device
|
|
13
|
+
* safe areas. Zero custom CSS — no `min-h-dvh`, no `position: sticky`, no page gutter by hand.
|
|
14
|
+
*/
|
|
15
|
+
const ITEMS = [
|
|
16
|
+
{ rc: "RC-204881", name: "洗顔フォーム", status: "未仕分け", tone: "warning" as const },
|
|
17
|
+
{ rc: "RC-204882", name: "日焼け止め", status: "棚上", tone: "info" as const },
|
|
18
|
+
{ rc: "RC-204879", name: "ビタミン B", status: "棚上", tone: "info" as const },
|
|
19
|
+
{ rc: "RC-204875", name: "歯ブラシ", status: "梱包済み", tone: "muted" as const },
|
|
20
|
+
{ rc: "RC-204871", name: "入浴剤", status: "棚上", tone: "info" as const },
|
|
21
|
+
{ rc: "RC-204864", name: "解熱鎮痛薬", status: "梱包済み", tone: "muted" as const },
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const TABS = [
|
|
25
|
+
{ id: "inbound", label: "入庫", icon: Inbox },
|
|
26
|
+
{ id: "packing", label: "梱包", icon: Package },
|
|
27
|
+
{ id: "outbound", label: "出庫", icon: Truck },
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
export default function Demo() {
|
|
31
|
+
const [tab, setTab] = React.useState("inbound");
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<MobileShell
|
|
35
|
+
statusBar={
|
|
36
|
+
<>
|
|
37
|
+
<Text size="sm" weight="medium" tabular>
|
|
38
|
+
9:41
|
|
39
|
+
</Text>
|
|
40
|
+
<Text size="sm" weight="medium" tone="muted" tabular>
|
|
41
|
+
Acme Handy
|
|
42
|
+
</Text>
|
|
43
|
+
</>
|
|
44
|
+
}
|
|
45
|
+
header={
|
|
46
|
+
<Flex align="center" justify="between" gap="xs" className="w-full">
|
|
47
|
+
<Heading level={3} as="h1">
|
|
48
|
+
入庫
|
|
49
|
+
</Heading>
|
|
50
|
+
<Button variant="ghost" size="sm">
|
|
51
|
+
選択
|
|
52
|
+
</Button>
|
|
53
|
+
</Flex>
|
|
54
|
+
}
|
|
55
|
+
actions={
|
|
56
|
+
<>
|
|
57
|
+
<Button className="flex-[2]">
|
|
58
|
+
<ScanLine aria-hidden="true" />
|
|
59
|
+
スキャン
|
|
60
|
+
</Button>
|
|
61
|
+
<Button variant="outline" className="flex-1">
|
|
62
|
+
手入力
|
|
63
|
+
</Button>
|
|
64
|
+
</>
|
|
65
|
+
}
|
|
66
|
+
tabBar={TABS.map((t) => {
|
|
67
|
+
const Icon = t.icon;
|
|
68
|
+
return (
|
|
69
|
+
<Button
|
|
70
|
+
key={t.id}
|
|
71
|
+
variant="ghost"
|
|
72
|
+
onClick={() => setTab(t.id)}
|
|
73
|
+
aria-current={t.id === tab ? "page" : undefined}
|
|
74
|
+
className="h-full flex-col rounded-none"
|
|
75
|
+
>
|
|
76
|
+
<Icon aria-hidden="true" />
|
|
77
|
+
<Text size="2xs">{t.label}</Text>
|
|
78
|
+
</Button>
|
|
79
|
+
);
|
|
80
|
+
})}
|
|
81
|
+
>
|
|
82
|
+
<Flex direction="col" gap="sm">
|
|
83
|
+
{ITEMS.map((item) => (
|
|
84
|
+
<Card key={item.rc} density="tight">
|
|
85
|
+
<CardContent solo>
|
|
86
|
+
<Flex align="center" justify="between" gap="sm">
|
|
87
|
+
<Flex direction="col" gap="none">
|
|
88
|
+
<Text weight="medium">{item.name}</Text>
|
|
89
|
+
<Text size="xs" mono tone="muted" tabular>
|
|
90
|
+
{item.rc}
|
|
91
|
+
</Text>
|
|
92
|
+
</Flex>
|
|
93
|
+
<Badge tone={item.tone}>{item.status}</Badge>
|
|
94
|
+
</Flex>
|
|
95
|
+
</CardContent>
|
|
96
|
+
</Card>
|
|
97
|
+
))}
|
|
98
|
+
</Flex>
|
|
99
|
+
</MobileShell>
|
|
100
|
+
);
|
|
101
|
+
}
|