@godxjp/ui 33.10.1 → 33.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DESIGN.md +1 -0
- package/README.md +3 -3
- package/agent/DESIGN.md +1 -0
- package/agent/START-HERE.md +7 -7
- package/agent/components/Anchor.json +1 -1
- package/agent/components/AppShell.json +1 -1
- package/agent/components/Cascader.json +1 -0
- package/agent/components/DataTable.json +1 -1
- package/agent/components/DatePicker.json +1 -0
- package/agent/components/Input.json +1 -0
- package/agent/components/NumberInput.json +1 -0
- package/agent/components/Pagination.json +1 -1
- package/agent/components/PasswordInput.json +1 -0
- package/agent/components/ResizablePanel.json +1 -1
- package/agent/components/ScrollArea.json +1 -1
- package/agent/components/SearchInput.json +1 -0
- package/agent/components/Select.json +1 -0
- package/agent/components/Table.json +1 -1
- package/agent/components/TimePicker.json +1 -0
- package/agent/components/Topbar.json +8 -2
- package/agent/components/TopbarItem.json +7 -1
- package/agent/components/TreeSelect.json +1 -0
- package/agent/components-index.json +7 -7
- package/agent/components.json +31 -10
- package/agent/index.json +6 -6
- package/agent/llms.txt +6 -6
- package/agent/tokens.json +39 -3
- package/dist/components/data-display/data-table.js +2 -0
- package/dist/components/data-display/table.js +3 -0
- package/dist/components/data-entry/input.js +16 -1
- package/dist/components/data-entry/search-input.js +1 -1
- package/dist/components/layout/app-shell.js +16 -6
- package/dist/components/layout/topbar-item.d.ts +1 -0
- package/dist/components/layout/topbar-item.js +9 -4
- package/dist/components/layout/topbar.d.ts +1 -1
- package/dist/components/layout/topbar.js +32 -3
- package/dist/components/navigation/pagination.js +4 -0
- package/dist/contracts/measurement.json +1 -1
- package/dist/lab/anchor.js +11 -1
- package/dist/lib/focus-reveal.d.ts +5 -0
- package/dist/lib/focus-reveal.js +19 -0
- package/dist/lib/hooks.js +5 -2
- package/dist/props/components/layout.prop.d.ts +13 -0
- package/dist/props/registry.d.ts +9 -1
- package/dist/props/registry.js +10 -0
- package/dist/styles/control.css +131 -3
- package/dist/styles/focus-ring.css +79 -19
- package/dist/styles/layers.json +1 -1
- package/dist/styles/layout.css +4 -4
- package/dist/styles/shell-layout.css +48 -0
- package/dist/styles.css +1 -1
- package/dist/tokens/base.css +2 -0
- package/dist/tokens/components/control.css +4 -1
- package/dist/tokens/components/resizable.css +4 -0
- package/dist/tokens/components/shell.css +3 -0
- package/dist/tokens/foundation.css +4 -1
- package/docs/TOKENS.md +52 -23
- package/package.json +2 -2
- package/scripts/visual-audit.mjs +33 -3
package/dist/tokens/base.css
CHANGED
|
@@ -234,6 +234,8 @@
|
|
|
234
234
|
|
|
235
235
|
--control-affix-inset-inline-end: var(--space-2);
|
|
236
236
|
--control-affix-action-size: 1.5rem;
|
|
237
|
+
|
|
238
|
+
--control-affix-touch-target-size: var(--band-height-xl);
|
|
237
239
|
--control-affix-action-radius: initial;
|
|
238
240
|
--control-affix-icon-size: var(--icon-size-md);
|
|
239
241
|
|
|
@@ -499,7 +501,8 @@
|
|
|
499
501
|
--control-height-default: var(--band-height-xl);
|
|
500
502
|
|
|
501
503
|
--search-input-end-padding: calc(
|
|
502
|
-
var(--search-input-edge-inset) + var(--touch-target-min) / 2 +
|
|
504
|
+
var(--search-input-edge-inset) + var(--touch-target-min) / 2 +
|
|
505
|
+
var(--control-affix-touch-target-size) / 2
|
|
503
506
|
);
|
|
504
507
|
}
|
|
505
508
|
}
|
|
@@ -148,9 +148,12 @@
|
|
|
148
148
|
|
|
149
149
|
--focus-ring-offset: var(--focus-outline-offset);
|
|
150
150
|
|
|
151
|
+
--focus-ring-inset-offset: calc(-1 * (var(--focus-ring-width) + var(--focus-outline-offset)));
|
|
152
|
+
--focus-ring-contained-offset: initial;
|
|
153
|
+
|
|
151
154
|
--focus-ring-clip-margin: 8px;
|
|
152
155
|
|
|
153
|
-
--region-focus-ring-width:
|
|
156
|
+
--region-focus-ring-width: var(--focus-ring-weight);
|
|
154
157
|
--region-focus-ring-color: initial;
|
|
155
158
|
|
|
156
159
|
--gradient-brand: none;
|
package/docs/TOKENS.md
CHANGED
|
@@ -277,7 +277,11 @@ The census confirmed the number and rejected the diagnosis: **`width` is not one
|
|
|
277
277
|
|
|
278
278
|
**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.
|
|
279
279
|
|
|
280
|
-
The focus mark reads this scale
|
|
280
|
+
The focus mark reads this scale through `--focus-ring-weight`: the default is `--stroke-md` (2px), with a 2px outline gap. `--focus-ring-width` is derived from the weight and the global `--focus-outline` switch; do not set it directly.
|
|
281
|
+
|
|
282
|
+
Clipping surfaces use `--focus-ring-inset-offset` (default minus the mark width plus the gap, -4px) through the inherited `--focus-ring-contained-offset` context. Pagination, tab strips, cards, bars and scrolling surfaces keep the mark inside their boundary without adding padding. A surface-coloured inset backing separates the brand mark from brand-filled controls. Keyboard-scroll regions show their inset mark by default; `--region-focus-ring-width: 0` is an explicit opt-out.
|
|
283
|
+
|
|
284
|
+
Resize separators use `--resizable-handle-size` (default `--space-2`, 8px), with the inline or block axis selected by ARIA orientation. This reserves room for the inset mark even on an empty handle; focusing does not change its size.
|
|
281
285
|
|
|
282
286
|
#### `--band-height-*` — the vertical extent of a horizontal band
|
|
283
287
|
|
|
@@ -487,23 +491,23 @@ It is reserved for `@container` / `@media` re-points. Everything static stays in
|
|
|
487
491
|
|
|
488
492
|
Fifteen existing token defaults build on the eight first-pass changes. Body stays 14px/1.7, labels and headings stay 500, with no Latin-style negative tracking on Japanese. Mobile gutters remain 16px. Zebra stays off; table numeric alignment and sidebar active styling are unchanged. Card header-to-body spacing grows to 24px; horizontal card/table insets and section gaps stay 16px so fixed-width date columns remain on one line. No new token or component API.
|
|
489
493
|
|
|
490
|
-
| Token
|
|
491
|
-
|
|
492
|
-
| `--space-page-x`
|
|
493
|
-
| `--space-page-y`
|
|
494
|
-
| `--card-space-body-y`
|
|
495
|
-
| `--page-title-font-size`
|
|
496
|
-
| `--page-title-font-size-compact` | `var( --heading-h2, calc(var(--font-size-base) * var(--font-size-ratio) * var(--font-size-ratio)) )`
|
|
497
|
-
| `--overlay-background`
|
|
498
|
-
| `--card-title-font-size`
|
|
499
|
-
| `--card-shadow`
|
|
500
|
-
| `--form-field-row-gap`
|
|
501
|
-
| `--form-block-gap`
|
|
502
|
-
| `--control-height-default`
|
|
503
|
-
| `--control-focus-ring-width`
|
|
504
|
-
| `--table-row-height-default`
|
|
505
|
-
| `--focus-outline-weight`
|
|
506
|
-
| `--focus-outline-offset`
|
|
494
|
+
| Token | Previous | New |
|
|
495
|
+
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
496
|
+
| `--space-page-x` | `var(--space-6)` | `var(--space-8)` |
|
|
497
|
+
| `--space-page-y` | `var(--space-6)` | `var(--space-8)` |
|
|
498
|
+
| `--card-space-body-y` | `var(--space-section-active)` | `var(--space-6)` |
|
|
499
|
+
| `--page-title-font-size` | `var( --heading-h1, calc( var(--font-size-base) * var(--font-size-ratio) * var(--font-size-ratio) * var(--font-size-ratio) ) )` | `var( --heading-h1, calc( var(--font-size-base) * var(--font-size-ratio) * var(--font-size-ratio) * var(--font-size-ratio) ) )` |
|
|
500
|
+
| `--page-title-font-size-compact` | `var( --heading-h2, calc(var(--font-size-base) * var(--font-size-ratio) * var(--font-size-ratio)) )` | `var( --heading-h2, calc(var(--font-size-base) * var(--font-size-ratio) * var(--font-size-ratio)) )` |
|
|
501
|
+
| `--overlay-background` | `rgb(0 0 0 / 0.5)` | `rgb(0 0 0 / 0.4)` |
|
|
502
|
+
| `--card-title-font-size` | `var(--font-size-base)` | `calc(var(--font-size-base) * var(--font-size-ratio))` |
|
|
503
|
+
| `--card-shadow` | `initial` | `none` |
|
|
504
|
+
| `--form-field-row-gap` | `var(--space-3)` | `var(--space-3)` |
|
|
505
|
+
| `--form-block-gap` | `var(--space-4)` | `var(--space-6)` |
|
|
506
|
+
| `--control-height-default` | `var(--band-height-md)` | `var(--band-height-lg)` |
|
|
507
|
+
| `--control-focus-ring-width` | `initial` | `var(--stroke-md)` |
|
|
508
|
+
| `--table-row-height-default` | `var(--band-height-md)` | `var(--band-height-lg)` |
|
|
509
|
+
| `--focus-outline-weight` | `initial` | `var(--stroke-md)` |
|
|
510
|
+
| `--focus-outline-offset` | `0px` | `2px` |
|
|
507
511
|
|
|
508
512
|
### Complete restoration (both passes)
|
|
509
513
|
|
|
@@ -514,8 +518,17 @@ Load after library and preset styles. The original input colors restore the orig
|
|
|
514
518
|
--space-page-x: var(--space-6);
|
|
515
519
|
--space-page-y: var(--space-6);
|
|
516
520
|
--card-space-body-y: var(--space-section-active);
|
|
517
|
-
--page-title-font-size: var(
|
|
518
|
-
|
|
521
|
+
--page-title-font-size: var(
|
|
522
|
+
--heading-h1,
|
|
523
|
+
calc(
|
|
524
|
+
var(--font-size-base) * var(--font-size-ratio) * var(--font-size-ratio) *
|
|
525
|
+
var(--font-size-ratio)
|
|
526
|
+
)
|
|
527
|
+
);
|
|
528
|
+
--page-title-font-size-compact: var(
|
|
529
|
+
--heading-h2,
|
|
530
|
+
calc(var(--font-size-base) * var(--font-size-ratio) * var(--font-size-ratio))
|
|
531
|
+
);
|
|
519
532
|
--overlay-background: rgb(0 0 0 / 0.5);
|
|
520
533
|
--card-title-font-size: var(--font-size-base);
|
|
521
534
|
--card-shadow: initial;
|
|
@@ -528,14 +541,19 @@ Load after library and preset styles. The original input colors restore the orig
|
|
|
528
541
|
--focus-outline-offset: 0px;
|
|
529
542
|
--button-radius: var(--radius-md, calc(var(--radius) / var(--radius-ratio)));
|
|
530
543
|
--control-shadow: var(--shadow-xs);
|
|
531
|
-
--shadow-md:
|
|
532
|
-
|
|
544
|
+
--shadow-md:
|
|
545
|
+
0 4px 6px -1px rgb(var(--shadow-color) / 0.1), 0 2px 4px -2px rgb(var(--shadow-color) / 0.1);
|
|
546
|
+
--shadow-lg:
|
|
547
|
+
0 10px 15px -3px rgb(var(--shadow-color) / 0.1), 0 4px 6px -4px rgb(var(--shadow-color) / 0.1);
|
|
533
548
|
--duration-fast: 150ms;
|
|
534
549
|
--duration-base: 250ms;
|
|
535
550
|
--duration-slow: 500ms;
|
|
536
551
|
--input: 30 7% 53%;
|
|
537
552
|
}
|
|
538
|
-
.dark,
|
|
553
|
+
.dark,
|
|
554
|
+
:root[data-theme="dark"] {
|
|
555
|
+
--input: 45 6% 47%;
|
|
556
|
+
}
|
|
539
557
|
|
|
540
558
|
.ui-scale-fixed {
|
|
541
559
|
--space-page-x: var(--space-6);
|
|
@@ -543,3 +561,14 @@ Load after library and preset styles. The original input colors restore the orig
|
|
|
543
561
|
--space-section: var(--space-4);
|
|
544
562
|
}
|
|
545
563
|
```
|
|
564
|
+
|
|
565
|
+
### Input affix touch targets
|
|
566
|
+
|
|
567
|
+
`--control-affix-touch-target-size` defaults to `var(--band-height-xl)` (44px) and applies
|
|
568
|
+
only under `pointer: coarse`. It sizes the action box, not the glyph. Input reserves the measured
|
|
569
|
+
width of its complete trailing slot plus the existing inset and gap, including two adjacent
|
|
570
|
+
44px actions in a 200px field. `--input-trailing-measured-size` is runtime measurement, not a
|
|
571
|
+
service override. `allowClear` still replaces the suffix; DatePicker and TimePicker still swap
|
|
572
|
+
clear and open actions. NumberInput lays out its two steppers horizontally on coarse pointers.
|
|
573
|
+
SearchInput retains its glyph centre while sharing this target token. Fine-pointer geometry is
|
|
574
|
+
unchanged. Override the token on the field or in the service theme; no new prop is required.
|
package/package.json
CHANGED
package/scripts/visual-audit.mjs
CHANGED
|
@@ -453,9 +453,9 @@ export const PROBE_RULES = [
|
|
|
453
453
|
id: "c04-compact-account-name",
|
|
454
454
|
severity: "warn",
|
|
455
455
|
category: "a11y",
|
|
456
|
-
standard: `compact (<600px) bar shows
|
|
456
|
+
standard: `compact (<600px) bar shows avatar-only or measured bounded shared-device identity (${RC}); trigger name per WCAG 2.2 SC 4.1.2`,
|
|
457
457
|
kind: "probe",
|
|
458
|
-
fix: "
|
|
458
|
+
fix: "Shared-device exception: Topbar identity with TopbarItem truncate keeps a bounded, ellipsised name and full title/accessible name. Otherwise below 600px the bar shows the avatar only: hide the account name (it belongs in the opened account menu) and make the avatar the trigger — accessible name + aria-haspopup, opening identity and account controls.",
|
|
459
459
|
},
|
|
460
460
|
{
|
|
461
461
|
id: "c05-compact-editor-inset",
|
|
@@ -733,7 +733,7 @@ export function evaluateProbes(raw, { url, viewport }) {
|
|
|
733
733
|
// C04 — compact account access without the name in the bar.
|
|
734
734
|
const accounts = applies("c04-compact-account-name") ? raw.c04?.mapped || [] : [];
|
|
735
735
|
for (const a of accounts) {
|
|
736
|
-
if (a.nameVisible)
|
|
736
|
+
if (a.nameVisible && !a.compactIdentity)
|
|
737
737
|
add(
|
|
738
738
|
"c04-compact-account-name",
|
|
739
739
|
a.element,
|
|
@@ -1158,7 +1158,37 @@ export function collectProbes(opts) {
|
|
|
1158
1158
|
const pushAccount = (region, nameEl, avatar, t, nameText) => {
|
|
1159
1159
|
if (avatar) accountAvatars.add(avatar);
|
|
1160
1160
|
const text = nameText ?? (nameEl && shown(nameEl) ? snippet(nameEl.textContent) : "");
|
|
1161
|
+
const label = region.querySelector('[data-slot="topbar-item-label"]');
|
|
1162
|
+
const identity = region.closest('[data-slot="topbar-identity"]');
|
|
1163
|
+
const bar = identity?.closest('[data-slot="topbar"]');
|
|
1164
|
+
const r = region.getBoundingClientRect();
|
|
1165
|
+
const b = bar?.getBoundingClientRect();
|
|
1166
|
+
const l = label?.getBoundingClientRect();
|
|
1167
|
+
// An opt-in is not an exemption by itself: measure the visible label, bounded share,
|
|
1168
|
+
// containment, and full-name recovery. Old full-width labels still fail C04.
|
|
1169
|
+
const compactIdentity = !!(
|
|
1170
|
+
identity &&
|
|
1171
|
+
b &&
|
|
1172
|
+
label &&
|
|
1173
|
+
l &&
|
|
1174
|
+
text &&
|
|
1175
|
+
region.getAttribute("data-truncate") === "true" &&
|
|
1176
|
+
cs(label).textOverflow === "ellipsis" &&
|
|
1177
|
+
cs(label).whiteSpace === "nowrap" &&
|
|
1178
|
+
l.width > 1 &&
|
|
1179
|
+
l.height > 1 &&
|
|
1180
|
+
l.left >= r.left - 1 &&
|
|
1181
|
+
l.right <= r.right + 1 &&
|
|
1182
|
+
r.width <= b.width * 0.4 + 1 &&
|
|
1183
|
+
r.left >= b.left - 1 &&
|
|
1184
|
+
r.right <= b.right + 1 &&
|
|
1185
|
+
r.left >= -1 &&
|
|
1186
|
+
r.right <= width + 1 &&
|
|
1187
|
+
region.getAttribute("title")?.includes(label.textContent) &&
|
|
1188
|
+
accName(region).includes(label.textContent)
|
|
1189
|
+
);
|
|
1161
1190
|
accounts.push({
|
|
1191
|
+
compactIdentity,
|
|
1162
1192
|
element: desc(region),
|
|
1163
1193
|
nameVisible: !!text,
|
|
1164
1194
|
nameText: text,
|