@godxjp/ui 22.0.0 → 23.1.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/README.md +4 -4
- package/dist/app/date-format-labels.d.ts +14 -2
- package/dist/app/date-format-labels.js +1 -1
- package/dist/app/date-formats.d.ts +14 -2
- package/dist/app/date-formats.js +9 -2
- package/dist/components/data-display/data-table.d.ts +8 -1
- package/dist/components/data-display/data-table.js +9 -2
- package/dist/components/data-display/scroll-area.d.ts +24 -4
- package/dist/components/data-display/scroll-area.js +34 -72
- package/dist/components/data-entry/cascader.js +8 -6
- package/dist/components/data-entry/checkbox.js +3 -1
- package/dist/components/data-entry/choice-hit-target.d.ts +24 -0
- package/dist/components/data-entry/choice-hit-target.js +12 -0
- package/dist/components/data-entry/control-surface.d.ts +8 -0
- package/dist/components/data-entry/control-surface.js +10 -1
- package/dist/components/data-entry/form-field.js +5 -4
- package/dist/components/data-entry/input.js +1 -1
- package/dist/components/data-entry/number-input.js +27 -6
- package/dist/components/data-entry/radio.js +4 -3
- package/dist/components/data-entry/search-select.js +225 -95
- package/dist/components/data-entry/select.d.ts +76 -14
- package/dist/components/data-entry/select.js +495 -163
- package/dist/components/data-entry/slider.d.ts +3 -11
- package/dist/components/data-entry/slider.js +582 -93
- package/dist/components/data-entry/switch.js +3 -1
- package/dist/components/feedback/dialog.js +2 -2
- package/dist/components/feedback/sheet.js +2 -22
- package/dist/components/navigation/dropdown-menu.d.ts +11 -3
- package/dist/components/navigation/dropdown-menu.js +190 -15
- package/dist/components/navigation/filter-bar.js +2 -1
- package/dist/components/navigation/index.d.ts +0 -3
- package/dist/components/navigation/index.js +0 -78
- package/dist/components/navigation/tabs.js +16 -4
- package/dist/components/ui/index.d.ts +0 -3
- package/dist/components/ui/index.js +0 -3
- package/dist/components/ui/input-otp.d.ts +1 -1
- package/dist/components/ui/segmented.js +3 -1
- package/dist/components/ui/tag-input.js +3 -5
- package/dist/i18n/messages/en.json +5 -1
- package/dist/i18n/messages/ja.json +5 -1
- package/dist/i18n/messages/vi.json +5 -1
- package/dist/lib/breakpoint-token.d.ts +8 -0
- package/dist/lib/breakpoint-token.js +29 -0
- package/dist/lib/select-options.d.ts +21 -0
- package/dist/lib/select-options.js +46 -0
- package/dist/props/components/data-display.prop.d.ts +17 -7
- package/dist/props/components/data-entry.prop.d.ts +323 -30
- package/dist/props/components/index.d.ts +1 -1
- package/dist/props/components/navigation.prop.d.ts +25 -1
- package/dist/props/registry.d.ts +69 -1
- package/dist/props/registry.js +75 -0
- package/dist/props/vocabulary/data.prop.d.ts +5 -0
- package/dist/props/vocabulary/index.d.ts +1 -1
- package/dist/styles/control.css +246 -28
- package/dist/styles/data-display-layout.css +18 -10
- package/dist/styles/focus-ring.css +28 -0
- package/dist/styles/fonts.css +88 -4
- package/dist/styles/form-layout.css +4 -0
- package/dist/styles/layout.css +2 -1
- package/dist/styles/navigation-layout.css +24 -238
- package/dist/styles/shell-layout.css +148 -139
- package/dist/styles/table-layout.css +12 -5
- package/dist/tokens/components/control.css +12 -3
- package/dist/tokens/components/data-display.css +0 -5
- package/dist/tokens/components/navigation.css +5 -5
- package/dist/tokens/components/scroll-area.css +7 -0
- package/docs/CONSUMER-RULES.md +7 -2
- package/docs/CUSTOMER-THEMING.md +25 -9
- package/docs/DATETIME.md +11 -2
- package/docs/FRAME-COVERAGE-REPORT.md +4 -7
- package/docs/SPACING.md +35 -5
- package/docs/TOKENS.md +1 -1
- package/docs/data-display/data-table/index.tsx +44 -3
- package/docs/data-display/popover.tsx +4 -6
- package/docs/data-display/scroll-area.tsx +51 -45
- package/docs/data-display/table.tsx +1 -1
- package/docs/data-entry/date-picker.tsx +2 -3
- package/docs/data-entry/input-otp.tsx +5 -2
- package/docs/data-entry/segmented-in-filter-row.tsx +77 -0
- package/docs/data-entry/segmented.tsx +40 -1
- package/docs/data-entry/select-matrix.tsx +1 -2
- package/docs/data-entry/select.tsx +108 -3
- package/docs/data-entry/slider.tsx +125 -47
- package/docs/feedback/dialog.tsx +1 -2
- package/docs/feedback/sheet.tsx +1 -2
- package/docs/layout/app-shell-states.tsx +143 -0
- package/docs/navigation/dropdown-menu.tsx +77 -6
- package/docs/navigation/tabs.tsx +72 -0
- package/docs/roadmap/ai-chat-components.md +1 -2
- package/docs/roadmap/parity-audit-data-entry.md +44 -33
- package/docs/roadmap/parity-audit-layout-navigation-general.md +304 -310
- package/docs/roadmap/parity-backlog.md +2 -3
- package/docs/roadmap/tree-components.md +0 -1
- package/package.json +25 -55
- package/scripts/_agent-setup.mjs +18 -0
- package/scripts/guinea-pig-skill.md +12 -6
- package/scripts/ui-audit.mjs +185 -7
- package/scripts/visual-audit-rules.mjs +0 -7
- package/scripts/visual-audit.mjs +6 -27
- package/dist/components/navigation/context-menu.d.ts +0 -21
- package/dist/components/navigation/context-menu.js +0 -149
- package/dist/components/navigation/menubar.d.ts +0 -28
- package/dist/components/navigation/menubar.js +0 -136
- package/dist/components/navigation/navigation-menu.d.ts +0 -10
- package/dist/components/navigation/navigation-menu.js +0 -91
- package/dist/components/ui/context-menu.d.ts +0 -1
- package/dist/components/ui/context-menu.js +0 -2
- package/dist/components/ui/menubar.d.ts +0 -1
- package/dist/components/ui/menubar.js +0 -2
- package/dist/components/ui/navigation-menu.d.ts +0 -1
- package/dist/components/ui/navigation-menu.js +0 -2
- package/docs/FRAME-A11Y-CI.md +0 -349
- package/docs/navigation/context-menu.tsx +0 -128
- package/docs/navigation/menubar.tsx +0 -141
- package/docs/navigation/navigation-menu.tsx +0 -158
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
> Generated by `scripts/frame-coverage.mjs` (issue #163). Do not edit by hand — run `pnpm check:frame-coverage`.
|
|
4
4
|
> Standard: [FRAME-COVERAGE-STANDARD.md](./FRAME-COVERAGE-STANDARD.md). A missing dimension is **UNTESTED**, never a pass.
|
|
5
5
|
|
|
6
|
-
- Public components: **
|
|
7
|
-
- With ≥1 frame: **
|
|
6
|
+
- Public components: **135**
|
|
7
|
+
- With ≥1 frame: **130** · zero-frame: **5**
|
|
8
8
|
- Fully covered (every contract axis declared): **0**
|
|
9
9
|
|
|
10
10
|
## UNTESTED — no `/frame/**` route
|
|
@@ -74,7 +74,7 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
|
|
|
74
74
|
| Input | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
75
75
|
| NumberInput | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
76
76
|
| SearchInput | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
77
|
-
| Select | ✓ |
|
|
77
|
+
| Select | ✓ | · | · | · | · | · | · | · | · | · |
|
|
78
78
|
| Switch | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
79
79
|
| Textarea | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
80
80
|
| Label | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
|
|
@@ -91,7 +91,7 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
|
|
|
91
91
|
| Toaster | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
|
|
92
92
|
| Tabs | ✓ | ✓ | N/A | · | · | · | · | · | · | · |
|
|
93
93
|
| Pagination | ✓ | · | · | · | · | · | · | · | · | · |
|
|
94
|
-
| DropdownMenu | ✓ | N/A |
|
|
94
|
+
| DropdownMenu | ✓ | N/A | · | · | · | · | · | · | · | · |
|
|
95
95
|
| Steps | ✓ | ✓ | N/A | · | · | · | · | · | · | · |
|
|
96
96
|
| Toolbar | ✓ | N/A | · | N/A | · | · | · | · | · | · |
|
|
97
97
|
| AppProvider | ✓ | · | · | · | · | · | · | · | · | · |
|
|
@@ -128,9 +128,6 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
|
|
|
128
128
|
| Rating | ✓ | N/A | · | · | · | · | · | · | · | · |
|
|
129
129
|
| Segmented | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
130
130
|
| TagInput | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
131
|
-
| ContextMenu | ✓ | N/A | N/A | · | · | · | · | · | · | · |
|
|
132
|
-
| Menubar | ✓ | N/A | N/A | · | · | · | · | · | · | · |
|
|
133
|
-
| NavigationMenu | ✓ | N/A | N/A | · | · | · | · | · | · | · |
|
|
134
131
|
| ResizablePanel | ✓ | N/A | · | N/A | · | · | · | · | · | · |
|
|
135
132
|
| Carousel | ✓ | N/A | N/A | · | · | · | · | · | · | · |
|
|
136
133
|
| AppSettingPicker | ✓ | N/A | · | · | · | · | · | · | · | · |
|
package/docs/SPACING.md
CHANGED
|
@@ -42,11 +42,11 @@ Implementation: `src/tokens/base.css` (values) · layout owners: `src/styles/*-l
|
|
|
42
42
|
| `--card-space-body-y` | `--space-section-active` | Header↔body gap |
|
|
43
43
|
| `--card-space-header-y` / `--card-space-footer-y` | `--space-stack-sm` | Banded header + separated footer band |
|
|
44
44
|
|
|
45
|
-
| Component
|
|
46
|
-
|
|
|
47
|
-
| `StatCard`
|
|
48
|
-
| `CardContent solo`
|
|
49
|
-
| `CardContent flush
|
|
45
|
+
| Component | Use |
|
|
46
|
+
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
47
|
+
| `StatCard` | KPI / stat tile (`solo` path) |
|
|
48
|
+
| `CardContent solo` | Body-only card (same padding as `StatCard`) |
|
|
49
|
+
| `CardContent flush` | Edge-to-edge table/tabs in card — REQUIRED when the table IS the body (rule 10). `flush` alone drops the border, radius and inline padding; add `tight` only to change the HEADER band. |
|
|
50
50
|
|
|
51
51
|
See preview **Data Display → Card** for live examples.
|
|
52
52
|
|
|
@@ -64,6 +64,36 @@ Pick by AXIS, and note that the three do **not** share one value: each reads a d
|
|
|
64
64
|
|
|
65
65
|
Because `ui-card-inset-x` reads `--card-space-inset`, it follows the card it sits in: a `Card density="tight"` or `"cozy"` moves those cells with the shell. The other two read fixed steps (band and body) and do not.
|
|
66
66
|
|
|
67
|
+
## Control interiors are NOT on this scale
|
|
68
|
+
|
|
69
|
+
Everything above is the space **between** things — page sections, siblings in a stack, a card's
|
|
70
|
+
shell against its content. A control's **inside** is a different measurement and it is derived from
|
|
71
|
+
the control band (`--control-height`, `--control-padding-x`), never from `--space-*`. The two do not
|
|
72
|
+
meet, and reading a step off the table above as a minimum for a control's interior gives the wrong
|
|
73
|
+
answer.
|
|
74
|
+
|
|
75
|
+
The case that keeps coming up is `Segmented`'s track (gh#503). Its padding is **2px**, and the
|
|
76
|
+
label inside it therefore sits ~5px from the track's outer edge — under `--space-2` (8px), which is
|
|
77
|
+
NOT a floor this document sets for anything.
|
|
78
|
+
|
|
79
|
+
2px is the whole geometry of the control:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
label height = --control-height − track padding × 2 → 32 − 4 = 28
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
so the track measures **exactly** `--control-height` and a `Segmented` sits level with the `Input`
|
|
86
|
+
and the `Button` beside it on the same row. Raise the padding to 8px and one of two things has to
|
|
87
|
+
give: either the label band drops to 16px — a 14px type size in a 16px box, under every hit target
|
|
88
|
+
this library holds — or the track grows to 44px (28 + 8 × 2) and stops lining up with every other
|
|
89
|
+
control. The same derivation is why a `Button`'s own label sits ~5px inside its border. A control
|
|
90
|
+
is sized by its band; the band is what a dense enterprise UI is for.
|
|
91
|
+
|
|
92
|
+
**The knob, if a service wants a roomier control.** `--segmented-track-padding` is a published
|
|
93
|
+
component token (`src/tokens/components/segmented.css`); raising it re-derives the item height from
|
|
94
|
+
the same formula, so the track stays exactly one control tall. Do not reach for a Tailwind `p-*` on
|
|
95
|
+
the control — the audit rejects it, and it would break the identity above.
|
|
96
|
+
|
|
67
97
|
## MCP
|
|
68
98
|
|
|
69
99
|
`get_pattern page-sections` (a page of Cards, spaced by the page) · `get_rule 40` (mobile-first spacing) · `list_audit_rules` (the spacing rules the CLI enforces).
|
package/docs/TOKENS.md
CHANGED
|
@@ -220,7 +220,7 @@ The census confirmed the number and rejected the diagnosis: **`width` is not one
|
|
|
220
220
|
|
|
221
221
|
**Px, never rem.** A stroke is a _device_ line: its job is to read as one crisp rule at any type size, so it must not grow when the root font-size does. Every token that moved onto this scale was already `px` for that reason; a `rem` thickness (`--slider-track-height: 0.375rem`) is a different decision and stayed where it was. **Not `--scaling`-multiplied** either — `--scaling` is a density knob, and a 1px divider at 0.92px would blur rather than tighten.
|
|
222
222
|
|
|
223
|
-
`--focus-ring-
|
|
223
|
+
The focus mark reads this scale too, through `--focus-ring-weight` — `var(--focus-outline-weight)`, which is `var(--stroke-hairline)` (the light 1px mark the ON state ships). `--focus-ring-width` is DERIVED from it (`weight × --focus-outline`, the on/off switch) and must never be set directly; a theme that wants a 2px focus perimeter (WCAG 2.2 SC 2.4.13) sets `--focus-ring-weight: var(--stroke-md)`. See docs/CUSTOMER-THEMING.md.
|
|
224
224
|
|
|
225
225
|
#### `--band-height-*` — the vertical extent of a horizontal band
|
|
226
226
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useMemo, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import { AppProvider } from "@godxjp/ui/app";
|
|
4
|
-
import { Badge, DataTable, type ColumnDef } from "@godxjp/ui/data-display";
|
|
4
|
+
import { Badge, Card, CardContent, DataTable, type ColumnDef } from "@godxjp/ui/data-display";
|
|
5
5
|
import { Button, Text } from "@godxjp/ui/general";
|
|
6
6
|
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
7
7
|
import {
|
|
@@ -93,6 +93,16 @@ const columns: ColumnDef<Invoice>[] = [
|
|
|
93
93
|
},
|
|
94
94
|
];
|
|
95
95
|
|
|
96
|
+
/* Five 240px columns: wider than the frame at every viewport the gates sweep, and wide for a
|
|
97
|
+
* reason no font can change — the width is declared, so the overflow is deterministic in CI. */
|
|
98
|
+
const wideColumns: ColumnDef<Invoice>[] = [
|
|
99
|
+
{ key: "id", header: "請求書番号", width: "240px" },
|
|
100
|
+
{ key: "partner", header: "取引先", width: "240px" },
|
|
101
|
+
{ key: "amount", header: "金額", align: "right", width: "240px" },
|
|
102
|
+
{ key: "status", header: "状態", width: "240px" },
|
|
103
|
+
{ key: "date", header: "期限日", width: "240px" },
|
|
104
|
+
];
|
|
105
|
+
|
|
96
106
|
export default function Demo() {
|
|
97
107
|
const [selected, setSelected] = useState<Set<string>>(new Set(["INV-0311"]));
|
|
98
108
|
const [sort, setSort] = useState<SortStateProp | undefined>({
|
|
@@ -117,6 +127,22 @@ export default function Demo() {
|
|
|
117
127
|
subtitle="sortable · selectable · bulk actions · row actions · loading · clickable rows · empty state"
|
|
118
128
|
>
|
|
119
129
|
<Flex direction="col" gap="lg">
|
|
130
|
+
{/* A table WIDER than its frame, inside a flush Card — the shape a list page uses. It must
|
|
131
|
+
scroll inside its own box with the fade at the inline end, never cut its last columns
|
|
132
|
+
(WCAG 1.4.10). `check:data-table-overflow` measures this section. */}
|
|
133
|
+
<Flex direction="col" gap="sm" id="wide-overflow" className="max-w-3xl">
|
|
134
|
+
<Text weight="medium">枠より広い表(横スクロール · 列を切らない)</Text>
|
|
135
|
+
<Card>
|
|
136
|
+
<CardContent flush>
|
|
137
|
+
<DataTable
|
|
138
|
+
data={invoices}
|
|
139
|
+
columns={wideColumns}
|
|
140
|
+
getRowId={(row) => row.id}
|
|
141
|
+
selectable
|
|
142
|
+
/>
|
|
143
|
+
</CardContent>
|
|
144
|
+
</Card>
|
|
145
|
+
</Flex>
|
|
120
146
|
<Flex direction="col" gap="sm" id="text-action-width">
|
|
121
147
|
<Text weight="medium">日本語の行アクション</Text>
|
|
122
148
|
<DataTable
|
|
@@ -264,13 +290,28 @@ export default function Demo() {
|
|
|
264
290
|
</AppProvider>
|
|
265
291
|
</Flex>
|
|
266
292
|
|
|
267
|
-
<Flex direction="col" gap="sm">
|
|
293
|
+
<Flex direction="col" gap="sm" id="empty-builtin">
|
|
268
294
|
<Text as="div" weight="medium">
|
|
269
295
|
空の状態(data が空のとき自動表示)
|
|
270
296
|
</Text>
|
|
271
297
|
<DataTable data={[]} columns={columns} getRowId={(row) => row.id} />
|
|
272
298
|
</Flex>
|
|
273
299
|
|
|
300
|
+
{/* The SAME cell with consumer content in it. `empty` takes a ReactNode, so a plain string
|
|
301
|
+
is a legal call — and the lifecycle cell used to be `padding: 0`, which put that string
|
|
302
|
+
flush against the table's edge. Measured here; see check:data-table-empty-inset. */}
|
|
303
|
+
<Flex direction="col" gap="sm" id="empty-plain-string">
|
|
304
|
+
<Text as="div" weight="medium">
|
|
305
|
+
空の状態(empty に文字列を渡す)
|
|
306
|
+
</Text>
|
|
307
|
+
<DataTable
|
|
308
|
+
data={[]}
|
|
309
|
+
columns={columns}
|
|
310
|
+
getRowId={(row) => row.id}
|
|
311
|
+
empty="まだ登録がありません"
|
|
312
|
+
/>
|
|
313
|
+
</Flex>
|
|
314
|
+
|
|
274
315
|
{/* — the two failure states, in the same table grid as empty/loading. */}
|
|
275
316
|
<Flex direction="col" gap="sm">
|
|
276
317
|
<Text as="div" weight="medium">
|
|
@@ -292,7 +333,7 @@ export default function Demo() {
|
|
|
292
333
|
<DataTable data={[]} columns={columns} getRowId={(row) => row.id} error />
|
|
293
334
|
</Flex>
|
|
294
335
|
|
|
295
|
-
<Flex direction="col" gap="sm">
|
|
336
|
+
<Flex direction="col" gap="sm" id="error-custom-node">
|
|
296
337
|
<Text as="div" weight="medium">
|
|
297
338
|
エラー(error にノードを渡して文言を差し替え)
|
|
298
339
|
</Text>
|
|
@@ -135,10 +135,7 @@ export default function Demo() {
|
|
|
135
135
|
<Flex direction="row" wrap gap="sm">
|
|
136
136
|
<Popover>
|
|
137
137
|
<PopoverTrigger asChild>
|
|
138
|
-
|
|
139
|
-
<Button data-axe-open variant="outline">
|
|
140
|
-
side=top
|
|
141
|
-
</Button>
|
|
138
|
+
<Button variant="outline">side=top</Button>
|
|
142
139
|
</PopoverTrigger>
|
|
143
140
|
<PopoverContent side="top" aria-label="上側の配置例">
|
|
144
141
|
<PopoverDescription>上に開きます。</PopoverDescription>
|
|
@@ -215,8 +212,9 @@ export default function Demo() {
|
|
|
215
212
|
<CardDescription>
|
|
216
213
|
既定の panel は --popover-width(18rem)。auto は中身に測らせます — 自前の幅を持つもの
|
|
217
214
|
(Calendar、チャート、固定幅のプレビュー)はこれ以外に正解がありません。trigger
|
|
218
|
-
はアンカーに合わせます。className に w-*
|
|
219
|
-
retune できません。flush が padding
|
|
215
|
+
はアンカーに合わせます。className に w-*
|
|
216
|
+
を書くのは呼び出し側の定数で、どのテーマからも retune できません。flush が padding
|
|
217
|
+
側で避けているのと同じ話です。
|
|
220
218
|
</CardDescription>
|
|
221
219
|
</CardHeader>
|
|
222
220
|
<CardContent>
|
|
@@ -14,10 +14,10 @@ import { Button, Text } from "@godxjp/ui/general";
|
|
|
14
14
|
import { Flex, PageContainer, ResponsiveGrid } from "@godxjp/ui/layout";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* ScrollArea —
|
|
18
|
-
* (vertical) or width (horizontal)
|
|
19
|
-
* `
|
|
20
|
-
*
|
|
17
|
+
* ScrollArea — a native scrolling box. ALWAYS give it an explicit height/max-height
|
|
18
|
+
* (vertical) or width (horizontal), or nothing ever overflows and no scrollbar appears.
|
|
19
|
+
* `orientation` decides which axes may scroll; the browser draws the bar, styled from
|
|
20
|
+
* the --scroll-area-* tokens. Composed only from real @godxjp/ui components.
|
|
21
21
|
*/
|
|
22
22
|
const entries = Array.from(
|
|
23
23
|
{ length: 18 },
|
|
@@ -97,7 +97,7 @@ export default function Demo() {
|
|
|
97
97
|
return (
|
|
98
98
|
<PageContainer
|
|
99
99
|
title="ScrollArea"
|
|
100
|
-
subtitle="
|
|
100
|
+
subtitle="Native scrolling, token-styled scrollbar · needs an explicit height"
|
|
101
101
|
>
|
|
102
102
|
<Flex direction="col" gap="lg">
|
|
103
103
|
<Card>
|
|
@@ -115,7 +115,6 @@ export default function Demo() {
|
|
|
115
115
|
anchor="bottom"
|
|
116
116
|
viewportRef={streamViewport}
|
|
117
117
|
onAnchoredChange={setAnchored}
|
|
118
|
-
type="always"
|
|
119
118
|
>
|
|
120
119
|
<CardContent>
|
|
121
120
|
<Flex direction="col">
|
|
@@ -173,7 +172,7 @@ export default function Demo() {
|
|
|
173
172
|
<CardContent>
|
|
174
173
|
<Card variant="outline" className="h-40 w-full">
|
|
175
174
|
<CardContent flush>
|
|
176
|
-
<ScrollArea anchor="bottom" anchorOffset={0}
|
|
175
|
+
<ScrollArea anchor="bottom" anchorOffset={0}>
|
|
177
176
|
<CardContent>
|
|
178
177
|
<Flex direction="col" gap="xs">
|
|
179
178
|
{entries.map((e) => (
|
|
@@ -215,40 +214,13 @@ export default function Demo() {
|
|
|
215
214
|
</CardContent>
|
|
216
215
|
</Card>
|
|
217
216
|
|
|
218
|
-
<Card>
|
|
219
|
-
<CardHeader>
|
|
220
|
-
<CardTitle level={2}>type="always"(バーを常時表示)</CardTitle>
|
|
221
|
-
<CardDescription>
|
|
222
|
-
既定の hover はホバー時のみバーを表示します。always
|
|
223
|
-
は内容が溢れる限りバーを常に表示します。
|
|
224
|
-
</CardDescription>
|
|
225
|
-
</CardHeader>
|
|
226
|
-
<CardContent>
|
|
227
|
-
<Card variant="outline" className="h-56 w-full">
|
|
228
|
-
<CardContent flush>
|
|
229
|
-
<ScrollArea type="always">
|
|
230
|
-
<CardContent>
|
|
231
|
-
<Flex direction="col" gap="xs">
|
|
232
|
-
{entries.map((e) => (
|
|
233
|
-
<div key={e} className="text-sm tabular-nums">
|
|
234
|
-
{e}
|
|
235
|
-
</div>
|
|
236
|
-
))}
|
|
237
|
-
</Flex>
|
|
238
|
-
</CardContent>
|
|
239
|
-
</ScrollArea>
|
|
240
|
-
</CardContent>
|
|
241
|
-
</Card>
|
|
242
|
-
</CardContent>
|
|
243
|
-
</Card>
|
|
244
|
-
|
|
245
217
|
<Card>
|
|
246
218
|
<CardHeader>
|
|
247
219
|
<CardTitle level={2}>ScrollArea</CardTitle>
|
|
248
220
|
<CardDescription>orientation="horizontal"</CardDescription>
|
|
249
221
|
</CardHeader>
|
|
250
222
|
<CardContent>
|
|
251
|
-
<ScrollArea orientation="horizontal"
|
|
223
|
+
<ScrollArea orientation="horizontal">
|
|
252
224
|
<ResponsiveGrid flow="columns">
|
|
253
225
|
{columns.map((column) => (
|
|
254
226
|
<Card key={column}>
|
|
@@ -264,17 +236,51 @@ export default function Demo() {
|
|
|
264
236
|
|
|
265
237
|
<Card>
|
|
266
238
|
<CardHeader>
|
|
267
|
-
<CardTitle level={2}
|
|
239
|
+
<CardTitle level={2}>ScrollBar は何も描画しない(非推奨)</CardTitle>
|
|
240
|
+
<CardDescription>
|
|
241
|
+
v22 まではこの要素を置くことが軸を開く方法だったが、スクロールがブラウザ本来のものに
|
|
242
|
+
なったので ScrollBar は何も描画しない。下のカードには ScrollBar
|
|
243
|
+
が置いてあるが、横に動くのは orientation="both" のおかげで、ScrollBar
|
|
244
|
+
のおかげではない。残っている <ScrollBar> は消して、軸は orientation で宣言する。
|
|
245
|
+
</CardDescription>
|
|
246
|
+
</CardHeader>
|
|
247
|
+
<CardContent>
|
|
248
|
+
<Card variant="outline" className="h-24 w-full">
|
|
249
|
+
<CardContent flush>
|
|
250
|
+
<ScrollArea orientation="both">
|
|
251
|
+
<ResponsiveGrid flow="columns">
|
|
252
|
+
{columns.map((column) => (
|
|
253
|
+
<Text key={column}>{column}</Text>
|
|
254
|
+
))}
|
|
255
|
+
</ResponsiveGrid>
|
|
256
|
+
<ScrollBar orientation="horizontal" />
|
|
257
|
+
</ScrollArea>
|
|
258
|
+
</CardContent>
|
|
259
|
+
</Card>
|
|
260
|
+
</CardContent>
|
|
261
|
+
</Card>
|
|
262
|
+
|
|
263
|
+
<Card>
|
|
264
|
+
<CardHeader>
|
|
265
|
+
<CardTitle level={2}>両方向スクロール(orientation="both")</CardTitle>
|
|
266
|
+
<CardDescription>
|
|
267
|
+
縦にも横にも溢れうる面は orientation="both"。以前は縦の ScrollArea に
|
|
268
|
+
ScrollBar を足して横軸を開けていたが、スクロールはブラウザ本来のものになったので、
|
|
269
|
+
軸を決めるのは orientation だけになった。
|
|
270
|
+
</CardDescription>
|
|
268
271
|
</CardHeader>
|
|
269
272
|
<CardContent>
|
|
270
|
-
<
|
|
271
|
-
<
|
|
272
|
-
|
|
273
|
-
<
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
273
|
+
<Card variant="outline" className="h-32 w-full">
|
|
274
|
+
<CardContent flush>
|
|
275
|
+
<ScrollArea orientation="both">
|
|
276
|
+
<ResponsiveGrid flow="columns">
|
|
277
|
+
{columns.map((column) => (
|
|
278
|
+
<Text key={column}>{column}</Text>
|
|
279
|
+
))}
|
|
280
|
+
</ResponsiveGrid>
|
|
281
|
+
</ScrollArea>
|
|
282
|
+
</CardContent>
|
|
283
|
+
</Card>
|
|
278
284
|
</CardContent>
|
|
279
285
|
</Card>
|
|
280
286
|
|
|
@@ -288,7 +294,7 @@ export default function Demo() {
|
|
|
288
294
|
<CardContent>
|
|
289
295
|
<Card variant="outline" className="h-56 w-full">
|
|
290
296
|
<CardContent flush>
|
|
291
|
-
<ScrollArea
|
|
297
|
+
<ScrollArea>
|
|
292
298
|
<CardContent>
|
|
293
299
|
<Flex direction="col" gap="xs">
|
|
294
300
|
{shortEntries.map((e) => (
|
|
@@ -181,7 +181,7 @@ export default function Demo() {
|
|
|
181
181
|
full frame. The suppression above is scoped to a flush body, never to `bordered`.
|
|
182
182
|
</CardDescription>
|
|
183
183
|
</CardHeader>
|
|
184
|
-
<CardContent>
|
|
184
|
+
<CardContent flush>
|
|
185
185
|
<Table bordered>
|
|
186
186
|
<TableHeader>
|
|
187
187
|
<TableRow>
|
|
@@ -41,8 +41,7 @@ export default function Demo() {
|
|
|
41
41
|
形式に整形され、 解釈できない入力は元の値へ復帰する。
|
|
42
42
|
</CardDescription>
|
|
43
43
|
</CardHeader>
|
|
44
|
-
|
|
45
|
-
<CardContent data-axe-open>
|
|
44
|
+
<CardContent>
|
|
46
45
|
<FormField id="issue-date" label="発行日" required>
|
|
47
46
|
<DatePicker
|
|
48
47
|
id="issue-date"
|
|
@@ -288,7 +287,7 @@ export default function Demo() {
|
|
|
288
287
|
ISO 送信される。 開始 > 終了で入力しても order (既定 true) が昇順に正規化する。
|
|
289
288
|
</CardDescription>
|
|
290
289
|
</CardHeader>
|
|
291
|
-
<CardContent
|
|
290
|
+
<CardContent>
|
|
292
291
|
<FormField id="period" label="会計期間" required>
|
|
293
292
|
<DatePicker
|
|
294
293
|
range
|
|
@@ -38,8 +38,11 @@ export default function Demo() {
|
|
|
38
38
|
<CardDescription>6スロット 1グループ · ペースト・矢印キー操作に対応。</CardDescription>
|
|
39
39
|
</CardHeader>
|
|
40
40
|
<CardContent>
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
{/* この行の id は FIELD ではなく CONTROL 側にある。FormField はその id をそのまま
|
|
42
|
+
使い、ラベルのクリックもその id を見る(gh#477:以前は FormField 自身の id を
|
|
43
|
+
見ていたので、両者が食い違った瞬間にラベルがどこも指さなくなった)。 */}
|
|
44
|
+
<FormField label="認証コード" required>
|
|
45
|
+
<InputOTP id="email-otp" maxLength={6} value={emailCode} onChange={setEmailCode}>
|
|
43
46
|
<InputOTPGroup>
|
|
44
47
|
<InputOTPSlot index={0} />
|
|
45
48
|
<InputOTPSlot index={1} />
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Badge,
|
|
3
|
+
Card,
|
|
4
|
+
CardContent,
|
|
5
|
+
CardDescription,
|
|
6
|
+
CardHeader,
|
|
7
|
+
CardTitle,
|
|
8
|
+
} from "@godxjp/ui/data-display";
|
|
9
|
+
import { Segmented } from "@godxjp/ui/data-entry";
|
|
10
|
+
import { Button, Text } from "@godxjp/ui/general";
|
|
11
|
+
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The composition a consumer actually filters a list with: a Segmented that carries a count badge
|
|
15
|
+
* per option, sharing a WRAPPING flex row with the other filter controls, inside a Card.
|
|
16
|
+
*
|
|
17
|
+
* It is a separate frame from `segmented.tsx` because the row is the variable. `#four-with-counts`
|
|
18
|
+
* over there puts the track directly in a CardContent, where it is a block box and shrinks to the
|
|
19
|
+
* column; here it is a FLEX ITEM, and a flex item's `min-inline-size` defaults to `auto` — its
|
|
20
|
+
* max-content width — so nothing makes it give ground to the row.
|
|
21
|
+
*/
|
|
22
|
+
const OPTIONS = [
|
|
23
|
+
{ value: "all", label: "すべて", count: 133 },
|
|
24
|
+
{ value: "ginou", label: "技能実習", count: 82 },
|
|
25
|
+
{ value: "tokutei", label: "特定技能", count: 51 },
|
|
26
|
+
{ value: "ikusei", label: "育成就労", count: 0 },
|
|
27
|
+
].map(({ value, label, count }) => ({
|
|
28
|
+
value,
|
|
29
|
+
label: (
|
|
30
|
+
<>
|
|
31
|
+
{label}
|
|
32
|
+
<Badge as="span" variant="secondary">
|
|
33
|
+
{count}
|
|
34
|
+
</Badge>
|
|
35
|
+
</>
|
|
36
|
+
),
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
export default function SegmentedInFilterRow() {
|
|
40
|
+
return (
|
|
41
|
+
<PageContainer title="Segmented in a filter row" subtitle="4 択 + 件数バッジ · Flex wrap の中">
|
|
42
|
+
<Card id="four-in-wrap-row">
|
|
43
|
+
<CardHeader>
|
|
44
|
+
<CardTitle level={2}>制度の絞り込み</CardTitle>
|
|
45
|
+
<CardDescription>
|
|
46
|
+
`check:segmented-wrap` がこのカードも測ります。トラックは行の中でも縮み、393px
|
|
47
|
+
でラベルも件数も切り詰めません。
|
|
48
|
+
</CardDescription>
|
|
49
|
+
</CardHeader>
|
|
50
|
+
<CardContent>
|
|
51
|
+
<Flex gap="sm" align="center" wrap>
|
|
52
|
+
<Segmented aria-label="制度" defaultValue="all" options={OPTIONS} />
|
|
53
|
+
<Button variant="outline" size="sm">
|
|
54
|
+
絞り込みを解除
|
|
55
|
+
</Button>
|
|
56
|
+
</Flex>
|
|
57
|
+
</CardContent>
|
|
58
|
+
</Card>
|
|
59
|
+
|
|
60
|
+
<Card id="four-in-wrap-row-alone">
|
|
61
|
+
<CardHeader>
|
|
62
|
+
<CardTitle level={2}>同じトラック、行の中に一つだけ</CardTitle>
|
|
63
|
+
<CardDescription>
|
|
64
|
+
<Text size="sm" tone="muted">
|
|
65
|
+
兄弟が無くても行は行。フレックス項目としての縮み方を切り分けるための対照。
|
|
66
|
+
</Text>
|
|
67
|
+
</CardDescription>
|
|
68
|
+
</CardHeader>
|
|
69
|
+
<CardContent>
|
|
70
|
+
<Flex gap="sm" align="center" wrap>
|
|
71
|
+
<Segmented aria-label="制度(単独)" defaultValue="all" options={OPTIONS} />
|
|
72
|
+
</Flex>
|
|
73
|
+
</CardContent>
|
|
74
|
+
</Card>
|
|
75
|
+
</PageContainer>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
Badge,
|
|
5
|
+
Card,
|
|
6
|
+
CardContent,
|
|
7
|
+
CardDescription,
|
|
8
|
+
CardHeader,
|
|
9
|
+
CardTitle,
|
|
10
|
+
} from "@godxjp/ui/data-display";
|
|
4
11
|
import { FormField, Segmented } from "@godxjp/ui/data-entry";
|
|
5
12
|
import { Text, VisuallyHidden } from "@godxjp/ui/general";
|
|
6
13
|
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
@@ -84,6 +91,38 @@ export default function Demo() {
|
|
|
84
91
|
</CardContent>
|
|
85
92
|
</Card>
|
|
86
93
|
|
|
94
|
+
<Card id="four-with-counts">
|
|
95
|
+
<CardHeader>
|
|
96
|
+
<CardTitle level={2}>4 択 + 件数(スマホ幅では折り返す)</CardTitle>
|
|
97
|
+
<CardDescription>
|
|
98
|
+
一覧の上の状態フィルター。4 つが 1 行に収まらない幅では、トラックが 2 行目に折り返し
|
|
99
|
+
ます — ラベルも件数も切り詰めません。`check:segmented-wrap` がこのカードを測ります。
|
|
100
|
+
</CardDescription>
|
|
101
|
+
</CardHeader>
|
|
102
|
+
<CardContent>
|
|
103
|
+
<Segmented
|
|
104
|
+
aria-label="状態"
|
|
105
|
+
defaultValue="all"
|
|
106
|
+
options={[
|
|
107
|
+
{ value: "all", label: "すべて", count: 128 },
|
|
108
|
+
{ value: "active", label: "実習中", count: 96 },
|
|
109
|
+
{ value: "pending", label: "申請中", count: 12 },
|
|
110
|
+
{ value: "gone", label: "失踪・帰国", count: 0 },
|
|
111
|
+
].map(({ value, label, count }) => ({
|
|
112
|
+
value,
|
|
113
|
+
label: (
|
|
114
|
+
<>
|
|
115
|
+
{label}
|
|
116
|
+
<Badge as="span" variant="secondary">
|
|
117
|
+
{count}
|
|
118
|
+
</Badge>
|
|
119
|
+
</>
|
|
120
|
+
),
|
|
121
|
+
}))}
|
|
122
|
+
/>
|
|
123
|
+
</CardContent>
|
|
124
|
+
</Card>
|
|
125
|
+
|
|
87
126
|
<Card>
|
|
88
127
|
<CardHeader>
|
|
89
128
|
<CardTitle level={2}>size · vertical · block</CardTitle>
|
|
@@ -142,8 +142,7 @@ 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
|
-
|
|
146
|
-
<CardContent data-axe-open>
|
|
145
|
+
<CardContent>
|
|
147
146
|
<FormField
|
|
148
147
|
id="searchable-invalid"
|
|
149
148
|
label="担当拠点"
|