@godxjp/ui 19.3.1 → 19.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.
- 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/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/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/input-otp.tsx +1 -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/foundation/email-tokens.tsx +1 -1
- package/docs/general/activity.tsx +1 -1
- 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 +2 -2
- package/docs/layout/separator.tsx +2 -2
- package/docs/layout/service-role-panel.tsx +1 -1
- package/docs/layout/sidebar.tsx +6 -6
- package/docs/layout/split-pane.tsx +1 -1
- package/docs/layout/topbar.tsx +2 -8
- 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 +1 -1
- 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 +2 -2
- 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 +12 -14
- 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
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
|
|
@@ -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
|
|
@@ -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
|
+
}
|
|
@@ -47,7 +47,7 @@ const TOOLBAR_CHROME_TOKENS = {
|
|
|
47
47
|
} as CSSProperties;
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
-
* `--page-header-min-block-size-chrome` ·
|
|
50
|
+
* `--page-header-min-block-size-chrome` · クロム帯の「高さ」。文書のヘッダーは中身なりの
|
|
51
51
|
* 高さで正しい · 見出しは見出しの高さだからです。クロムは逆で、家具には「ものが中央に収まる帯」が
|
|
52
52
|
* 要ります。既定は `auto`(=rule #44 の最も静かな状態)なので、このトークンを置くまで DOM も
|
|
53
53
|
* 見え方も従来どおり · 文書ページはそもそもこの規則に一致しません。
|
|
@@ -109,7 +109,7 @@ const journalColumns: ColumnDef<JournalEntry>[] = [
|
|
|
109
109
|
* PageContainer · mandatory page shell.
|
|
110
110
|
* Covers: title/subtitle/status/extra/footer/breadcrumb/linkComponent + variant
|
|
111
111
|
* default/narrow/flush/ghost + density compact/default/comfortable + PageContainer.Inset.
|
|
112
|
-
* The embedded header is the CANONICAL DXS PageHeader
|
|
112
|
+
* The embedded header is the CANONICAL DXS PageHeader — status/meta band included.
|
|
113
113
|
* Each example is standalone (no AppShell) so the variant behaviour is visible in
|
|
114
114
|
* isolation. Composed only from real @godxjp/ui components.
|
|
115
115
|
*/
|
|
@@ -165,7 +165,7 @@ export default function Demo() {
|
|
|
165
165
|
</ResponsiveGrid>
|
|
166
166
|
</PageContainer>
|
|
167
167
|
|
|
168
|
-
{/* ── 1b. Canonical page-header contract
|
|
168
|
+
{/* ── 1b. Canonical page-header contract · status/meta band ── */}
|
|
169
169
|
{/* PageContainer's embedded header IS the DXS PageHeader: breadcrumbs + title +
|
|
170
170
|
subtitle + status/meta + actions + responsive overflow on ONE renderer. The
|
|
171
171
|
`status` band shares the title line at --page-header-status-gap and wraps
|
|
@@ -405,7 +405,7 @@ export default function Demo() {
|
|
|
405
405
|
</Card>
|
|
406
406
|
</PageContainer>
|
|
407
407
|
|
|
408
|
-
{/* ── 6. fill · body height behaviour on a tall shell
|
|
408
|
+
{/* ── 6. fill · body height behaviour on a tall shell ──
|
|
409
409
|
Each PageContainer sits in a fixed-height framed box that stands in for the
|
|
410
410
|
viewport-tall app shell, so the two behaviours are visible side by side. */}
|
|
411
411
|
<ResponsiveGrid columns={{ sm: 1, md: 2 }}>
|
|
@@ -452,7 +452,7 @@ export default function Demo() {
|
|
|
452
452
|
</div>
|
|
453
453
|
</ResponsiveGrid>
|
|
454
454
|
|
|
455
|
-
{/* ── 7. headerLayout · 390px でヘッダー extra をタイトル行に残す
|
|
455
|
+
{/* ── 7. headerLayout · 390px でヘッダー extra をタイトル行に残す ──
|
|
456
456
|
stack (既定) は 640px 未満で extra を subtitle の下の全幅行に落とす。
|
|
457
457
|
responsive-inline は --page-header-extra-measure (11rem) の測度で
|
|
458
458
|
title 帯の横に残す。640px 以上では両者は同一。
|
|
@@ -505,7 +505,7 @@ export default function Demo() {
|
|
|
505
505
|
</PageContainer>
|
|
506
506
|
</ResponsiveGrid>
|
|
507
507
|
|
|
508
|
-
{/* ── 8. measure · ヘッダーとボディを 1 つの測度で束ねる
|
|
508
|
+
{/* ── 8. measure · ヘッダーとボディを 1 つの測度で束ねる ──
|
|
509
509
|
measure は variant(クローム)と直交する第 3 の軸。variant="narrow" は
|
|
510
510
|
.ui-page-body しか絞らないため、ヘッダーのアクションはページ端に取り残される。
|
|
511
511
|
measure はヘッダーとボディの両方を同じトークン測度で絞るので、extra の終端が
|
|
@@ -13,7 +13,7 @@ import { Flex, PageContainer, ResponsiveGrid, SplitPane } from "@godxjp/ui/layou
|
|
|
13
13
|
* ResponsiveGrid · equal-width multi-column tile grid with automatic responsive
|
|
14
14
|
* collapse (CSS container queries, not viewport). It OWNS its query container
|
|
15
15
|
* (container-type: inline-size), so it responds to the width available to the grid
|
|
16
|
-
* with no external container-type declaration
|
|
16
|
+
* with no external container-type declaration. Direct children are typically
|
|
17
17
|
* StatCard (self-contained bordered card · never wrap in Card/CardContent) or
|
|
18
18
|
* Card+CardContent for richer tile bodies. columns accepts a number OR breakpoint
|
|
19
19
|
* object { sm?, md?, lg? } — or use the named `preset` prop (e.g. "pricing-plans") for a
|
|
@@ -45,7 +45,7 @@ export default function Demo() {
|
|
|
45
45
|
aside={
|
|
46
46
|
<Flex direction="col" gap="sm">
|
|
47
47
|
<Text tone="muted">狭いコンテナ(約 20rem)→ sm=1 列</Text>
|
|
48
|
-
{/* No wrapping `@container` needed — ResponsiveGrid OWNS its query container
|
|
48
|
+
{/* No wrapping `@container` needed — ResponsiveGrid OWNS its query container. */}
|
|
49
49
|
<ResponsiveGrid columns={4}>
|
|
50
50
|
<StatCard label="今日の入金" value="¥420,000" />
|
|
51
51
|
<StatCard label="未処理" value="6 件" />
|
|
@@ -19,7 +19,7 @@ import { Flex, PageContainer, Separator } from "@godxjp/ui/layout";
|
|
|
19
19
|
* defaults to true · set false only when the divider carries semantic meaning for
|
|
20
20
|
* a11y.
|
|
21
21
|
*
|
|
22
|
-
*
|
|
22
|
+
* `label` INTERRUPTS the rule: a message stream's day divider, a "new messages"
|
|
23
23
|
* watermark, an auth conjunction. A labelled rule flips `decorative` to false, so it is a real
|
|
24
24
|
* role="separator" NAMED by the label (the visible node is aria-hidden, so the string is announced
|
|
25
25
|
* exactly once). `labelAlign` is a controlled vocabulary value — start | center | end, logical, so
|
|
@@ -172,7 +172,7 @@ export default function Demo() {
|
|
|
172
172
|
</CardContent>
|
|
173
173
|
</Card>
|
|
174
174
|
|
|
175
|
-
{/* ──
|
|
175
|
+
{/* ── — the real screen the labelled rule exists for ─────────────────────────── */}
|
|
176
176
|
<Card>
|
|
177
177
|
<CardHeader>
|
|
178
178
|
<CardTitle level={2}>実画面 · チャンネルの投稿ストリーム</CardTitle>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ServiceRolePanel — ロール一覧 ⇄ 詳細 (canonical master-detail roles surface
|
|
2
|
+
* ServiceRolePanel — ロール一覧 ⇄ 詳細 (canonical master-detail roles surface).
|
|
3
3
|
*
|
|
4
4
|
* MasterDetail (rail=master) underneath owns all geometry: two tracks at 1440/1024, stacked
|
|
5
5
|
* list-then-detail at 390. The panel adds selection (aria-current rows), locked system roles,
|
package/docs/layout/sidebar.tsx
CHANGED
|
@@ -127,7 +127,7 @@ const MENTION_SECTIONS: SidebarSectionProp[] = [
|
|
|
127
127
|
];
|
|
128
128
|
|
|
129
129
|
/**
|
|
130
|
-
*
|
|
130
|
+
* nav row and nav icon read SEPARATE colour tokens. A service normally sets these once in
|
|
131
131
|
* its theme.css (`:root` or a scoped `[data-tenant] .app-sidebar`); here they are scoped to one
|
|
132
132
|
* demo frame so the default rail can sit next to the themed one. Icons only — geometry (16px icon,
|
|
133
133
|
* 32px row, 10px gap) is untouched.
|
|
@@ -138,7 +138,7 @@ const CANONICAL_NAV_TOKENS = {
|
|
|
138
138
|
} as CSSProperties;
|
|
139
139
|
|
|
140
140
|
/**
|
|
141
|
-
*
|
|
141
|
+
* THE router-link contract. `createSidebarLink` adapts any router `Link` — React Router /
|
|
142
142
|
* TanStack use `to`, Inertia and Next.js use `href` (the default, and
|
|
143
143
|
* `inertiaSidebarLink(Link)` from `@godxjp/ui/inertia` is the same thing pre-bound). The consumer
|
|
144
144
|
* writes NO row markup: the Sidebar composes the icon slot, the label, the badge, the active state
|
|
@@ -171,7 +171,7 @@ const ROUTED_SECTIONS: SidebarSectionProp[] = [
|
|
|
171
171
|
];
|
|
172
172
|
|
|
173
173
|
/**
|
|
174
|
-
* renderItem · DEPRECATED
|
|
174
|
+
* renderItem · DEPRECATED — kept working for existing consumers. It leaves the row CONTENT
|
|
175
175
|
* to the caller, which is how a `<Link>{item.label}</Link>` silently dropped every icon in
|
|
176
176
|
* production. `rowProps` now carries the library-composed `children`, so spreading it (or rendering
|
|
177
177
|
* `rowProps.children`) restores the canonical row; the star is a decorative, non-interactive affix.
|
|
@@ -346,7 +346,7 @@ export default function Demo() {
|
|
|
346
346
|
</CardContent>
|
|
347
347
|
</Card>
|
|
348
348
|
|
|
349
|
-
{/* linkComponent prop · THE router-link contract
|
|
349
|
+
{/* linkComponent prop · THE router-link contract — library composes the row. */}
|
|
350
350
|
<Card>
|
|
351
351
|
<CardHeader>
|
|
352
352
|
<CardTitle level={2}>linkComponent プロップ(ルーターリンク)</CardTitle>
|
|
@@ -395,7 +395,7 @@ export default function Demo() {
|
|
|
395
395
|
</CardContent>
|
|
396
396
|
</Card>
|
|
397
397
|
|
|
398
|
-
{/* renderItem prop · DEPRECATED escape hatch
|
|
398
|
+
{/* renderItem prop · DEPRECATED escape hatch — kept for back-compat. */}
|
|
399
399
|
<Card>
|
|
400
400
|
<CardHeader>
|
|
401
401
|
<CardTitle level={2}>renderItem プロップ(非推奨)</CardTitle>
|
|
@@ -526,7 +526,7 @@ export default function Demo() {
|
|
|
526
526
|
</CardContent>
|
|
527
527
|
</Card>
|
|
528
528
|
|
|
529
|
-
{/* Nav colour tokens · icon and label are themed SEPARATELY
|
|
529
|
+
{/* Nav colour tokens · icon and label are themed SEPARATELY. */}
|
|
530
530
|
<Card>
|
|
531
531
|
<CardHeader>
|
|
532
532
|
<CardTitle level={2}>ナビの配色トークン(アイコンとラベルを別々に)</CardTitle>
|
|
@@ -17,7 +17,7 @@ import { FileText, Building2, Calendar, CreditCard, ArrowRight } from "lucide-re
|
|
|
17
17
|
* Shows: main list + detail panel, asideWidth sm/md, nested inside PageContainer.
|
|
18
18
|
* It OWNS its query container (container-type: inline-size), so the two-column split
|
|
19
19
|
* is chosen from the PANE's own width (≥48rem), not the viewport — a narrow embedded
|
|
20
|
-
* pane on a large screen correctly stays single-column
|
|
20
|
+
* pane on a large screen correctly stays single-column.
|
|
21
21
|
* Composed only from real @godxjp/ui components.
|
|
22
22
|
*
|
|
23
23
|
* NOTE: <Flex> defaults to direction="row"; vertical stacks set direction="col"
|
package/docs/layout/topbar.tsx
CHANGED
|
@@ -37,10 +37,7 @@ import {
|
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* Topbar · a PURE SLOT bar. The shell only positions `start` / `center` / `end`; the CONSUMER
|
|
40
|
-
* composes every control.
|
|
41
|
-
* sidebar toggle, brand mark (Avatar), an entity switcher, a search trigger, a notifications button, a
|
|
42
|
-
* user menu · entirely from real primitives, so you can see there is no hidden template (and no
|
|
43
|
-
* dead dropdown: a control exists ONLY because it's placed here).
|
|
40
|
+
* composes every control.
|
|
44
41
|
*/
|
|
45
42
|
const SECTIONS: SidebarSectionProp[] = [
|
|
46
43
|
{
|
|
@@ -153,10 +150,7 @@ export default function Demo() {
|
|
|
153
150
|
// end · notifications + user menu, both consumer-composed.
|
|
154
151
|
const end = (
|
|
155
152
|
<>
|
|
156
|
-
{
|
|
157
|
-
budget before it gets a say. At 320 this environment chip alone claimed 93 of the bar's
|
|
158
|
-
198px, squeezing start to 25px and clipping the entity switcher inside it. An ambient
|
|
159
|
-
status label is the first thing a compact bar drops, so it appears from sm up. */}
|
|
153
|
+
{}
|
|
160
154
|
<Badge tone="warning" className="text-xs">
|
|
161
155
|
ステージング
|
|
162
156
|
</Badge>
|
|
@@ -39,7 +39,7 @@ export default function Demo() {
|
|
|
39
39
|
const [period, setPeriod] = useState("all");
|
|
40
40
|
const hasActiveFilters = query !== "" || status !== "all";
|
|
41
41
|
|
|
42
|
-
// Typed model
|
|
42
|
+
// Typed model — ALL state is consumer data; the bar only renders it.
|
|
43
43
|
const [modelQuery, setModelQuery] = useState("田中");
|
|
44
44
|
const [modelStatus, setModelStatus] = useState("active");
|
|
45
45
|
const [modelRole, setModelRole] = useState("");
|
|
@@ -80,7 +80,7 @@ export default function Demo() {
|
|
|
80
80
|
subtitle="Search, labelled filters, active state, consumer-owned reset, and both responsive overflow strategies"
|
|
81
81
|
>
|
|
82
82
|
<Flex direction="col" gap="lg">
|
|
83
|
-
{/* Typed model
|
|
83
|
+
{/* Typed model — search/filters/chips/reset/result-count/actions as DATA.
|
|
84
84
|
The bar owns layout, token widths, chip lifecycle and keyboard order; the page owns
|
|
85
85
|
every piece of state. Remove a chip, reset, or pick a filter and watch the chips row
|
|
86
86
|
and the localized result count follow. */}
|
|
@@ -97,7 +97,7 @@ export default function Demo() {
|
|
|
97
97
|
onValueChange={handleChange}
|
|
98
98
|
/>
|
|
99
99
|
|
|
100
|
-
{/* Regression: total=0, exactly one page, multiple pages, + the single-page opt-in
|
|
100
|
+
{/* Regression: total=0, exactly one page, multiple pages, + the single-page opt-in. */}
|
|
101
101
|
<Card>
|
|
102
102
|
<CardHeader>
|
|
103
103
|
<CardTitle level={2}>境界状態 · 0 件 / 1 ページ / 複数ページ</CardTitle>
|
|
@@ -136,7 +136,7 @@ export default function Demo() {
|
|
|
136
136
|
</CardContent>
|
|
137
137
|
</Card>
|
|
138
138
|
|
|
139
|
-
{/* Long localized total label — the row stays ONE line and never wraps on desktop
|
|
139
|
+
{/* Long localized total label — the row stays ONE line and never wraps on desktop. */}
|
|
140
140
|
<Card>
|
|
141
141
|
<CardHeader>
|
|
142
142
|
<CardTitle level={2}>長いローカライズ済みラベル · 折り返さない</CardTitle>
|
|
@@ -229,7 +229,7 @@ export default function Demo() {
|
|
|
229
229
|
</CardContent>
|
|
230
230
|
</Card>
|
|
231
231
|
|
|
232
|
-
{/* Inline row — the hosted-identity / device progression
|
|
232
|
+
{/* Inline row — the hosted-identity / device progression */}
|
|
233
233
|
<Card>
|
|
234
234
|
<CardHeader>
|
|
235
235
|
<CardTitle level={2}>
|
package/docs/navigation/tabs.tsx
CHANGED
|
@@ -67,7 +67,7 @@ export default function Demo() {
|
|
|
67
67
|
</CardContent>
|
|
68
68
|
</Card>
|
|
69
69
|
|
|
70
|
-
{/* Disabled first item — fallback selection must skip it
|
|
70
|
+
{/* Disabled first item — fallback selection must skip it */}
|
|
71
71
|
<Card>
|
|
72
72
|
<CardHeader>
|
|
73
73
|
<CardTitle level={2}>先頭タブが disabled · フォールバック選択</CardTitle>
|
|
@@ -50,6 +50,7 @@ import {
|
|
|
50
50
|
CardContent,
|
|
51
51
|
CardHeader,
|
|
52
52
|
CardTitle,
|
|
53
|
+
ListRow,
|
|
53
54
|
Progress,
|
|
54
55
|
StatCard,
|
|
55
56
|
Table,
|
|
@@ -353,27 +354,25 @@ export default function AcmePortalShowcase() {
|
|
|
353
354
|
<CardContent flush>
|
|
354
355
|
<ul className="divide-border divide-y">
|
|
355
356
|
{QUEUE.map((q) => (
|
|
356
|
-
<
|
|
357
|
-
|
|
357
|
+
<ListRow
|
|
358
|
+
as="li"
|
|
359
|
+
key={q.title}
|
|
360
|
+
leading={
|
|
358
361
|
<Badge
|
|
359
362
|
tone={q.tone}
|
|
360
363
|
variant="outline"
|
|
361
364
|
icon={q.icon}
|
|
362
365
|
aria-label={q.title}
|
|
363
366
|
/>
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
<Text as="div" size="xs" tone="muted" truncate>
|
|
369
|
-
{q.meta}
|
|
370
|
-
</Text>
|
|
371
|
-
</div>
|
|
367
|
+
}
|
|
368
|
+
title={q.title}
|
|
369
|
+
description={q.meta}
|
|
370
|
+
trailing={
|
|
372
371
|
<Button variant="outline" size="sm">
|
|
373
372
|
{q.action}
|
|
374
373
|
</Button>
|
|
375
|
-
|
|
376
|
-
|
|
374
|
+
}
|
|
375
|
+
/>
|
|
377
376
|
))}
|
|
378
377
|
</ul>
|
|
379
378
|
</CardContent>
|
|
@@ -237,7 +237,7 @@ function SectionHead({
|
|
|
237
237
|
center?: boolean;
|
|
238
238
|
}) {
|
|
239
239
|
return (
|
|
240
|
-
<div className={center ? "mx-auto
|
|
240
|
+
<div className={center ? "mx-auto text-center" : undefined}>
|
|
241
241
|
<div className="tx-eyebrow">{eyebrow}</div>
|
|
242
242
|
<h2 className="tx-h2">{title}</h2>
|
|
243
243
|
{sub ? <p className="tx-lead mx-auto">{sub}</p> : null}
|
|
@@ -272,7 +272,7 @@ function Services() {
|
|
|
272
272
|
];
|
|
273
273
|
return (
|
|
274
274
|
<section className="bg-card tx-section">
|
|
275
|
-
<
|
|
275
|
+
<Flex direction="col" gap="xl" className={SHELL}>
|
|
276
276
|
<SectionHead
|
|
277
277
|
center
|
|
278
278
|
eyebrow="Dịch vụ"
|
|
@@ -296,7 +296,7 @@ function Services() {
|
|
|
296
296
|
</Card>
|
|
297
297
|
))}
|
|
298
298
|
</ResponsiveGrid>
|
|
299
|
-
</
|
|
299
|
+
</Flex>
|
|
300
300
|
</section>
|
|
301
301
|
);
|
|
302
302
|
}
|
|
@@ -310,7 +310,7 @@ function Steps() {
|
|
|
310
310
|
];
|
|
311
311
|
return (
|
|
312
312
|
<section className="bg-background tx-section">
|
|
313
|
-
<
|
|
313
|
+
<Flex direction="col" gap="xl" className={SHELL}>
|
|
314
314
|
<SectionHead eyebrow="Quy trình" title="Mua hàng quốc tế trong 4 bước" />
|
|
315
315
|
<ResponsiveGrid columns={{ sm: 1, md: 2, lg: 4 }}>
|
|
316
316
|
{steps.map(([Icon, t, d], i) => (
|
|
@@ -332,7 +332,7 @@ function Steps() {
|
|
|
332
332
|
</Flex>
|
|
333
333
|
))}
|
|
334
334
|
</ResponsiveGrid>
|
|
335
|
-
</
|
|
335
|
+
</Flex>
|
|
336
336
|
</section>
|
|
337
337
|
);
|
|
338
338
|
}
|
|
@@ -346,7 +346,7 @@ function Routes() {
|
|
|
346
346
|
];
|
|
347
347
|
return (
|
|
348
348
|
<section className="bg-card tx-section">
|
|
349
|
-
<
|
|
349
|
+
<Flex direction="col" gap="xl" className={SHELL}>
|
|
350
350
|
<SectionHead eyebrow="Tuyến vận chuyển" title="Giá cước rõ ràng theo từng tuyến" />
|
|
351
351
|
<ResponsiveGrid columns={{ sm: 1, md: 2, lg: 4 }}>
|
|
352
352
|
{routes.map(([c, code, mode, price]) => (
|
|
@@ -370,7 +370,7 @@ function Routes() {
|
|
|
370
370
|
</Card>
|
|
371
371
|
))}
|
|
372
372
|
</ResponsiveGrid>
|
|
373
|
-
</
|
|
373
|
+
</Flex>
|
|
374
374
|
</section>
|
|
375
375
|
);
|
|
376
376
|
}
|
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
CardContent,
|
|
44
44
|
CardHeader,
|
|
45
45
|
CardTitle,
|
|
46
|
+
ListRow,
|
|
46
47
|
Progress,
|
|
47
48
|
StatCard,
|
|
48
49
|
Table,
|
|
@@ -241,27 +242,25 @@ export default function WarehouseDashboardShowcase() {
|
|
|
241
242
|
<ul className="divide-border divide-y">
|
|
242
243
|
{QUEUE.map((q) => {
|
|
243
244
|
return (
|
|
244
|
-
<
|
|
245
|
-
|
|
245
|
+
<ListRow
|
|
246
|
+
as="li"
|
|
247
|
+
key={q.title}
|
|
248
|
+
leading={
|
|
246
249
|
<Badge
|
|
247
250
|
tone={q.tone}
|
|
248
251
|
variant="outline"
|
|
249
252
|
icon={q.icon}
|
|
250
253
|
aria-label={q.title}
|
|
251
254
|
/>
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
<Text as="div" size="2xs" tone="muted" truncate>
|
|
257
|
-
{q.meta}
|
|
258
|
-
</Text>
|
|
259
|
-
</div>
|
|
255
|
+
}
|
|
256
|
+
title={q.title}
|
|
257
|
+
description={q.meta}
|
|
258
|
+
trailing={
|
|
260
259
|
<Button variant="outline" size="sm">
|
|
261
260
|
{q.action}
|
|
262
261
|
</Button>
|
|
263
|
-
|
|
264
|
-
|
|
262
|
+
}
|
|
263
|
+
/>
|
|
265
264
|
);
|
|
266
265
|
})}
|
|
267
266
|
</ul>
|