@godxjp/ui 19.2.0 → 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 +26 -2
- package/dist/components/data-display/badge.js +20 -5
- 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 +72 -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 +113 -2
- package/dist/props/registry.js +155 -1
- 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/badge-layout.css +15 -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/badge.css +8 -0
- 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 +37 -1
- package/docs/data-display/card/index.tsx +6 -4
- package/docs/data-display/carousel.tsx +8 -4
- package/docs/data-display/data-table/examples/approval-queue.tsx +1 -1
- package/docs/data-display/data-table/examples/grid-features.tsx +1 -1
- package/docs/data-display/data-table/index.tsx +1 -1
- package/docs/data-display/permission-matrix.tsx +15 -11
- package/docs/data-display/popover.tsx +2 -1
- package/docs/data-display/scroll-area.tsx +108 -76
- package/docs/data-display/table.tsx +2 -2
- package/docs/data-display/timeline-grid.tsx +119 -0
- package/docs/data-entry/branch-scope-picker.tsx +1 -1
- package/docs/data-entry/calendar.tsx +1 -1
- package/docs/data-entry/checkbox.tsx +1 -1
- package/docs/data-entry/country-picker-recipe.tsx +11 -6
- package/docs/data-entry/form-field/index.tsx +33 -29
- package/docs/data-entry/form-root.tsx +1 -1
- package/docs/data-entry/input-otp.tsx +1 -1
- package/docs/data-entry/password-input.tsx +1 -5
- package/docs/data-entry/select.tsx +7 -7
- package/docs/data-entry/textarea.tsx +3 -3
- 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/sheet.tsx +112 -102
- package/docs/feedback/skeleton.tsx +2 -2
- package/docs/foundation/colors.tsx +8 -6
- package/docs/foundation/email-tokens.tsx +83 -66
- package/docs/foundation/radius-shadow.tsx +13 -11
- package/docs/general/activity.tsx +1 -1
- package/docs/layout/app-shell.tsx +2 -2
- package/docs/layout/aspect-ratio.tsx +30 -14
- 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/flex.tsx +6 -2
- package/docs/layout/master-detail.tsx +2 -2
- package/docs/layout/mobile-shell.tsx +101 -0
- package/docs/layout/page-container.tsx +15 -7
- package/docs/layout/responsive-grid.tsx +12 -4
- package/docs/layout/separator.tsx +2 -2
- package/docs/layout/service-role-panel.tsx +1 -1
- package/docs/layout/sidebar.tsx +175 -152
- package/docs/layout/split-pane.tsx +45 -28
- package/docs/layout/topbar.tsx +19 -23
- package/docs/navigation/app-setting-picker.tsx +5 -4
- package/docs/navigation/breadcrumb.tsx +12 -5
- package/docs/navigation/context-menu.tsx +10 -4
- package/docs/navigation/filter-bar.tsx +2 -2
- package/docs/navigation/navigation-menu.tsx +89 -96
- package/docs/navigation/pagination.tsx +2 -2
- package/docs/navigation/steps.tsx +13 -11
- package/docs/navigation/tabs.tsx +27 -21
- package/docs/navigation/toolbar.tsx +15 -15
- package/docs/providers/format-date.tsx +2 -2
- package/docs/showcase/acme-portal.tsx +41 -28
- package/docs/showcase/acme-website.tsx +67 -61
- package/docs/showcase/case1-warehouse-dashboard.tsx +46 -31
- package/docs/showcase/case2-employee-me.tsx +33 -36
- package/docs/showcase/case3-approval-workflow.tsx +34 -32
- package/docs/showcase/case4-login.tsx +95 -101
- package/docs/showcase/case5-shift-calendar.tsx +182 -281
- package/docs/showcase/case6-agency-handy.tsx +514 -470
- package/docs/showcase/futurelastic-web.tsx +32 -29
- package/docs/showcase/org-switcher.tsx +20 -13
- package/docs/showcase/permission-matrix.tsx +20 -17
- 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 +9 -9
- package/docs/showcase/table-crud-list.tsx +4 -4
- package/docs/showcase/table-density.tsx +49 -42
- package/docs/showcase/table-expandable-rows.tsx +112 -100
- package/docs/showcase/table-filter-chips.tsx +78 -71
- package/docs/showcase/table-footer-totals.tsx +30 -23
- package/docs/showcase/table-grouped-subtotals.tsx +31 -25
- package/docs/showcase/table-master-detail.tsx +27 -24
- package/docs/showcase/table-pagination.tsx +34 -27
- package/docs/showcase/table-states.tsx +42 -34
- package/docs/showcase/table-sticky-columns.tsx +11 -7
- package/docs/showcase/table-tree-rows.tsx +22 -15
- package/docs/showcase/table-view-tabs.tsx +12 -14
- package/package.json +7 -7
|
@@ -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
|
|
@@ -139,8 +139,12 @@ export default function Demo() {
|
|
|
139
139
|
<iframe
|
|
140
140
|
title="Transactional email specimen at 480px"
|
|
141
141
|
srcDoc={specimen}
|
|
142
|
-
className="
|
|
143
|
-
style={{
|
|
142
|
+
className="bg-background w-full"
|
|
143
|
+
style={{
|
|
144
|
+
border: "1px solid hsl(var(--border))",
|
|
145
|
+
borderRadius: "var(--radius-md)",
|
|
146
|
+
height: 560,
|
|
147
|
+
}}
|
|
144
148
|
/>
|
|
145
149
|
</CardContent>
|
|
146
150
|
</Card>
|
|
@@ -160,8 +164,13 @@ export default function Demo() {
|
|
|
160
164
|
<iframe
|
|
161
165
|
title="Transactional email specimen at 360px"
|
|
162
166
|
srcDoc={specimen}
|
|
163
|
-
className="
|
|
164
|
-
style={{
|
|
167
|
+
className="bg-background"
|
|
168
|
+
style={{
|
|
169
|
+
border: "1px solid hsl(var(--border))",
|
|
170
|
+
borderRadius: "var(--radius-md)",
|
|
171
|
+
width: 360,
|
|
172
|
+
height: 620,
|
|
173
|
+
}}
|
|
165
174
|
/>
|
|
166
175
|
</CardContent>
|
|
167
176
|
</Card>
|
|
@@ -182,39 +191,41 @@ export default function Demo() {
|
|
|
182
191
|
</CardDescription>
|
|
183
192
|
</CardHeader>
|
|
184
193
|
<CardContent>
|
|
185
|
-
<
|
|
186
|
-
{
|
|
187
|
-
{
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
<
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
<
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
194
|
+
<Flex direction="col" gap="md">
|
|
195
|
+
<ResponsiveGrid columns={{ sm: 1, md: 3 }}>
|
|
196
|
+
{[
|
|
197
|
+
{ label: "Inline <svg>", markup: EMAIL_BRAND_MARK.svg },
|
|
198
|
+
{
|
|
199
|
+
// Prose label, not markup: it names the email delivery form. The real delivery
|
|
200
|
+
// on the next line is a self-contained data: URI (email clients block remote
|
|
201
|
+
// images) and it does carry alt="GoDX".
|
|
202
|
+
// ui-audit-disable-next-line img-needs-alt
|
|
203
|
+
label: "data: URL in <img>",
|
|
204
|
+
markup: `<img src="${EMAIL_BRAND_MARK.dataUri}" width="${EMAIL_BRAND_MARK.widthPx}" height="${EMAIL_BRAND_MARK.heightPx}" alt="GoDX">`,
|
|
205
|
+
},
|
|
206
|
+
// Prose label, not markup: a raw <table> is the only brand-mark fallback that
|
|
207
|
+
// renders in email clients without SVG support, so the label names it literally.
|
|
208
|
+
// ui-audit-disable-next-line no-raw-table
|
|
209
|
+
{ label: "<table> fallback", markup: EMAIL_BRAND_MARK.tableHtml },
|
|
210
|
+
].map((item) => (
|
|
211
|
+
<Flex key={item.label} direction="col" gap="sm">
|
|
212
|
+
<div
|
|
213
|
+
// eslint-disable-next-line react/no-danger
|
|
214
|
+
dangerouslySetInnerHTML={{ __html: item.markup }}
|
|
215
|
+
/>
|
|
216
|
+
<Text size="sm" tone="muted">
|
|
217
|
+
{item.label}
|
|
218
|
+
</Text>
|
|
219
|
+
</Flex>
|
|
220
|
+
))}
|
|
221
|
+
</ResponsiveGrid>
|
|
222
|
+
<Flex direction="col" gap="xs">
|
|
223
|
+
<Text size="sm" tone="muted">
|
|
224
|
+
viewBox {EMAIL_BRAND_MARK.viewBox} · {EMAIL_BRAND_MARK.width}×
|
|
225
|
+
{EMAIL_BRAND_MARK.height} · capsule {EMAIL_COLORS.brand} · glyph{" "}
|
|
226
|
+
{EMAIL_COLORS.brandForeground}
|
|
227
|
+
</Text>
|
|
228
|
+
</Flex>
|
|
218
229
|
</Flex>
|
|
219
230
|
</CardContent>
|
|
220
231
|
</Card>
|
|
@@ -235,8 +246,12 @@ export default function Demo() {
|
|
|
235
246
|
{colorRows.map((row) => (
|
|
236
247
|
<Flex key={row.token} direction="col" gap="xs">
|
|
237
248
|
<div
|
|
238
|
-
className="
|
|
239
|
-
style={{
|
|
249
|
+
className="h-12"
|
|
250
|
+
style={{
|
|
251
|
+
border: "1px solid hsl(var(--border))",
|
|
252
|
+
borderRadius: "var(--radius-md)",
|
|
253
|
+
backgroundColor: row.hex,
|
|
254
|
+
}}
|
|
240
255
|
/>
|
|
241
256
|
<Text size="sm">{row.token}</Text>
|
|
242
257
|
<Flex gap="xs" align="center">
|
|
@@ -271,33 +286,35 @@ export default function Demo() {
|
|
|
271
286
|
</CardDescription>
|
|
272
287
|
</CardHeader>
|
|
273
288
|
<CardContent>
|
|
274
|
-
<Flex direction="col" gap="
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
<
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
289
|
+
<Flex direction="col" gap="md">
|
|
290
|
+
<Flex direction="col" gap="xs">
|
|
291
|
+
{fontStacks.map((stack) => (
|
|
292
|
+
<Flex key={stack.label} direction="col" gap="xs">
|
|
293
|
+
<Badge tone="neutral" variant="outline">
|
|
294
|
+
{stack.label}
|
|
295
|
+
</Badge>
|
|
296
|
+
<Text size="sm" tone="muted">
|
|
297
|
+
{stack.value}
|
|
298
|
+
</Text>
|
|
299
|
+
</Flex>
|
|
300
|
+
))}
|
|
301
|
+
</Flex>
|
|
302
|
+
<ResponsiveGrid columns={{ sm: 1, md: 2, lg: 4 }}>
|
|
303
|
+
{geometryGroups.map((group) => (
|
|
304
|
+
<Flex key={group.title} direction="col" gap="xs">
|
|
305
|
+
<Text weight="medium">{group.title}</Text>
|
|
306
|
+
{group.rows.map(([label, value]) => (
|
|
307
|
+
<Flex key={label} justify="between" gap="sm">
|
|
308
|
+
<Text size="sm" tone="muted">
|
|
309
|
+
{label}
|
|
310
|
+
</Text>
|
|
311
|
+
<Text size="sm">{value}</Text>
|
|
312
|
+
</Flex>
|
|
313
|
+
))}
|
|
314
|
+
</Flex>
|
|
315
|
+
))}
|
|
316
|
+
</ResponsiveGrid>
|
|
285
317
|
</Flex>
|
|
286
|
-
<ResponsiveGrid columns={{ sm: 1, md: 2, lg: 4 }}>
|
|
287
|
-
{geometryGroups.map((group) => (
|
|
288
|
-
<Flex key={group.title} direction="col" gap="xs">
|
|
289
|
-
<Text weight="medium">{group.title}</Text>
|
|
290
|
-
{group.rows.map(([label, value]) => (
|
|
291
|
-
<Flex key={label} justify="between" gap="sm">
|
|
292
|
-
<Text size="sm" tone="muted">
|
|
293
|
-
{label}
|
|
294
|
-
</Text>
|
|
295
|
-
<Text size="sm">{value}</Text>
|
|
296
|
-
</Flex>
|
|
297
|
-
))}
|
|
298
|
-
</Flex>
|
|
299
|
-
))}
|
|
300
|
-
</ResponsiveGrid>
|
|
301
318
|
</CardContent>
|
|
302
319
|
</Card>
|
|
303
320
|
</Flex>
|
|
@@ -127,17 +127,19 @@ export default function Demo() {
|
|
|
127
127
|
</Text>
|
|
128
128
|
</Flex>
|
|
129
129
|
<Flex direction="col" gap="xs">
|
|
130
|
-
<
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
130
|
+
<Card>
|
|
131
|
+
<CardContent flush>
|
|
132
|
+
{/* ui-audit-disable-next-line no-utility-spacing — a tile showing the shadow token itself; the box IS the subject */}
|
|
133
|
+
<div className="p-4" style={{ boxShadow: "var(--shadow-lg)" }}>
|
|
134
|
+
<Text as="div" weight="medium">
|
|
135
|
+
Floating(ポップオーバー)
|
|
136
|
+
</Text>
|
|
137
|
+
<Text as="div" size="xs" tone="muted">
|
|
138
|
+
--shadow-lg lifts it off the page
|
|
139
|
+
</Text>
|
|
140
|
+
</div>
|
|
141
|
+
</CardContent>
|
|
142
|
+
</Card>
|
|
141
143
|
<Text as="div" size="xs" tone="muted">
|
|
142
144
|
floating surface · elevated
|
|
143
145
|
</Text>
|
|
@@ -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
|
|
@@ -138,7 +138,7 @@ export default function Demo() {
|
|
|
138
138
|
{/* Decorative brand mark — hidden below `sm` where the hamburger already anchors the
|
|
139
139
|
start of a narrow mobile topbar, so functional controls (entity switcher, search)
|
|
140
140
|
keep priority and the bar never overflows. */}
|
|
141
|
-
<Avatar className="
|
|
141
|
+
<Avatar className="rounded-md">
|
|
142
142
|
<AvatarFallback className="bg-primary text-primary-foreground font-bold">
|
|
143
143
|
C
|
|
144
144
|
</AvatarFallback>
|
|
@@ -159,7 +159,7 @@ export default function Demo() {
|
|
|
159
159
|
<DropdownMenuSeparator />
|
|
160
160
|
{ENTITIES.map((e) => (
|
|
161
161
|
<DropdownMenuItem key={e.id} onSelect={() => setActiveEntity(e.name)}>
|
|
162
|
-
<Building2 className="
|
|
162
|
+
<Building2 className="size-4" />
|
|
163
163
|
{e.name}
|
|
164
164
|
</DropdownMenuItem>
|
|
165
165
|
))}
|
|
@@ -27,9 +27,13 @@ export default function Demo() {
|
|
|
27
27
|
</CardHeader>
|
|
28
28
|
<CardContent>
|
|
29
29
|
<AspectRatio ratio={16 / 9}>
|
|
30
|
-
<
|
|
31
|
-
<
|
|
32
|
-
|
|
30
|
+
<Card variant="muted" className="h-full w-full">
|
|
31
|
+
<CardContent flush>
|
|
32
|
+
<Flex align="center" justify="center" gap="xs">
|
|
33
|
+
<Text tone="muted">16:9 動画プレビュー(サンプル)</Text>
|
|
34
|
+
</Flex>
|
|
35
|
+
</CardContent>
|
|
36
|
+
</Card>
|
|
33
37
|
</AspectRatio>
|
|
34
38
|
</CardContent>
|
|
35
39
|
</Card>
|
|
@@ -45,9 +49,13 @@ export default function Demo() {
|
|
|
45
49
|
<CardContent>
|
|
46
50
|
<div className="max-w-xs">
|
|
47
51
|
<AspectRatio ratio={4 / 3}>
|
|
48
|
-
<
|
|
49
|
-
<
|
|
50
|
-
|
|
52
|
+
<Card variant="muted" className="h-full w-full">
|
|
53
|
+
<CardContent flush>
|
|
54
|
+
<Flex align="center" justify="center" gap="xs">
|
|
55
|
+
<Text tone="muted">領収書スキャン 4:3</Text>
|
|
56
|
+
</Flex>
|
|
57
|
+
</CardContent>
|
|
58
|
+
</Card>
|
|
51
59
|
</AspectRatio>
|
|
52
60
|
</div>
|
|
53
61
|
</CardContent>
|
|
@@ -66,11 +74,15 @@ export default function Demo() {
|
|
|
66
74
|
{["株式会社 A", "合同会社 B", "有限会社 C"].map((name) => (
|
|
67
75
|
<div key={name} className="w-28">
|
|
68
76
|
<AspectRatio ratio={1}>
|
|
69
|
-
<
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
77
|
+
<Card variant="muted" className="h-full w-full">
|
|
78
|
+
<CardContent flush>
|
|
79
|
+
<Flex align="center" justify="center" gap="xs">
|
|
80
|
+
<Text size="xs" tone="muted" className="text-center">
|
|
81
|
+
{name}
|
|
82
|
+
</Text>
|
|
83
|
+
</Flex>
|
|
84
|
+
</CardContent>
|
|
85
|
+
</Card>
|
|
74
86
|
</AspectRatio>
|
|
75
87
|
</div>
|
|
76
88
|
))}
|
|
@@ -90,9 +102,13 @@ export default function Demo() {
|
|
|
90
102
|
</CardHeader>
|
|
91
103
|
<CardContent>
|
|
92
104
|
<AspectRatio ratio={21 / 9}>
|
|
93
|
-
<
|
|
94
|
-
<
|
|
95
|
-
|
|
105
|
+
<Card variant="muted" className="h-full w-full">
|
|
106
|
+
<CardContent flush>
|
|
107
|
+
<Flex align="center" justify="center" gap="xs">
|
|
108
|
+
<Text tone="muted">月次売上推移グラフ(21:9)</Text>
|
|
109
|
+
</Flex>
|
|
110
|
+
</CardContent>
|
|
111
|
+
</Card>
|
|
96
112
|
</AspectRatio>
|
|
97
113
|
</CardContent>
|
|
98
114
|
</Card>
|
|
@@ -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.
|
package/docs/layout/flex.tsx
CHANGED
|
@@ -129,7 +129,8 @@ export default function Demo() {
|
|
|
129
129
|
direction="row"
|
|
130
130
|
gap="sm"
|
|
131
131
|
align={a}
|
|
132
|
-
className="bg-muted min-h-20 rounded-md
|
|
132
|
+
className="bg-muted min-h-20 rounded-md"
|
|
133
|
+
style={{ padding: "var(--space-2)" }}
|
|
133
134
|
>
|
|
134
135
|
<Text size="xs" tone="muted" className="w-16">
|
|
135
136
|
{a}
|
|
@@ -166,7 +167,8 @@ export default function Demo() {
|
|
|
166
167
|
gap="xs"
|
|
167
168
|
align="center"
|
|
168
169
|
justify={j}
|
|
169
|
-
className="bg-muted flex-1 rounded-md
|
|
170
|
+
className="bg-muted flex-1 rounded-md"
|
|
171
|
+
style={{ padding: "var(--space-2)" }}
|
|
170
172
|
>
|
|
171
173
|
<Badge variant="outline">借方</Badge>
|
|
172
174
|
<Badge variant="outline">貸方</Badge>
|
|
@@ -192,6 +194,7 @@ export default function Demo() {
|
|
|
192
194
|
<Text size="xs" tone="muted">
|
|
193
195
|
wrap={false}(既定)
|
|
194
196
|
</Text>
|
|
197
|
+
{/* ui-audit-disable-next-line no-utility-spacing — a tinted tile so the gap between children is visible; the box IS the subject */}
|
|
195
198
|
<Flex direction="row" gap="xs" wrap={false} className="bg-muted rounded-md p-2">
|
|
196
199
|
<Badge variant="outline">勘定科目</Badge>
|
|
197
200
|
<Badge variant="outline">補助科目</Badge>
|
|
@@ -202,6 +205,7 @@ export default function Demo() {
|
|
|
202
205
|
<Text size="xs" tone="muted">
|
|
203
206
|
wrap={true}
|
|
204
207
|
</Text>
|
|
208
|
+
{/* ui-audit-disable-next-line no-utility-spacing — a tinted tile so the gap between children is visible; the box IS the subject */}
|
|
205
209
|
<Flex direction="row" gap="xs" wrap className="bg-muted rounded-md p-2">
|
|
206
210
|
<Badge variant="outline">勘定科目</Badge>
|
|
207
211
|
<Badge variant="outline">補助科目</Badge>
|
|
@@ -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
|
+
}
|