@godxjp/ui 28.12.0 → 29.0.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/agent/START-HERE.md +29 -10
- package/agent/components/Anchor.json +6 -1
- package/agent/components/AppLauncher.json +10 -0
- package/agent/components/AppShell.json +1 -1
- package/agent/components/AreaChart.json +19 -1
- package/agent/components/Attachments.json +26 -1
- package/agent/components/BarChart.json +11 -1
- package/agent/components/BranchScopePicker.json +10 -0
- package/agent/components/Cascader.json +6 -1
- package/agent/components/Checkbox.json +6 -0
- package/agent/components/CompactBarTrend.json +1 -1
- package/agent/components/CredentialReveal.json +21 -0
- package/agent/components/DataState.json +1 -1
- package/agent/components/DataTable.json +4 -4
- package/agent/components/FormField.json +1 -1
- package/agent/components/InfiniteQueryState.json +1 -1
- package/agent/components/Input.json +1 -1
- package/agent/components/InputOTP.json +35 -0
- package/agent/components/LineChart.json +20 -2
- package/agent/components/ListRow.json +1 -1
- package/agent/components/Masonry.json +1 -1
- package/agent/components/MasterDetail.json +1 -1
- package/agent/components/PasswordStrength.json +1 -1
- package/agent/components/PermissionMatrix.json +6 -1
- package/agent/components/SearchInput.json +5 -0
- package/agent/components/Select.json +1 -0
- package/agent/components/ServiceRolePanel.json +5 -0
- package/agent/components/Sidebar.json +1 -1
- package/agent/components/Switch.json +6 -0
- package/agent/components/Table.json +8 -3
- package/agent/components/Tabs.json +10 -0
- package/agent/components/ThemeScope.json +49 -0
- package/agent/components/TimeRangePicker.json +5 -0
- package/agent/components/Topbar.json +1 -0
- package/agent/components/TopbarItem.json +2 -1
- package/agent/components/Transfer.json +6 -1
- package/agent/components/TreeSelect.json +1 -1
- package/agent/components/Upload.json +5 -0
- package/agent/components/UploadCropDialog.json +1 -1
- package/agent/components/formatDate.json +1 -1
- package/agent/components-index.json +5 -0
- package/agent/components.json +297 -31
- package/agent/index.json +19 -9
- package/agent/llms.txt +10 -10
- package/agent/patterns/tenant-brand-color.json +28 -0
- package/agent/patterns-index.json +27 -0
- package/agent/patterns.json +28 -0
- package/agent/rules.json +15 -0
- package/agent/tokens.json +4965 -970
- package/dist/app/index.d.ts +3 -0
- package/dist/app/index.js +3 -0
- package/dist/app/tenant-theme.d.ts +80 -0
- package/dist/app/tenant-theme.js +154 -0
- package/dist/app/theme-axes.d.ts +14 -1
- package/dist/app/theme-axes.js +24 -31
- package/dist/components/charts/chart-cartesian.d.ts +5 -1
- package/dist/components/charts/chart-cartesian.js +15 -8
- package/dist/components/data-display/badge.d.ts +1 -1
- package/dist/components/data-display/badge.js +20 -2
- package/dist/components/data-display/carousel.js +4 -4
- package/dist/components/data-display/data-table.js +13 -2
- package/dist/components/data-display/permission-matrix.js +1 -1
- package/dist/components/data-display/table.d.ts +11 -2
- package/dist/components/data-display/table.js +18 -2
- package/dist/components/data-entry/control-appearance.d.ts +12 -6
- package/dist/components/data-entry/control-appearance.js +1 -1
- package/dist/components/data-entry/select.js +4 -3
- package/dist/components/feedback/dialog.js +6 -3
- package/dist/components/feedback/overlay-header-tone.d.ts +7 -0
- package/dist/components/feedback/overlay-header-tone.js +4 -4
- package/dist/components/feedback/sheet.d.ts +1 -1
- package/dist/components/feedback/sheet.js +6 -9
- package/dist/components/feedback/sonner.js +16 -3
- package/dist/components/general/button.js +22 -5
- package/dist/components/layout/affix.js +15 -1
- package/dist/components/layout/sidebar.js +7 -1
- package/dist/components/navigation/anchor.d.ts +1 -1
- package/dist/components/navigation/anchor.js +5 -4
- package/dist/components/navigation/app-setting-picker.js +1 -1
- package/dist/components/navigation/pagination.js +1 -1
- package/dist/components/navigation/tabs.js +15 -2
- package/dist/components/query/infinite-query-state.d.ts +22 -6
- package/dist/contracts/measurement.json +1 -1
- package/dist/i18n/messages/en.json +0 -697
- package/dist/i18n/messages/ja.json +0 -691
- package/dist/i18n/messages/vi.json +0 -691
- package/dist/lib/control-styles.d.ts +31 -11
- package/dist/lib/control-styles.js +6 -6
- package/dist/lib/overlay-portal.d.ts +20 -0
- package/dist/lib/overlay-portal.js +93 -0
- package/dist/props/components/app.prop.d.ts +12 -0
- package/dist/props/components/charts.prop.d.ts +30 -0
- package/dist/props/components/index.d.ts +1 -1
- package/dist/props/components/navigation.prop.d.ts +21 -2
- package/dist/props/components/query.prop.d.ts +36 -2
- package/dist/props/registry.d.ts +46 -1
- package/dist/props/registry.js +38 -3
- package/dist/styles/alert-layout.css +34 -14
- package/dist/styles/badge-layout.css +10 -6
- package/dist/styles/base.css +14 -5
- package/dist/styles/card-layout.css +19 -8
- package/dist/styles/chart-layout.css +22 -3
- package/dist/styles/control.css +165 -59
- package/dist/styles/data-display-layout.css +129 -36
- package/dist/styles/data-entry-layout.css +23 -87
- package/dist/styles/dialog-layout.css +49 -19
- package/dist/styles/float-button-layout.css +5 -5
- package/dist/styles/focus-ring.css +9 -5
- package/dist/styles/layout.css +42 -15
- package/dist/styles/logo-layout.css +1 -1
- package/dist/styles/motion.css +1 -1
- package/dist/styles/navigation-layout.css +90 -29
- package/dist/styles/shell-layout.css +63 -40
- package/dist/styles/table-layout.css +56 -17
- package/dist/styles/text-layout.css +13 -4
- package/dist/styles/toggle.css +8 -2
- package/dist/tokens/components/actions.css +1 -1
- package/dist/tokens/components/attachments.css +4 -4
- package/dist/tokens/components/badge.css +4 -4
- package/dist/tokens/components/callout.css +1 -1
- package/dist/tokens/components/card.css +9 -4
- package/dist/tokens/components/chart.css +10 -1
- package/dist/tokens/components/chat-bubble.css +1 -1
- package/dist/tokens/components/control.css +28 -10
- package/dist/tokens/components/conversations.css +2 -1
- package/dist/tokens/components/data-display.css +12 -7
- package/dist/tokens/components/descriptions.css +1 -1
- package/dist/tokens/components/draggable-panel.css +1 -1
- package/dist/tokens/components/feedback.css +28 -8
- package/dist/tokens/components/float-button.css +1 -1
- package/dist/tokens/components/legal-document.css +1 -1
- package/dist/tokens/components/logo.css +1 -1
- package/dist/tokens/components/mega-menu.css +5 -3
- package/dist/tokens/components/navigation.css +21 -7
- package/dist/tokens/components/segmented.css +8 -3
- package/dist/tokens/components/shell.css +19 -5
- package/dist/tokens/components/table.css +9 -1
- package/dist/tokens/components/thought-chain.css +1 -1
- package/dist/tokens/components/toggle.css +2 -0
- package/dist/tokens/components/tree.css +3 -1
- package/dist/tokens/components/upload.css +6 -6
- package/dist/tokens/components/welcome.css +1 -1
- package/dist/tokens/foundation.css +28 -1
- package/docs/COMPOSITION-VS-COMPONENT.md +31 -0
- package/docs/CUSTOMER-THEMING.md +637 -1
- package/docs/DESIGN-AUTHORITY.md +13 -0
- package/docs/FRAME-COVERAGE-REPORT.md +3 -2
- package/docs/GLASSMORPHISM-STANDARD.md +196 -0
- package/docs/THEME-API-COVERAGE.md +538 -0
- package/docs/TOKEN-RESOLUTION.md +195 -0
- package/docs/TOKENS.md +63 -24
- package/docs/asset-modules.d.ts +7 -0
- package/docs/data-display/charts.tsx +80 -0
- package/docs/data-display/data-table/index.tsx +30 -0
- package/docs/data-display/popover.tsx +1 -1
- package/docs/data-display/table.tsx +52 -0
- package/docs/feedback/sheet.tsx +10 -10
- package/docs/foundation/density.tsx +4 -4
- package/docs/i18n/messages/en.json +1201 -0
- package/docs/i18n/messages/ja.json +1195 -0
- package/docs/i18n/messages/vi.json +1195 -0
- package/docs/layout/account-chip.tsx +2 -2
- package/docs/layout/responsive-grid.tsx +1 -1
- package/docs/navigation/toolbar.tsx +20 -12
- package/docs/providers/theme-scope.tsx +186 -0
- package/docs/showcase/caimono-price-comparison.tsx +911 -0
- package/docs/showcase/case4-login.tsx +2 -2
- package/docs/showcase/marketing-page.tsx +3 -2
- package/docs/showcase/permission-matrix.tsx +13 -5
- package/docs/showcase/table-pagination.tsx +2 -1
- package/docs/showcase/tenant-brand-color.tsx +338 -0
- package/docs/showcase/theme-customization.tsx +2 -1
- package/docs/showcase/theme-lab.tsx +2125 -0
- package/docs/themes/flat.css +462 -0
- package/docs/themes/glassmorphism.css +958 -0
- package/docs/themes/index.ts +200 -0
- package/package.json +4 -3
- package/scripts/explain-token.mjs +382 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Token resolution — who overrides whom, and how to prove it
|
|
2
|
+
|
|
3
|
+
This document exists because of one complaint: _"rất nhiều chỗ cứ đè cấu hình lung tung làm ảnh
|
|
4
|
+
hưởng component này sang component khác"_ — configuration overriding configuration until changing
|
|
5
|
+
one component moves another. That is a real failure mode and prose does not settle it, so this
|
|
6
|
+
page is **an order, a rule, and a tool**. The tool is `scripts/explain-token.mjs`.
|
|
7
|
+
|
|
8
|
+
Nothing here is invented. Ant Design v5 settled this problem years ago and its vocabulary is used
|
|
9
|
+
throughout; where this package lacks one of Ant Design's layers, that is said plainly rather than
|
|
10
|
+
papered over with a new word.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 1. The order
|
|
15
|
+
|
|
16
|
+
**Yes, the chain is what you said.** For a value at a given element, strongest first:
|
|
17
|
+
|
|
18
|
+
| # | layer | in this package | Ant Design equivalent |
|
|
19
|
+
| --- | ----------------- | -------------------------------------------------------------- | ------------------------------------------ |
|
|
20
|
+
| 1 | **instance** | `style={{ "--card-radius": "…" }}` on the element | a component prop / `<Component style>` |
|
|
21
|
+
| 2 | **nearest scope** | `[data-tenant]`, `.dark`, `[data-density]`, any region wrapper | the **nearest** `ConfigProvider theme` |
|
|
22
|
+
| 3 | **global** | `:root` in the app's own `theme.css` | the outermost `ConfigProvider theme.token` |
|
|
23
|
+
| 4 | **default** | `:root` in `src/tokens/**` | `theme.defaultAlgorithm` seed |
|
|
24
|
+
|
|
25
|
+
There is no bespoke machinery here: a CSS custom property is resolved by the ordinary cascade, so
|
|
26
|
+
"nearest scope wins" is just inheritance, and "the app's `theme.css` beats the package" is just the
|
|
27
|
+
layer contract — **unlayered CSS outranks every `@layer`**, and everything this package ships is
|
|
28
|
+
layered (`docs/TOKENS.md` · The layer contract).
|
|
29
|
+
|
|
30
|
+
Between 2 and 3 there is no ambiguity to resolve: an override on a wrapper is _nearer_ to the
|
|
31
|
+
element than `:root`, so it wins by inheritance, not by specificity. Two scopes on the same element
|
|
32
|
+
are ordinary cascade — higher specificity, then later.
|
|
33
|
+
|
|
34
|
+
## 2. The four tiers — Ant Design's model, and the one layer we do not have
|
|
35
|
+
|
|
36
|
+
Ant Design v5: **Seed → Map → Alias → Component**. This package:
|
|
37
|
+
|
|
38
|
+
| Ant Design | here | file | count |
|
|
39
|
+
| ------------------------------------ | ----------- | ----------------------------- | ----- |
|
|
40
|
+
| **Seed Token** | foundation | `src/tokens/foundation.css` | 201 |
|
|
41
|
+
| **Map Token** (derived by algorithm) | — _partial_ | `src/tokens/derived.css` | — |
|
|
42
|
+
| **Alias Token** | semantic | `src/tokens/semantic/*.css` | 92 |
|
|
43
|
+
| **Component Token** | component | `src/tokens/components/*.css` | 1688 |
|
|
44
|
+
|
|
45
|
+
**The Map layer is PARTIAL, not missing** — an earlier draft of this page said "missing" and Codex
|
|
46
|
+
was right to reject it. `derived.css` really is a Map layer for the brand ramp: `--ring`,
|
|
47
|
+
`--primary-hover` and `--primary-active` are computed from `--primary` with relative colour, which
|
|
48
|
+
is derivation by algorithm in the sense Ant Design means. Foundation mixes seed and derived too —
|
|
49
|
+
the spacing steps are `calc(<n> * var(--scaling))` (`foundation.css:673`) and the shadows derive
|
|
50
|
+
from `--shadow-color` (`foundation.css:290`).
|
|
51
|
+
|
|
52
|
+
What is genuinely thin is its **reach**: the hover knobs are themselves `initial`, the destructive
|
|
53
|
+
states are authored literals (`derived.css:136`), and the `@supports not (color: hsl(from …))`
|
|
54
|
+
branch hands older engines literals that stop following the seed altogether (`derived.css:188`).
|
|
55
|
+
That last one is why `tenantTheme()` (gh#868) computes hover/pressed in JavaScript — not because
|
|
56
|
+
there was no algorithm layer, but because the one that exists does not survive an engine without
|
|
57
|
+
relative colour.
|
|
58
|
+
|
|
59
|
+
A previous draft also claimed the thin Map layer is _why_ the component tier needs 1688 tokens.
|
|
60
|
+
That is unsupported and has been removed: deriving defaults does not remove the need for
|
|
61
|
+
independently overridable component knobs, which is what most of those 1688 are.
|
|
62
|
+
|
|
63
|
+
## 3. The rule that makes the order work — and silently breaks it
|
|
64
|
+
|
|
65
|
+
`var()` substitutes **where it is declared**, not where it is read.
|
|
66
|
+
|
|
67
|
+
```css
|
|
68
|
+
/* BROKEN — the chain is dead at step 2 */
|
|
69
|
+
:root {
|
|
70
|
+
--card-border-color: var(--border);
|
|
71
|
+
}
|
|
72
|
+
.ui-card {
|
|
73
|
+
border-color: var(--card-border-color);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`--card-border-color` resolves against the **root's** `--border`, once. A `[data-tenant]` below
|
|
78
|
+
root that sets its own `--border` can never reach it: the binding already happened higher up. Step
|
|
79
|
+
2 of the chain exists, and for that token it does nothing.
|
|
80
|
+
|
|
81
|
+
```css
|
|
82
|
+
/* CORRECT — knob is `initial`, formula at the CALL SITE */
|
|
83
|
+
:root {
|
|
84
|
+
--card-border-color: initial;
|
|
85
|
+
}
|
|
86
|
+
.ui-card {
|
|
87
|
+
border-color: var(--card-border-color, hsl(var(--border)));
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Now the fallback is evaluated **at `.ui-card`**, where the scope is in effect, so the tenant's
|
|
92
|
+
`--border` is the one that arrives — and an explicit `--card-border-color` still overrides it.
|
|
93
|
+
|
|
94
|
+
This package has paid for that distinction seven times: gh#687, gh#843, gh#848, gh#866 and others.
|
|
95
|
+
It is the single most common cause of "I overrode the token and nothing happened."
|
|
96
|
+
|
|
97
|
+
## 4. The tool
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
node node_modules/@godxjp/ui/scripts/explain-token.mjs --card-radius # one token: every declaration, every read
|
|
101
|
+
node node_modules/@godxjp/ui/scripts/explain-token.mjs --table # a whole family
|
|
102
|
+
node node_modules/@godxjp/ui/scripts/explain-token.mjs --audit # every freeze, orphan and unpublished token
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
(From inside this repo's own checkout, drop the `node_modules/@godxjp/ui/` prefix.)
|
|
106
|
+
|
|
107
|
+
For one token it prints every declaration site — marked `root-only` or `below root` — with its
|
|
108
|
+
selector, its value, and whether it is a freeze; then every read and whether that read carries a
|
|
109
|
+
call-site fallback. If two components move together, run it on the token they share and the shared
|
|
110
|
+
declaration is on the screen.
|
|
111
|
+
|
|
112
|
+
**It does not compute a winner, and says so.** The first version ranked selectors into four
|
|
113
|
+
"cascade" buckets by regex and printed them strongest-last. Codex found that `@theme inline` and
|
|
114
|
+
`[dir="rtl"] .ui-actions[data-fade-in-inline]` both scored top precedence on the substring
|
|
115
|
+
`inline`, that `:root[data-brand="crm"]` was filed as a descendant scope, and that "strongest last"
|
|
116
|
+
sorted by alphabetical filename. A tool meant to settle override disputes that invents precedence
|
|
117
|
+
is worse than no tool. `root-only` is the one property it can prove, and it is the only one the
|
|
118
|
+
freeze test needs. `--audit` ends with the four things it cannot see; read them before treating a
|
|
119
|
+
clean run as proof.
|
|
120
|
+
|
|
121
|
+
### What `--audit` reports today
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
2090 declared · 1973 published · 641 frozen · 6 orphan reads
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
- **frozen (641)** — a root-only binding whose source is restated somewhere below root. The naive
|
|
128
|
+
test ("any `:root` binding that reads a token") reports **1028**, and a list that long is one
|
|
129
|
+
nobody reads; `--actions-gap: var(--space-1)` only matters because `--space-1` really is
|
|
130
|
+
restated. The scoped set is derived on every run, never hand-listed — a hand-kept list is what
|
|
131
|
+
went blind in gh#854. It counts **any** declaration below root, not just theme-looking scopes:
|
|
132
|
+
`.ui-page-container` inside `@media (max-width: 720px)` restates `--space-section-active`
|
|
133
|
+
(`layout.css:992`) while `--card-space-inset` binds it at `:root` (`card.css:6`), so below 720px
|
|
134
|
+
a Card keeps the root's inset. An earlier, narrower version of this test missed exactly that.
|
|
135
|
+
- **orphan reads (6)** — `var(--x)` where `--x` is declared nowhere and no fallback is given.
|
|
136
|
+
- **unpublished (117)** — declared in CSS but absent from `agent/tokens.json`, so a consumer cannot
|
|
137
|
+
discover them. From the consumer's point of view these are hard-coded. `--card-accent-color` is
|
|
138
|
+
one: six call-site declarations, zero documentation.
|
|
139
|
+
|
|
140
|
+
## 5. Rules for anyone adding or changing a token
|
|
141
|
+
|
|
142
|
+
1. **Declare it in the tier it belongs to.** Component tokens go in `src/tokens/components/<name>.css`,
|
|
143
|
+
named `--{component}-{part}-{property}`; `check:token-tiers` enforces the shape.
|
|
144
|
+
2. **A knob that mirrors a role is `initial` + a call-site fallback.** Never a `:root` binding.
|
|
145
|
+
See §3. If you are unsure whether it mirrors a role, run `explain-token.mjs` on the role and see
|
|
146
|
+
whether any scope restates it.
|
|
147
|
+
3. **Do not write another component's token from your own rule — with one qualified exception.**
|
|
148
|
+
Writing `--badge-*` from a Card rule is the literal shape of "changing one component moves
|
|
149
|
+
another," and that is the default answer.
|
|
150
|
+
|
|
151
|
+
The exception is a **composition default**: a child whose geometry legitimately differs when it
|
|
152
|
+
sits inside a particular parent. `control.css:313` does exactly this — a count Badge inside a
|
|
153
|
+
boxed Button gets `--badge-space-y: 0` and a tighter radius, because a chip in a button is not a
|
|
154
|
+
standalone status chip. That is correct, and an earlier draft of this rule would have forbidden
|
|
155
|
+
it.
|
|
156
|
+
|
|
157
|
+
To qualify, all three must hold: the boundary is **documented** at the rule; the child's tokens
|
|
158
|
+
are **public**, so the relationship is inspectable; and a per-instance override on the child
|
|
159
|
+
still **wins**. The descendant selector deserves scrutiny of its own — `control.css:313` reaches
|
|
160
|
+
every nested Badge, not just a direct child — but that is a scoping question, not grounds to ban
|
|
161
|
+
composition.
|
|
162
|
+
|
|
163
|
+
4. **Publish it.** A token absent from `agent/tokens.json` is not part of the API, whatever the
|
|
164
|
+
stylesheet says. `pnpm regen` does this; `check:agent-catalog` verifies it.
|
|
165
|
+
5. **A consumer sets tokens, never selectors.** App CSS targeting `[data-slot]`, `[data-priority]`
|
|
166
|
+
or `.ui-*` is unlayered and therefore outranks every package layer at every width, including the
|
|
167
|
+
responsive re-points — which is how a page-local fix becomes a library-wide regression.
|
|
168
|
+
6. **A theme that makes a surface translucent owns its own `prefers-reduced-transparency` and
|
|
169
|
+
`@supports not (backdrop-filter)` fallbacks.** The library cannot write them on the theme's
|
|
170
|
+
behalf — it does not know what opaque colour the theme wants, and guessing at one role's own
|
|
171
|
+
colour is not safe: `docs/themes/glassmorphism.css` sets `--card: 0 0% 100% / 42%`, so a fallback
|
|
172
|
+
that fell back to `hsl(var(--card))` would still be 42% translucent. Both branches stay
|
|
173
|
+
custom-property overrides on the theme's own selector, same shape as rule 5.
|
|
174
|
+
|
|
175
|
+
7. **A scoped theme cannot re-ink text it does not own the `color` of.** `src/styles/base.css`
|
|
176
|
+
sets `color: hsl(var(--foreground))` on `body`, above every scope, so that `var()` substitutes
|
|
177
|
+
once against the root and everything below inherits the resolved colour — the §3 freeze rule
|
|
178
|
+
applied to a PROPERTY rather than a token, and worse there, because a token can be given a knob
|
|
179
|
+
and `color` on `body` has none to give. `ThemeScope` re-states it on itself and on the
|
|
180
|
+
body-level overlay host, so a region wrapped in one re-inks correctly (gh#881). **A plain
|
|
181
|
+
wrapper themed by a stylesheet must state `color: hsl(var(--foreground))` on its own element
|
|
182
|
+
too** — that is the consumer's own element, not a selector into this package, so rule 5 permits
|
|
183
|
+
it.
|
|
184
|
+
|
|
185
|
+
## 6. What is not yet true
|
|
186
|
+
|
|
187
|
+
The owner's second question was whether **every smallest element** is configurable. It is not, and
|
|
188
|
+
the measurement is in `docs/THEME-API-COVERAGE.md`. Two known shapes of failure:
|
|
189
|
+
|
|
190
|
+
- a painted property written as a literal, with no token at all;
|
|
191
|
+
- a property written as `var(--x)` where `--x` is unpublished — reachable in principle, invisible
|
|
192
|
+
in practice.
|
|
193
|
+
|
|
194
|
+
Both are counted there per component. This page describes how resolution _works_; that one says how
|
|
195
|
+
far it currently _reaches_.
|
package/docs/TOKENS.md
CHANGED
|
@@ -44,17 +44,18 @@ src/styles/
|
|
|
44
44
|
|
|
45
45
|
Default brand tokens use the GodX Agent Portal palette: navy primary, 朱 orange focus/accent, warm neutral surfaces. App or customer identity colors belong in the consuming app theme, not in package tokens.
|
|
46
46
|
|
|
47
|
-
#### The
|
|
47
|
+
#### The four tone tiers — FILL, TEXT, MARK, SURFACE
|
|
48
48
|
|
|
49
|
-
A status tone can be painted
|
|
49
|
+
A status tone can be painted four ways, and each way is judged against a different thing. Reading
|
|
50
50
|
the wrong tier is this palette's most expensive recurring bug, because nothing about it looks wrong
|
|
51
51
|
in the source.
|
|
52
52
|
|
|
53
|
-
| Tier
|
|
54
|
-
|
|
|
55
|
-
| **FILL**
|
|
56
|
-
| **TEXT**
|
|
57
|
-
| **MARK**
|
|
53
|
+
| Tier | Tokens | What it paints | Contrast bar |
|
|
54
|
+
| ----------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
|
|
55
|
+
| **FILL** | `--success`, `--warning`, `--info`, `--destructive` | A solid chip, band or bar with a label ON it | AA **4.5:1** against its own `*-foreground` label |
|
|
56
|
+
| **TEXT** | `--text-success`, `--text-warning`, `--text-info`, `--text-error` | Small coloured type — a StatCard delta, an outline badge label, a field's error line | AA **4.5:1** against the surface BEHIND it |
|
|
57
|
+
| **MARK** | `--mark-success`, `--mark-warning`, `--mark-info`, `--mark-destructive`, `--mark-primary`, `--mark-attention` | A thin shape carrying meaning with nothing written on it — a `Card accent` rail, a `DataTable rowTone` rail | SC 1.4.11 **3:1** against the surface it sits on |
|
|
58
|
+
| **SURFACE** | `--surface-success`, `--surface-warning`, `--surface-info`, `--surface-destructive` | The pale GROUND a toned surface paints — an `Alert` tint, a status `Badge` chip, a toned `DataTable` row, a toast, a `ChatBubble`, a toned Dialog/Sheet header, an `EmptyState` medallion | whatever sits ON it must clear AA **4.5:1** — see below |
|
|
58
59
|
|
|
59
60
|
The MARK tier exists because both rails were reading FILL, and two of them were effectively
|
|
60
61
|
invisible. Measured in Chromium on the light card: `Card accent="warning"` drew its 6px rail at
|
|
@@ -66,6 +67,44 @@ place and both follow — and since 3:1 is looser than 4.5:1, anything legible a
|
|
|
66
67
|
a mark by construction. `--mark-attention` is the exception: there is no `--text-attention`, and
|
|
67
68
|
the fill already clears the floor in both themes (3.32 / 6.75).
|
|
68
69
|
|
|
70
|
+
**The SURFACE tier is `initial` and has no default of its own (gh#866).** The other three tiers
|
|
71
|
+
hold a colour; this one holds a brand's ANSWER, and there is no single derived value it could
|
|
72
|
+
carry — Alert washes at 5%, Badge at 10%, the row tone at 6%, the medallion at 12%, the toast
|
|
73
|
+
`color-mix`es into `--popover`. So each surface keeps its own formula AT ITS CALL SITE, behind the
|
|
74
|
+
role:
|
|
75
|
+
|
|
76
|
+
```css
|
|
77
|
+
background-color: var(--surface-success, hsl(var(--success) / var(--alert-bg-alpha)));
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Unset, every surface paints exactly what it painted before (measured in Chromium: 30/30 computed
|
|
81
|
+
values byte-identical). Set on a scope — `[data-tenant] { --surface-success: #E8F5EF }` — all nine
|
|
82
|
+
follow, because the formula lives where the paint happens rather than at `:root`; the same probe
|
|
83
|
+
measured 0/30 before the roles existed and 30/30 after.
|
|
84
|
+
|
|
85
|
+
The tier exists because DERIVATION TIES THE GROUND'S HUE TO THE INK. A brand kit that pairs
|
|
86
|
+
`--success #126342` with `--success-soft #E8F5EF` is not describing a derivation: #E8F5EF is a
|
|
87
|
+
separately chosen mint, not that green at any alpha, and the only move the system offered was to
|
|
88
|
+
lighten the success TEXT until its wash matched — damaging the ink's contrast to fix the colour of
|
|
89
|
+
the ground.
|
|
90
|
+
|
|
91
|
+
**A brand's ground is the brand's contrast problem, and these are the numbers to check.** Everything
|
|
92
|
+
this library paints ON a status surface reads the TEXT tier — the Alert icon and title, the Badge
|
|
93
|
+
label (`text-*-strong`), the toast ink — and on the kit's four grounds that measures success
|
|
94
|
+
**6.22:1** · warning **5.48:1** · error **6.64:1** · info **7.34:1**, with body ink
|
|
95
|
+
(`--foreground`) at 13.9–14.4:1. All four clear AA, so the role is safe to hand a brand.
|
|
96
|
+
|
|
97
|
+
The one thing that does NOT is the Callout RAIL, which is the FILL tier by design (a 4px rail at
|
|
98
|
+
the border alpha reads as a smudge): against the brand grounds it measures success **1.99:1** and
|
|
99
|
+
warning **1.62:1**, under SC 1.4.11's 3:1. That is inherited, not introduced — on today's derived
|
|
100
|
+
tint the same rail measures **2.12:1** and **1.69:1** — and the repair is the MARK tier, not a
|
|
101
|
+
lighter ground.
|
|
102
|
+
|
|
103
|
+
`primary` and `attention` have no SURFACE entry on purpose: a brand ships "soft" pairs for the four
|
|
104
|
+
statuses, and two more roles nobody asked for make the vocabulary harder to learn. Borders stay
|
|
105
|
+
derived too (`--alert-border-alpha`, `--chat-bubble-tone-border-alpha`) — the kit supplies no border
|
|
106
|
+
colours.
|
|
107
|
+
|
|
69
108
|
Two guards, because one was not enough:
|
|
70
109
|
`src/tokens/__tests__/tone-mark-contrast.test.ts` recomputes every tone × ground × theme off the
|
|
71
110
|
committed tokens and reads the alias out of the CSS (so repointing a mark back at FILL fails the
|
|
@@ -75,20 +114,20 @@ gate had ever looked at one.
|
|
|
75
114
|
|
|
76
115
|
**Progress and Legend joined the tier, and the wa-iro question is settled.** `.ui-legend-swatch`,
|
|
77
116
|
`.ui-progress-bar` and `.ui-progress-segment` all read FILL as standalone graphics and all failed
|
|
78
|
-
the same floor. The floor applies: nothing is written on a progress fill, so
|
|
79
|
-
|
|
117
|
+
the same floor. The floor applies: nothing is written on a progress fill, so _where the colour
|
|
118
|
+
stops_ is the entire datum, and a slice of a partition carries its share of the whole with no words
|
|
80
119
|
on it — that is precisely a "graphical object required to understand the content". The hue loses.
|
|
81
120
|
The two moved together because a swatch is a SAMPLE of the bar beside it; a key that is not the
|
|
82
121
|
colour it is a key to is not a key.
|
|
83
122
|
|
|
84
|
-
| surface
|
|
85
|
-
|
|
|
86
|
-
| `.ui-legend-swatch`
|
|
87
|
-
| `.ui-legend-swatch`
|
|
88
|
-
| `.ui-legend-swatch`
|
|
89
|
-
| `.ui-progress-segment` | warning
|
|
90
|
-
| `.ui-progress-segment` | success
|
|
91
|
-
| `.ui-progress-segment` | destructive | dark track
|
|
123
|
+
| surface | tone | ground | FILL (before) | MARK (after) |
|
|
124
|
+
| ---------------------- | ----------- | ----------- | ------------- | ------------ |
|
|
125
|
+
| `.ui-legend-swatch` | warning | light card | **1.74** | **5.90** |
|
|
126
|
+
| `.ui-legend-swatch` | success | light card | **2.18** | **6.84** |
|
|
127
|
+
| `.ui-legend-swatch` | destructive | dark card | **2.95** | **5.52** |
|
|
128
|
+
| `.ui-progress-segment` | warning | light track | **1.60** | **5.41** |
|
|
129
|
+
| `.ui-progress-segment` | success | light track | **2.00** | **6.28** |
|
|
130
|
+
| `.ui-progress-segment` | destructive | dark track | **2.42** | **4.52** |
|
|
92
131
|
|
|
93
132
|
Worst case anywhere on the two routes after the move: **4.52:1**. `.ui-progress-bar` (meter and
|
|
94
133
|
over-capacity) reads the same tokens as the slice, so a `tone="warning"` meter and a `warning`
|
|
@@ -101,10 +140,10 @@ failure — was on `text-destructive`, the FILL utility. So the same `tone` was
|
|
|
101
140
|
`Alert` and near-invisible one line below it, in the field that caused it. Measured in Chromium on
|
|
102
141
|
`/isolate/layout-auth-recovery-examples-mfa-challenge`:
|
|
103
142
|
|
|
104
|
-
| surface
|
|
105
|
-
|
|
|
106
|
-
| `.ui-form-field-note[role="alert"]` | dark card
|
|
107
|
-
| `.ui-form-field-note[role="alert"]` | light card | 6.16
|
|
143
|
+
| surface | ground | FILL (before) | TEXT (after) |
|
|
144
|
+
| ----------------------------------- | ---------- | ------------- | ------------ |
|
|
145
|
+
| `.ui-form-field-note[role="alert"]` | dark card | **2.95** | **5.52** |
|
|
146
|
+
| `.ui-form-field-note[role="alert"]` | light card | 6.16 | **7.21** |
|
|
108
147
|
|
|
109
148
|
Only the DARK branch failed, and the light one passing is why it survived: the fill is tuned for a
|
|
110
149
|
white label ON it, so it darkens on light grounds and lightens on dark ones — the opposite of what
|
|
@@ -114,13 +153,13 @@ two `ui-auth-shell` routes it had never loaded.
|
|
|
114
153
|
|
|
115
154
|
**A theme that repoints `--secondary` owes `--progress-track-background`.** The track defaults to
|
|
116
155
|
`hsl(var(--secondary))`, which is a pale neutral in the stock palette. `docs/showcase/acme-portal`
|
|
117
|
-
repurposes `--secondary` as a navy
|
|
156
|
+
repurposes `--secondary` as a navy _button_ colour, so its bars were drawn on a near-black track
|
|
118
157
|
and the mark fills measured 2.50 (success) / 2.90 (warning) on it. Naming the track explicitly is
|
|
119
158
|
the fix — 6.49 / 5.59 after — not dragging the tier back.
|
|
120
159
|
|
|
121
160
|
Three guards now, and each sees something the others cannot: the ratio tests in
|
|
122
161
|
`tone-mark-contrast.test.ts` (rails against card/background, progress marks against the track);
|
|
123
|
-
the
|
|
162
|
+
the _same file's_ CSS-alias assertions, which fail if a rule is repointed at the fill tier and
|
|
124
163
|
which also pin the swatch and the slice to the **same** token per tone; and `check:contrast`'s
|
|
125
164
|
**thin fill** pass — added because adding `/isolate/data-display-progress` to that gate's route
|
|
126
165
|
list on its own changed nothing at all. The graphic pass wants ≤24px on both axes and the rail
|
|
@@ -209,7 +248,7 @@ A system with only tier 1 turns every exception into a hack (`!important`, a glo
|
|
|
209
248
|
|
|
210
249
|
An inline custom property wins by **inheritance proximity**, not specificity, so it beats the `:root` default without any weight games. What keeps the route open is that every icon rule in `src/styles` reads its token through `var()` with no baked literal — `src/tokens/__tests__/icon-size-scale.test.ts` asserts exactly that, and carries a shrink-only list of the rules that still bake a literal and are therefore unreachable from an app.
|
|
211
250
|
|
|
212
|
-
The
|
|
251
|
+
The two left need tokens in `components/control.css` (`.ui-otp-separator-icon`) and `components/shell.css` (`.tb-icon-btn svg`).
|
|
213
252
|
|
|
214
253
|
**Before you add a step:** if a value is wanted in two places it belongs on the scale, and if it is wanted in one it does not. Adding a tenth step to serve a single call site is how a scale stops meaning anything.
|
|
215
254
|
|
package/docs/asset-modules.d.ts
CHANGED
|
@@ -44,3 +44,10 @@ declare module "*.gif" {
|
|
|
44
44
|
const src: string;
|
|
45
45
|
export default src;
|
|
46
46
|
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* A docs-owned theme stylesheet, imported for its side effect (e.g. `docs/themes/*.css`) —
|
|
50
|
+
* exactly like `preview/src/*.css`. There is nothing to type; the import exists only so the
|
|
51
|
+
* bundler includes the file.
|
|
52
|
+
*/
|
|
53
|
+
declare module "*.css";
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
1
2
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@godxjp/ui/data-display";
|
|
2
3
|
import { Flex, PageContainer, ResponsiveGrid } from "@godxjp/ui/layout";
|
|
3
4
|
import { AreaChart, BarChart, LineChart, PieChart } from "@godxjp/ui/charts";
|
|
5
|
+
import { useTranslation } from "@godxjp/ui/i18n";
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* Charts — tree-shaken `@godxjp/ui/charts` entry (needs the `recharts` optional
|
|
@@ -42,7 +44,18 @@ const sparseRevenue = [
|
|
|
42
44
|
|
|
43
45
|
const jpy = { style: "currency", currency: "JPY" } as const;
|
|
44
46
|
|
|
47
|
+
/** 生鮮品の相場推移 — 値そのものではなく「形」が意味を持つ連続値 (gh#865)。 */
|
|
48
|
+
const priceHistory = [
|
|
49
|
+
{ week: "第1週", price: 25400 },
|
|
50
|
+
{ week: "第2週", price: 26800 },
|
|
51
|
+
{ week: "第3週", price: 26100 },
|
|
52
|
+
{ week: "第4週", price: 28300 },
|
|
53
|
+
{ week: "第5週", price: 27600 },
|
|
54
|
+
{ week: "第6週", price: 29900 },
|
|
55
|
+
];
|
|
56
|
+
|
|
45
57
|
export default function Demo() {
|
|
58
|
+
const { t } = useTranslation();
|
|
46
59
|
return (
|
|
47
60
|
<PageContainer
|
|
48
61
|
title="Charts"
|
|
@@ -192,6 +205,73 @@ export default function Demo() {
|
|
|
192
205
|
</CardContent>
|
|
193
206
|
</Card>
|
|
194
207
|
</ResponsiveGrid>
|
|
208
|
+
|
|
209
|
+
<ResponsiveGrid columns={2}>
|
|
210
|
+
<Card>
|
|
211
|
+
<CardHeader>
|
|
212
|
+
<CardTitle level={2}>{t("chartsDocs.areaSplitTitle")}</CardTitle>
|
|
213
|
+
<CardDescription>{t("chartsDocs.areaSplitBody")}</CardDescription>
|
|
214
|
+
</CardHeader>
|
|
215
|
+
<CardContent>
|
|
216
|
+
<AreaChart
|
|
217
|
+
label={t("chartsDocs.areaSplitLabel")}
|
|
218
|
+
description={t("chartsDocs.areaSplitDescription")}
|
|
219
|
+
data={priceHistory}
|
|
220
|
+
categoryKey="week"
|
|
221
|
+
series={[
|
|
222
|
+
{
|
|
223
|
+
dataKey: "price",
|
|
224
|
+
label: t("chartsDocs.priceSeries"),
|
|
225
|
+
color: "var(--chart-5)",
|
|
226
|
+
fillColor: "var(--chart-3)",
|
|
227
|
+
},
|
|
228
|
+
]}
|
|
229
|
+
valueDomain={[24000, 31000]}
|
|
230
|
+
valueTicks={[24000, 26000, 28000, 30000]}
|
|
231
|
+
numberFormat={jpy}
|
|
232
|
+
showLegend={false}
|
|
233
|
+
showDots
|
|
234
|
+
curved
|
|
235
|
+
/>
|
|
236
|
+
</CardContent>
|
|
237
|
+
</Card>
|
|
238
|
+
|
|
239
|
+
<Card>
|
|
240
|
+
<CardHeader>
|
|
241
|
+
<CardTitle level={2}>{t("chartsDocs.tokenScopeTitle")}</CardTitle>
|
|
242
|
+
<CardDescription>{t("chartsDocs.tokenScopeBody")}</CardDescription>
|
|
243
|
+
</CardHeader>
|
|
244
|
+
<CardContent>
|
|
245
|
+
<Flex
|
|
246
|
+
direction="col"
|
|
247
|
+
style={
|
|
248
|
+
{
|
|
249
|
+
"--chart-series-stroke-width": "3",
|
|
250
|
+
"--chart-area-fill-alpha": "0.07",
|
|
251
|
+
"--chart-grid-line-dash": "none",
|
|
252
|
+
} as React.CSSProperties
|
|
253
|
+
}
|
|
254
|
+
>
|
|
255
|
+
<AreaChart
|
|
256
|
+
label={t("chartsDocs.tokenScopeLabel")}
|
|
257
|
+
data={priceHistory}
|
|
258
|
+
categoryKey="week"
|
|
259
|
+
series={[
|
|
260
|
+
{
|
|
261
|
+
dataKey: "price",
|
|
262
|
+
label: t("chartsDocs.priceSeries"),
|
|
263
|
+
color: "var(--chart-5)",
|
|
264
|
+
},
|
|
265
|
+
]}
|
|
266
|
+
valueDomain={[24000, 31000]}
|
|
267
|
+
numberFormat={jpy}
|
|
268
|
+
showLegend={false}
|
|
269
|
+
curved
|
|
270
|
+
/>
|
|
271
|
+
</Flex>
|
|
272
|
+
</CardContent>
|
|
273
|
+
</Card>
|
|
274
|
+
</ResponsiveGrid>
|
|
195
275
|
</Flex>
|
|
196
276
|
</PageContainer>
|
|
197
277
|
);
|
|
@@ -3,6 +3,7 @@ import { useMemo, useState } from "react";
|
|
|
3
3
|
import { AppProvider } from "@godxjp/ui/app";
|
|
4
4
|
import { Badge, Card, CardContent, DataTable, type ColumnDef } from "@godxjp/ui/data-display";
|
|
5
5
|
import { Button, Text } from "@godxjp/ui/general";
|
|
6
|
+
import { useTranslation } from "@godxjp/ui/i18n";
|
|
6
7
|
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
7
8
|
import {
|
|
8
9
|
DropdownMenu,
|
|
@@ -110,6 +111,7 @@ export default function Demo() {
|
|
|
110
111
|
direction: "desc",
|
|
111
112
|
});
|
|
112
113
|
const [density, setDensity] = useState<DensityProp>("comfortable");
|
|
114
|
+
const { t } = useTranslation();
|
|
113
115
|
|
|
114
116
|
const rows = useMemo(() => {
|
|
115
117
|
if (!sort) return invoices;
|
|
@@ -166,6 +168,34 @@ export default function Demo() {
|
|
|
166
168
|
getRowId={(row) => row.id}
|
|
167
169
|
/>
|
|
168
170
|
</Flex>
|
|
171
|
+
{/* The RECORD collection — a wide, heterogeneous record set. The fold is a CONTAINER
|
|
172
|
+
query, not a viewport one, so the same table folds by the width it is GIVEN: the two
|
|
173
|
+
blocks below are one component and one column list, rendered wide and narrow.
|
|
174
|
+
|
|
175
|
+
Below `collapseBelow` the header row hides and every `<tr>` becomes a bordered
|
|
176
|
+
key-value card. The per-cell labels are DERIVED from the same `ColumnDef.header` the
|
|
177
|
+
`<th>` uses (gh#864) — one declaration, so the card can never drift from the table it
|
|
178
|
+
collapsed out of, and the value that loses its header keeps its name. */}
|
|
179
|
+
<Flex direction="col" gap="sm" id="stacked-record-collection">
|
|
180
|
+
<Text weight="medium">{t("dataTableDocs.stackedRecordWide")}</Text>
|
|
181
|
+
<DataTable
|
|
182
|
+
preset="stacked-record-collection"
|
|
183
|
+
collapseBelow="sm"
|
|
184
|
+
data={invoices}
|
|
185
|
+
columns={columns}
|
|
186
|
+
getRowId={(row) => row.id}
|
|
187
|
+
/>
|
|
188
|
+
</Flex>
|
|
189
|
+
<Flex direction="col" gap="sm" id="stacked-record-collection-folded" className="max-w-xs">
|
|
190
|
+
<Text weight="medium">{t("dataTableDocs.stackedRecordFolded")}</Text>
|
|
191
|
+
<DataTable
|
|
192
|
+
preset="stacked-record-collection"
|
|
193
|
+
collapseBelow="sm"
|
|
194
|
+
data={invoices}
|
|
195
|
+
columns={columns}
|
|
196
|
+
getRowId={(row) => row.id}
|
|
197
|
+
/>
|
|
198
|
+
</Flex>
|
|
169
199
|
{/* Row TONE — the leading-edge rail + wash for a row in a named state. The status Badge
|
|
170
200
|
stays in its own cell: the rail makes the row findable, it does not carry the meaning
|
|
171
201
|
(WCAG 1.4.1). */}
|
|
@@ -78,7 +78,7 @@ export default function Demo() {
|
|
|
78
78
|
</PopoverTrigger>
|
|
79
79
|
<PopoverContent aria-label="ワークスペース">
|
|
80
80
|
<Select aria-label="ワークスペース" defaultOpen defaultValue="tokyo">
|
|
81
|
-
<SelectTrigger
|
|
81
|
+
<SelectTrigger data-picker-trigger="">
|
|
82
82
|
<SelectValue />
|
|
83
83
|
</SelectTrigger>
|
|
84
84
|
<SelectContent>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Badge,
|
|
2
3
|
Card,
|
|
3
4
|
CardContent,
|
|
4
5
|
CardDescription,
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
TableRow,
|
|
14
15
|
} from "@godxjp/ui/data-display";
|
|
15
16
|
import { Text } from "@godxjp/ui/general";
|
|
17
|
+
import { useTranslation } from "@godxjp/ui/i18n";
|
|
16
18
|
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
17
19
|
|
|
18
20
|
/**
|
|
@@ -21,6 +23,7 @@ import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
|
21
23
|
* for a custom one-off table. Composed only from real @godxjp/ui components.
|
|
22
24
|
*/
|
|
23
25
|
export default function Demo() {
|
|
26
|
+
const { t } = useTranslation();
|
|
24
27
|
return (
|
|
25
28
|
<PageContainer
|
|
26
29
|
title="Table"
|
|
@@ -290,6 +293,55 @@ export default function Demo() {
|
|
|
290
293
|
</CardContent>
|
|
291
294
|
</Card>
|
|
292
295
|
|
|
296
|
+
{/* ── gh#876 — TableRow tone, a typed route to the same paint DataTable's own
|
|
297
|
+
`rowTone` writes onto `data-tone` (wash + leading rail + `--surface-*` grounding,
|
|
298
|
+
gh#866). A hand-composed row discovers it from types now; `data-tone` written by
|
|
299
|
+
hand keeps working unchanged — this is an addition, not a migration. */}
|
|
300
|
+
<Card>
|
|
301
|
+
<CardHeader>
|
|
302
|
+
<CardTitle level={2}>{t("tableDocs.title")}</CardTitle>
|
|
303
|
+
<CardDescription>
|
|
304
|
+
`TableRow tone` writes the same `data-tone` attribute `DataTable`'s `rowTone`
|
|
305
|
+
already writes for you — no more reaching for the raw attribute to discover the row
|
|
306
|
+
can be toned at all.
|
|
307
|
+
</CardDescription>
|
|
308
|
+
</CardHeader>
|
|
309
|
+
<CardContent flush>
|
|
310
|
+
<Table>
|
|
311
|
+
<TableHeader>
|
|
312
|
+
<TableRow>
|
|
313
|
+
<TableHead>{t("tableDocs.item")}</TableHead>
|
|
314
|
+
<TableHead align="end">{t("tableDocs.amount")}</TableHead>
|
|
315
|
+
<TableHead>{t("tableDocs.status")}</TableHead>
|
|
316
|
+
</TableRow>
|
|
317
|
+
</TableHeader>
|
|
318
|
+
<TableBody>
|
|
319
|
+
<TableRow>
|
|
320
|
+
<TableCell>{t("tableDocs.fee")}</TableCell>
|
|
321
|
+
<TableCell numeric>¥440</TableCell>
|
|
322
|
+
<TableCell>
|
|
323
|
+
<Badge tone="neutral">{t("tableDocs.done")}</Badge>
|
|
324
|
+
</TableCell>
|
|
325
|
+
</TableRow>
|
|
326
|
+
<TableRow tone="warning">
|
|
327
|
+
<TableCell>{t("tableDocs.overdue")}</TableCell>
|
|
328
|
+
<TableCell numeric>¥128,000</TableCell>
|
|
329
|
+
<TableCell>
|
|
330
|
+
<Badge tone="warning">{t("tableDocs.check")}</Badge>
|
|
331
|
+
</TableCell>
|
|
332
|
+
</TableRow>
|
|
333
|
+
<TableRow tone="destructive">
|
|
334
|
+
<TableCell>{t("tableDocs.failed")}</TableCell>
|
|
335
|
+
<TableCell numeric>¥52,300</TableCell>
|
|
336
|
+
<TableCell>
|
|
337
|
+
<Badge tone="destructive">{t("tableDocs.failedBadge")}</Badge>
|
|
338
|
+
</TableCell>
|
|
339
|
+
</TableRow>
|
|
340
|
+
</TableBody>
|
|
341
|
+
</Table>
|
|
342
|
+
</CardContent>
|
|
343
|
+
</Card>
|
|
344
|
+
|
|
293
345
|
<Card>
|
|
294
346
|
<CardHeader>
|
|
295
347
|
<CardTitle level={2}>関連ファイル · flush, no table</CardTitle>
|
package/docs/feedback/sheet.tsx
CHANGED
|
@@ -141,8 +141,8 @@ export default function Demo() {
|
|
|
141
141
|
<SheetBody>
|
|
142
142
|
<Flex direction="col" gap="md">
|
|
143
143
|
<FormField id="filter-account" label="勘定科目">
|
|
144
|
-
<Select value={account} onValueChange={setAccount}>
|
|
145
|
-
<SelectTrigger id="filter-account"
|
|
144
|
+
<Select aria-label="勘定科目" value={account} onValueChange={setAccount}>
|
|
145
|
+
<SelectTrigger id="filter-account">
|
|
146
146
|
<SelectValue placeholder="すべての勘定科目" />
|
|
147
147
|
</SelectTrigger>
|
|
148
148
|
<SelectContent>
|
|
@@ -154,8 +154,8 @@ export default function Demo() {
|
|
|
154
154
|
</Select>
|
|
155
155
|
</FormField>
|
|
156
156
|
<FormField id="filter-status" label="ステータス">
|
|
157
|
-
<Select value={status} onValueChange={setStatus}>
|
|
158
|
-
<SelectTrigger id="filter-status"
|
|
157
|
+
<Select aria-label="ステータス" value={status} onValueChange={setStatus}>
|
|
158
|
+
<SelectTrigger id="filter-status">
|
|
159
159
|
<SelectValue placeholder="すべてのステータス" />
|
|
160
160
|
</SelectTrigger>
|
|
161
161
|
<SelectContent>
|
|
@@ -166,8 +166,8 @@ export default function Demo() {
|
|
|
166
166
|
</Select>
|
|
167
167
|
</FormField>
|
|
168
168
|
<FormField id="filter-source" label="ソース">
|
|
169
|
-
<Select value={source} onValueChange={setSource}>
|
|
170
|
-
<SelectTrigger id="filter-source"
|
|
169
|
+
<Select aria-label="ソース" value={source} onValueChange={setSource}>
|
|
170
|
+
<SelectTrigger id="filter-source">
|
|
171
171
|
<SelectValue placeholder="すべてのソース" />
|
|
172
172
|
</SelectTrigger>
|
|
173
173
|
<SelectContent>
|
|
@@ -444,10 +444,10 @@ export default function Demo() {
|
|
|
444
444
|
modal={false} on Sheet renders a non-modal panel, a pattern WAI-ARIA APG
|
|
445
445
|
allows. The page behind keeps working: no scrim, no scroll lock, nothing hidden from
|
|
446
446
|
assistive tech, and a press outside does not close the panel. Open the order summary
|
|
447
|
-
(side="left", so the quantity controls stay uncovered), then change a
|
|
448
|
-
below. The total inside the panel follows. Focus moves into the
|
|
449
|
-
|
|
450
|
-
|
|
447
|
+
(side="left", so the quantity controls stay uncovered), then change a
|
|
448
|
+
quantity below. The total inside the panel follows. Focus moves into the panel on
|
|
449
|
+
open, Tab can leave it, Escape closes it while focus is inside, and focus returns to
|
|
450
|
+
the trigger.
|
|
451
451
|
</CardDescription>
|
|
452
452
|
</CardHeader>
|
|
453
453
|
<CardContent>
|