@godxjp/ui 23.1.0 → 23.2.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.
Files changed (56) hide show
  1. package/dist/components/data-display/card.d.ts +45 -2
  2. package/dist/components/data-display/card.js +4 -2
  3. package/dist/components/data-display/feature-list.d.ts +26 -0
  4. package/dist/components/data-display/feature-list.js +29 -0
  5. package/dist/components/data-display/index.d.ts +6 -0
  6. package/dist/components/data-display/index.js +6 -0
  7. package/dist/components/data-display/swatch.d.ts +24 -0
  8. package/dist/components/data-display/swatch.js +19 -0
  9. package/dist/components/data-display/thumbnail.d.ts +37 -0
  10. package/dist/components/data-display/thumbnail.js +20 -0
  11. package/dist/components/feedback/index.d.ts +2 -2
  12. package/dist/components/feedback/index.js +19 -1
  13. package/dist/components/feedback/skeleton.d.ts +33 -3
  14. package/dist/components/feedback/skeleton.js +154 -3
  15. package/dist/components/layout/flex.d.ts +1 -1
  16. package/dist/components/layout/flex.js +17 -5
  17. package/dist/components/layout/sidebar.js +9 -2
  18. package/dist/components/navigation/tabs-scroll.d.ts +27 -0
  19. package/dist/components/navigation/tabs-scroll.js +36 -1
  20. package/dist/components/navigation/tabs.d.ts +2 -2
  21. package/dist/components/navigation/tabs.js +44 -12
  22. package/dist/i18n/messages/en.json +5 -0
  23. package/dist/i18n/messages/ja.json +5 -0
  24. package/dist/i18n/messages/vi.json +5 -0
  25. package/dist/props/components/data-display.prop.d.ts +93 -0
  26. package/dist/props/components/feedback.prop.d.ts +85 -1
  27. package/dist/props/components/layout.prop.d.ts +72 -1
  28. package/dist/props/components/navigation.prop.d.ts +72 -1
  29. package/dist/props/registry.d.ts +118 -0
  30. package/dist/props/registry.js +134 -0
  31. package/dist/styles/alert-layout.css +139 -0
  32. package/dist/styles/card-layout.css +48 -0
  33. package/dist/styles/data-display-layout.css +88 -0
  34. package/dist/styles/navigation-layout.css +76 -3
  35. package/dist/styles/shell-layout.css +18 -0
  36. package/dist/tokens/components/card.css +2 -0
  37. package/dist/tokens/components/data-display.css +23 -0
  38. package/dist/tokens/components/feedback.css +18 -0
  39. package/dist/tokens/components/navigation.css +2 -0
  40. package/dist/tokens/foundation.css +18 -16
  41. package/docs/CONSUMER-RULES.md +1 -1
  42. package/docs/DESIGN-AUTHORITY.md +2 -1
  43. package/docs/FRAME-COVERAGE-REPORT.md +29 -3
  44. package/docs/assets/shot-landscape.svg +12 -0
  45. package/docs/assets/shot-portrait.svg +10 -0
  46. package/docs/data-display/card/index.tsx +40 -0
  47. package/docs/data-display/feature-list.tsx +159 -0
  48. package/docs/data-display/swatch.tsx +107 -0
  49. package/docs/data-display/thumbnail.tsx +128 -0
  50. package/docs/feedback/skeleton.tsx +57 -0
  51. package/docs/layout/flex.tsx +29 -0
  52. package/docs/layout/sidebar.tsx +66 -10
  53. package/docs/navigation/tabs.tsx +59 -0
  54. package/package.json +4 -7
  55. package/scripts/consumer-rule.md +16 -0
  56. package/scripts/ui-audit.mjs +3 -4
@@ -4,6 +4,9 @@
4
4
  [data-slot="card"] {
5
5
  min-width: 0;
6
6
 
7
+ display: flex;
8
+ flex-direction: column;
9
+
7
10
  border-width: 1px;
8
11
  border-style: solid;
9
12
  border-color: hsl(var(--card-border, var(--border)));
@@ -25,6 +28,10 @@
25
28
  background: transparent;
26
29
  }
27
30
 
31
+ [data-slot="card"][data-variant="borderless"] {
32
+ border-width: 0;
33
+ }
34
+
28
35
  [data-slot="card"][data-variant="featured"] {
29
36
  border-color: var(--card-featured-border-color, hsl(var(--primary)));
30
37
  box-shadow: 0 0 0 var(--card-featured-ring-width)
@@ -74,6 +81,11 @@
74
81
 
75
82
  [data-slot="card"][data-accent] > [data-slot="card-header"],
76
83
  [data-slot="card"][data-accent] > [data-slot="card-content"]:not([data-flush]),
84
+
85
+ [data-slot="card"] > [data-slot="card-footer"] {
86
+ margin-block-start: auto;
87
+ }
88
+
77
89
  [data-slot="card"][data-accent] > [data-slot="card-footer"]:not([data-flush]) {
78
90
  padding-inline-start: calc(var(--card-space-inset) - var(--card-accent-rail-width));
79
91
  }
@@ -95,6 +107,21 @@
95
107
  padding-inline-start: var(--card-space-inset);
96
108
  }
97
109
 
110
+ [data-slot="card"][data-hoverable] {
111
+ cursor: pointer;
112
+ transition: box-shadow var(--duration-fast) var(--ease-standard);
113
+ }
114
+
115
+ [data-slot="card"][data-hoverable]:hover {
116
+ --card-shadow: var(--card-hover-shadow);
117
+ }
118
+
119
+ @media (prefers-reduced-motion: reduce) {
120
+ [data-slot="card"][data-hoverable] {
121
+ transition: none;
122
+ }
123
+ }
124
+
98
125
  [data-slot="card-header"] {
99
126
  display: flex;
100
127
  flex-direction: column;
@@ -335,6 +362,27 @@
335
362
  justify-content: stretch;
336
363
  }
337
364
 
365
+ [data-slot="card-footer"][data-actions] {
366
+ gap: 0;
367
+ flex-wrap: nowrap;
368
+ padding-inline: 0;
369
+ padding-block: 0;
370
+ border-top: var(--stroke-hairline) solid hsl(var(--card-border, var(--border)));
371
+ }
372
+
373
+ [data-slot="card-footer"][data-actions] > * {
374
+ display: flex;
375
+ min-width: 0;
376
+ flex: 1 1 0;
377
+ align-items: center;
378
+ justify-content: center;
379
+ padding-block: var(--card-space-footer-y);
380
+ }
381
+
382
+ [data-slot="card-footer"][data-actions] > * + * {
383
+ border-inline-start: var(--stroke-hairline) solid hsl(var(--card-border, var(--border)));
384
+ }
385
+
338
386
  .ui-card-inset-x {
339
387
  padding-inline: var(--card-space-inset);
340
388
  }
@@ -314,6 +314,94 @@
314
314
  background: hsl(var(--muted-foreground));
315
315
  }
316
316
 
317
+ .ui-swatch {
318
+ display: inline-block;
319
+ flex: none;
320
+
321
+ vertical-align: middle;
322
+ inline-size: var(--swatch-size);
323
+ block-size: var(--swatch-size);
324
+ border-radius: var(--swatch-radius);
325
+ background: var(--swatch-color);
326
+ box-shadow: inset 0 0 0 var(--swatch-border-width)
327
+ var(--swatch-border-color, hsl(var(--border)));
328
+ forced-color-adjust: none;
329
+ }
330
+
331
+ .ui-feature-list {
332
+ display: flex;
333
+ flex-direction: column;
334
+ gap: var(--feature-list-space-gap);
335
+ }
336
+
337
+ .ui-feature-list-item {
338
+ display: grid;
339
+ align-items: start;
340
+ grid-template-columns: auto minmax(0, 1fr);
341
+ column-gap: var(--feature-list-space-inline);
342
+ font-size: var(--feature-list-font-size);
343
+ line-height: var(--line-height-body);
344
+ }
345
+
346
+ .ui-feature-list-mark {
347
+ display: grid;
348
+ block-size: 1lh;
349
+ place-items: center;
350
+ color: hsl(var(--muted-foreground));
351
+ }
352
+
353
+ .ui-feature-list-mark > svg {
354
+ inline-size: var(--feature-list-mark-icon-size);
355
+ block-size: var(--feature-list-mark-icon-size);
356
+ }
357
+
358
+ .ui-feature-list-item[data-state="included"] .ui-feature-list-mark {
359
+ color: hsl(var(--mark-success));
360
+ }
361
+
362
+ .ui-feature-list-item[data-state="limited"] .ui-feature-list-mark {
363
+ color: hsl(var(--mark-warning));
364
+ }
365
+
366
+ .ui-feature-list-item[data-state="excluded"] .ui-feature-list-label {
367
+ color: hsl(var(--muted-foreground));
368
+ }
369
+
370
+ .ui-feature-list-body {
371
+ display: flex;
372
+ min-inline-size: 0;
373
+ flex-direction: column;
374
+
375
+ overflow-wrap: anywhere;
376
+ }
377
+
378
+ .ui-feature-list-description {
379
+ color: hsl(var(--muted-foreground));
380
+ font-size: var(--feature-list-description-font-size);
381
+ }
382
+
383
+ .ui-thumbnail {
384
+ display: block;
385
+
386
+ inline-size: auto;
387
+
388
+ max-inline-size: 100%;
389
+ block-size: var(--thumbnail-block-size);
390
+ border: var(--thumbnail-border-width) solid hsl(var(--border));
391
+ border-radius: var(--thumbnail-radius);
392
+
393
+ background: hsl(var(--muted));
394
+ object-fit: contain;
395
+ }
396
+
397
+ .ui-thumbnail[data-size="sm"] {
398
+ block-size: var(--thumbnail-block-size-sm);
399
+ }
400
+
401
+ .ui-thumbnail[data-size="lg"] {
402
+ block-size: var(--thumbnail-block-size-lg);
403
+ }
404
+
317
405
  .ui-timeline {
318
406
  display: flex;
319
407
  flex-direction: column;
@@ -53,22 +53,67 @@
53
53
  position: absolute;
54
54
  background: var(--tabs-indicator-background, hsl(var(--primary)));
55
55
  opacity: 0;
56
- transition: opacity var(--duration-fast) var(--ease-standard);
56
+
57
+ transition: opacity var(--duration-fast, 150ms) var(--ease-standard, cubic-bezier(0.2, 0, 0, 1));
57
58
  pointer-events: none;
58
59
  }
59
60
 
60
61
  [data-slot="tabs-list"][data-variant="line"][data-orientation="horizontal"]
61
62
  [data-slot="tabs-trigger"]::after {
62
- inset-inline: 0;
63
63
  inset-block-end: calc(-1 * var(--tabs-indicator-offset));
64
64
  block-size: var(--tabs-indicator-size);
65
+ inline-size: calc(100% - 2 * var(--tabs-indicator-inset));
66
+ inset-inline-start: var(--tabs-indicator-inset);
67
+ }
68
+
69
+ [data-slot="tabs"][data-indicator-align="start"]
70
+ [data-slot="tabs-list"][data-variant="line"][data-orientation="horizontal"]
71
+ [data-slot="tabs-trigger"]::after {
72
+ inset-inline-start: 0;
73
+ }
74
+
75
+ [data-slot="tabs"][data-indicator-align="end"]
76
+ [data-slot="tabs-list"][data-variant="line"][data-orientation="horizontal"]
77
+ [data-slot="tabs-trigger"]::after {
78
+ inset-inline-start: auto;
79
+ inset-inline-end: 0;
65
80
  }
66
81
 
67
82
  [data-slot="tabs-list"][data-variant="line"][data-orientation="vertical"]
68
83
  [data-slot="tabs-trigger"]::after {
69
- inset-block: 0;
70
84
  inset-inline-end: calc(-1 * var(--tabs-indicator-offset));
71
85
  inline-size: var(--tabs-indicator-size);
86
+ block-size: calc(100% - 2 * var(--tabs-indicator-inset));
87
+ inset-block-start: var(--tabs-indicator-inset);
88
+ }
89
+
90
+ [data-slot="tabs"][data-indicator-align="start"]
91
+ [data-slot="tabs-list"][data-variant="line"][data-orientation="vertical"]
92
+ [data-slot="tabs-trigger"]::after {
93
+ inset-block-start: 0;
94
+ }
95
+
96
+ [data-slot="tabs"][data-indicator-align="end"]
97
+ [data-slot="tabs-list"][data-variant="line"][data-orientation="vertical"]
98
+ [data-slot="tabs-trigger"]::after {
99
+ inset-block-start: auto;
100
+ inset-block-end: 0;
101
+ }
102
+
103
+ [data-slot="tabs"][data-indicator-size="label"][data-orientation="horizontal"][data-size="sm"] {
104
+ --tabs-indicator-inset: var(--tabs-trigger-padding-x-sm);
105
+ }
106
+
107
+ [data-slot="tabs"][data-indicator-size="label"][data-orientation="horizontal"][data-size="md"] {
108
+ --tabs-indicator-inset: var(--tabs-trigger-padding-x-md);
109
+ }
110
+
111
+ [data-slot="tabs"][data-indicator-size="label"][data-orientation="horizontal"][data-size="lg"] {
112
+ --tabs-indicator-inset: var(--tabs-trigger-padding-x-lg);
113
+ }
114
+
115
+ [data-slot="tabs"][data-indicator-size="label"][data-orientation="vertical"] {
116
+ --tabs-indicator-inset: var(--tabs-trigger-line-padding-y);
72
117
  }
73
118
 
74
119
  [data-slot="tabs-list"][data-variant="line"]
@@ -76,10 +121,38 @@
76
121
  opacity: 1;
77
122
  }
78
123
 
124
+ [data-slot="tabs"][data-animated-ink-bar="false"]
125
+ [data-slot="tabs-list"][data-variant="line"]
126
+ [data-slot="tabs-trigger"]::after {
127
+ transition: none;
128
+ }
129
+
130
+ @keyframes ui-tabs-pane-in {
131
+ from {
132
+ opacity: 0;
133
+ }
134
+ to {
135
+ opacity: 1;
136
+ }
137
+ }
138
+
139
+ [data-slot="tabs"][data-animated-tab-pane="true"] [data-slot="tabs-panel"][data-state="active"],
140
+ [data-slot="tabs"][data-animated-tab-pane="true"]
141
+ [data-slot="tabs-content"][data-state="active"] {
142
+ animation: ui-tabs-pane-in var(--duration-base, 250ms)
143
+ var(--ease-standard, cubic-bezier(0.2, 0, 0, 1));
144
+ }
145
+
79
146
  @media (prefers-reduced-motion: reduce) {
80
147
  [data-slot="tabs-list"][data-variant="line"] [data-slot="tabs-trigger"]::after {
81
148
  transition: none;
82
149
  }
150
+
151
+ [data-slot="tabs"][data-animated-tab-pane="true"] [data-slot="tabs-panel"][data-state="active"],
152
+ [data-slot="tabs"][data-animated-tab-pane="true"]
153
+ [data-slot="tabs-content"][data-state="active"] {
154
+ animation: none;
155
+ }
83
156
  }
84
157
 
85
158
  .ui-tabs-bar {
@@ -1692,6 +1692,22 @@
1692
1692
  color: var(--sidebar-badge-destructive-foreground, hsl(var(--destructive-foreground)));
1693
1693
  }
1694
1694
 
1695
+ .sb-trailing-icon {
1696
+ display: grid;
1697
+ width: var(--sidebar-nav-icon-size);
1698
+ height: var(--sidebar-nav-icon-size);
1699
+ flex: 0 0 auto;
1700
+ line-height: 0;
1701
+ place-items: center;
1702
+ }
1703
+
1704
+ .sb-trailing-icon svg {
1705
+ display: block;
1706
+ width: var(--sidebar-nav-icon-size);
1707
+ height: var(--sidebar-nav-icon-size);
1708
+ flex: 0 0 auto;
1709
+ }
1710
+
1695
1711
  .sb-footer {
1696
1712
  margin-top: auto;
1697
1713
  border-top: 1px solid hsl(var(--border));
@@ -1894,6 +1910,8 @@
1894
1910
  :is(.app-root[data-collapsed="true"] > .app-sidebar, .sb-root[data-collapsed="true"])
1895
1911
  .sb-section-label,
1896
1912
  :is(.app-root[data-collapsed="true"] > .app-sidebar, .sb-root[data-collapsed="true"]) .sb-label,
1913
+ :is(.app-root[data-collapsed="true"] > .app-sidebar, .sb-root[data-collapsed="true"])
1914
+ .sb-trailing-icon,
1897
1915
  :is(.app-root[data-collapsed="true"] > .app-sidebar, .sb-root[data-collapsed="true"]) .sb-badge {
1898
1916
  display: none;
1899
1917
  }
@@ -36,6 +36,8 @@
36
36
 
37
37
  --card-glow: 0 0 0 0 transparent;
38
38
 
39
+ --card-hover-shadow: var(--shadow-md);
40
+
39
41
  --card-tint: transparent;
40
42
 
41
43
  --card-accent-rail-width: var(--stroke-2xl);
@@ -82,6 +82,29 @@
82
82
 
83
83
  --legend-color: initial;
84
84
 
85
+ --swatch-size: 1rem;
86
+ --swatch-radius: 0.125rem;
87
+
88
+ --swatch-border-width: var(--stroke-hairline);
89
+
90
+ --swatch-border-color: initial;
91
+
92
+ --swatch-color: hsl(var(--muted));
93
+
94
+ --feature-list-space-gap: var(--space-stack-sm);
95
+
96
+ --feature-list-space-inline: var(--space-inline-sm);
97
+ --feature-list-font-size: var(--font-size-sm);
98
+ --feature-list-description-font-size: var(--font-size-xs);
99
+
100
+ --feature-list-mark-icon-size: var(--icon-size-md);
101
+
102
+ --thumbnail-block-size-sm: 4rem;
103
+ --thumbnail-block-size: 6rem;
104
+ --thumbnail-block-size-lg: 10rem;
105
+ --thumbnail-border-width: var(--stroke-hairline);
106
+ --thumbnail-radius: var(--radius);
107
+
85
108
  --timeline-dot-done-background: initial;
86
109
  --timeline-dot-current-background: initial;
87
110
  --timeline-line-completed-background: initial;
@@ -94,6 +94,24 @@
94
94
  --skeleton-stat-value-width: 8rem;
95
95
  --skeleton-stat-caption-width: 5rem;
96
96
 
97
+ --skeleton-element-radius: var(--radius-sm);
98
+ --skeleton-button-width-ratio: 2;
99
+ --skeleton-input-width-ratio: 5;
100
+
101
+ --skeleton-node-size: calc(var(--control-height) * 3);
102
+ --skeleton-image-glyph-size: var(--icon-size-4xl);
103
+
104
+ --skeleton-image-glyph-color: initial;
105
+
106
+ --skeleton-article-avatar-gap: var(--space-inline-lg);
107
+ --skeleton-article-avatar-title-offset: var(--space-3);
108
+ --skeleton-article-title-gap: var(--space-stack-lg);
109
+ --skeleton-article-line-gap: var(--space-stack-md);
110
+
111
+ --skeleton-paragraph-last-width: 61%;
112
+
113
+ --skeleton-sweep-gradient: initial;
114
+
97
115
  --query-load-more-space-block-start: var(--space-stack-md);
98
116
  --query-loading-more-space-block-start: var(--space-stack-sm);
99
117
 
@@ -47,6 +47,8 @@
47
47
  --tabs-indicator-size: 2px;
48
48
  --tabs-indicator-offset: 0px;
49
49
 
50
+ --tabs-indicator-inset: 0px;
51
+
50
52
  --tabs-root-gap: 0.5rem;
51
53
 
52
54
  --tabs-list-line-space-inset: 0px;
@@ -238,6 +238,24 @@
238
238
  --phi-0: var(--phi-unit);
239
239
  --phi-p1: calc(var(--phi-unit) * var(--ratio-phi));
240
240
  --phi-p2: calc(var(--phi-p1) * var(--ratio-phi));
241
+
242
+ --duration-fast: 150ms;
243
+ --duration-base: 250ms;
244
+ --duration-slow: 500ms;
245
+ --ease-standard: cubic-bezier(0.2, 0, 0, 1);
246
+ --ease-emphasized: cubic-bezier(0.32, 0.72, 0, 1);
247
+ --ease-decelerate: cubic-bezier(0, 0, 0, 1);
248
+ --ease-accelerate: cubic-bezier(0.3, 0, 1, 1);
249
+ --reveal-distance: 10px;
250
+
251
+ --reveal-stagger-step: 60ms;
252
+
253
+ --duration-loop: 1400ms;
254
+
255
+ --activity-interval: var(--duration-loop);
256
+
257
+ --activity-stagger-step: 160ms;
258
+
241
259
  }
242
260
 
243
261
  .ui-scale-fixed {
@@ -289,22 +307,6 @@
289
307
  --space-chrome-gap: var(--space-2);
290
308
  --field-label-gap: var(--space-2);
291
309
 
292
- --duration-fast: 150ms;
293
- --duration-base: 250ms;
294
- --duration-slow: 500ms;
295
- --ease-standard: cubic-bezier(0.2, 0, 0, 1);
296
- --ease-emphasized: cubic-bezier(0.32, 0.72, 0, 1);
297
- --ease-decelerate: cubic-bezier(0, 0, 0, 1);
298
- --ease-accelerate: cubic-bezier(0.3, 0, 1, 1);
299
- --reveal-distance: 10px;
300
-
301
- --reveal-stagger-step: 60ms;
302
-
303
- --duration-loop: 1400ms;
304
-
305
- --activity-interval: var(--duration-loop);
306
-
307
- --activity-stagger-step: 160ms;
308
310
  }
309
311
 
310
312
  .dark,
@@ -5,7 +5,7 @@ Read this once; the audit enforces it. Everything else in `docs/` is for contrib
5
5
  1. Load styles with `@import "@godxjp/ui/styles"` (fonts bundled) or `@import "@godxjp/ui/styles/core"` (no fonts). Never cherry-pick `*-layout.css`.
6
6
  2. Every page is `<PageContainer title subtitle extra footer>`; its sections are spaced by the page. Group items inside a section with `<Flex direction="col" gap>` or `<ResponsiveGrid>`.
7
7
  3. No Tailwind layout on your own elements: no `flex`, `grid`, `gap-*`, `p-*`, `m-*`, `space-*`. Rows are `<Flex>` (default row), stacks are `<Flex direction="col">`, grids are `<ResponsiveGrid>`.
8
- 4. No hand-rolled surfaces: no `rounded-* border bg-*` divs. A box is `Card`, a pill is `Badge`, a person is `Avatar`, a row is `ListRow`, a label/value pair is `Descriptions`, an empty area is `EmptyState`.
8
+ 4. No hand-rolled surfaces: no `rounded-* border bg-*` divs. A box is `Card`, a pill is `Badge`, a person is `Avatar`, a row is `ListRow`, a label/value pair is `Descriptions`, an empty area is `EmptyState`, a read-only sample of a colour the USER chose is `Swatch`.
9
9
  5. Real controls only: `Button`, `Input`, `Select`, `Textarea`, `Checkbox`… never raw `<button>`/`<input>`; a labelled control lives in `<FormField label>`. A Select outside a form takes `width="auto"`. **A disabled control's reason is visible text, never a tooltip** — see below.
10
10
  6. Text is `<Text>` / `<Heading>` with `tone`, `size`, `weight`, `truncate`, `mono` — not `className="text-muted-foreground font-semibold"`.
11
11
  7. Colours are semantic tokens (`tone="destructive"`, `bg-primary`), never palette names, hex, or `bg-black` / `text-white`.
@@ -253,7 +253,8 @@ a weaker one.** An algorithm guarantees a value is _consistent_; this repo had t
253
253
  times (below) precisely because consistent is not the same as _accessible_. A threshold guarantees
254
254
  the property actually being sold.
255
255
 
256
- **To change a derived value:** change it, run `pnpm test`, and if a threshold breaks the value is
256
+ **To change a derived value:** change it, run the test file that owns the threshold (never the full
257
+ suite — that is CI's job on the PR), and if a threshold breaks the value is
257
258
  wrong. Do not relax the threshold.
258
259
 
259
260
  **The four overrides that existed even while a generator did** — the clearest evidence the
@@ -3,16 +3,27 @@
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: **135**
7
- - With ≥1 frame: **130** · zero-frame: **5**
6
+ - Public components: **150**
7
+ - With ≥1 frame: **134** · zero-frame: **16**
8
8
  - Fully covered (every contract axis declared): **0**
9
9
 
10
10
  ## UNTESTED — no `/frame/**` route
11
11
 
12
12
  - [ ] `inertiaUpload`
13
+ - [ ] `FormFieldControl`
14
+ - [ ] `FormFieldArray`
15
+ - [ ] `useZodForm`
13
16
  - [ ] `CardBar`
14
17
  - [ ] `VisuallyHidden`
15
18
  - [ ] `RangeTimeline`
19
+ - [ ] `ServiceCatalogCta`
20
+ - [ ] `OverlayPortalProvider`
21
+ - [ ] `SkeletonArticle`
22
+ - [ ] `SkeletonAvatar`
23
+ - [ ] `SkeletonButton`
24
+ - [ ] `SkeletonInput`
25
+ - [ ] `SkeletonNode`
26
+ - [ ] `SkeletonImage`
16
27
  - [ ] `ChatBubbleList`
17
28
 
18
29
  ## Per-component contract axes
@@ -22,6 +33,10 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
22
33
  | Component | Frame | visua | state | owner | conte | respo | inter | acces | prefe | async |
23
34
  | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
24
35
  | inertiaUpload | **✗** | · | · | · | · | · | · | · | · | · |
36
+ | FormRoot | ✓ | · | · | · | · | · | · | · | · | · |
37
+ | FormFieldControl | **✗** | · | · | · | · | · | · | · | · | · |
38
+ | FormFieldArray | **✗** | · | · | · | · | · | · | · | · | · |
39
+ | useZodForm | **✗** | · | · | · | · | · | · | · | · | · |
25
40
  | CardBar | **✗** | N/A | N/A | N/A | · | · | · | · | · | · |
26
41
  | TimeRangePicker | ✓ | · | · | · | · | · | · | · | · | · |
27
42
  | VisuallyHidden | **✗** | N/A | N/A | N/A | · | · | · | · | · | · |
@@ -53,8 +68,12 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
53
68
  | CardContent | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
54
69
  | StatCard | ✓ | N/A | N/A | · | · | · | · | · | · | · |
55
70
  | ServiceLauncherCard | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
71
+ | ServiceCatalogCta | **✗** | N/A | N/A | N/A | · | · | · | · | · | · |
56
72
  | Badge | ✓ | ✓ | N/A | N/A | · | · | · | · | · | · |
57
73
  | Legend | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
74
+ | Swatch | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
75
+ | FeatureList | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
76
+ | Thumbnail | ✓ | · | N/A | N/A | · | · | · | · | · | · |
58
77
  | ListRow | ✓ | ✓ | N/A | N/A | · | · | · | · | · | · |
59
78
  | CredentialReveal | ✓ | ✓ | N/A | N/A | · | · | · | · | · | · |
60
79
  | QrCode | ✓ | ✓ | N/A | · | · | · | · | · | · | · |
@@ -95,6 +114,7 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
95
114
  | Steps | ✓ | ✓ | N/A | · | · | · | · | · | · | · |
96
115
  | Toolbar | ✓ | N/A | · | N/A | · | · | · | · | · | · |
97
116
  | AppProvider | ✓ | · | · | · | · | · | · | · | · | · |
117
+ | OverlayPortalProvider | **✗** | · | · | · | · | · | · | · | · | · |
98
118
  | formatDate | ✓ | · | · | · | · | · | · | · | · | · |
99
119
  | TimePicker | ✓ | · | · | · | · | · | · | · | · | · |
100
120
  | Cascader | ✓ | ✓ | · | · | · | · | · | · | · | · |
@@ -116,7 +136,13 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
116
136
  | PrefetchLink | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
117
137
  | Avatar | ✓ | ✓ | N/A | N/A | · | · | · | · | · | · |
118
138
  | Separator | ✓ | · | N/A | N/A | · | · | · | · | · | · |
119
- | Skeleton | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
139
+ | Skeleton | ✓ | N/A | · | N/A | · | · | · | · | · | · |
140
+ | SkeletonArticle | **✗** | N/A | · | N/A | · | · | · | · | · | · |
141
+ | SkeletonAvatar | **✗** | ✓ | N/A | N/A | · | · | · | · | · | · |
142
+ | SkeletonButton | **✗** | ✓ | N/A | N/A | · | · | · | · | · | · |
143
+ | SkeletonInput | **✗** | ✓ | N/A | N/A | · | · | · | · | · | · |
144
+ | SkeletonNode | **✗** | N/A | N/A | N/A | · | · | · | · | · | · |
145
+ | SkeletonImage | **✗** | N/A | N/A | N/A | · | · | · | · | · | · |
120
146
  | Toggle | ✓ | ✓ | · | N/A | · | · | · | · | · | · |
121
147
  | ToggleGroup | ✓ | ✓ | · | · | · | · | · | · | · | · |
122
148
  | AspectRatio | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
@@ -0,0 +1,12 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="960" height="540" viewBox="0 0 960 540" role="img">
2
+ <rect width="960" height="540" fill="hsl(210 20% 97%)"/>
3
+ <rect width="960" height="56" fill="hsl(152 34% 38%)"/>
4
+ <rect x="24" y="22" width="140" height="12" rx="6" fill="hsl(152 34% 80%)"/>
5
+ <rect y="56" width="216" height="484" fill="hsl(210 16% 92%)"/>
6
+ <rect x="24" y="92" width="160" height="10" rx="5" fill="hsl(210 12% 76%)"/>
7
+ <rect x="24" y="124" width="160" height="10" rx="5" fill="hsl(210 12% 82%)"/>
8
+ <rect x="24" y="156" width="160" height="10" rx="5" fill="hsl(210 12% 82%)"/>
9
+ <rect x="248" y="92" width="320" height="160" rx="12" fill="hsl(210 16% 88%)"/>
10
+ <rect x="592" y="92" width="320" height="160" rx="12" fill="hsl(210 16% 88%)"/>
11
+ <rect x="248" y="284" width="664" height="212" rx="12" fill="hsl(210 16% 90%)"/>
12
+ </svg>
@@ -0,0 +1,10 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="360" height="640" viewBox="0 0 360 640" role="img">
2
+ <rect width="360" height="640" fill="hsl(210 20% 97%)"/>
3
+ <rect width="360" height="72" fill="hsl(204 60% 46%)"/>
4
+ <rect x="20" y="30" width="120" height="12" rx="6" fill="hsl(204 60% 82%)"/>
5
+ <rect x="20" y="104" width="320" height="120" rx="10" fill="hsl(210 16% 88%)"/>
6
+ <rect x="20" y="248" width="320" height="64" rx="10" fill="hsl(210 16% 90%)"/>
7
+ <rect x="20" y="336" width="320" height="64" rx="10" fill="hsl(210 16% 90%)"/>
8
+ <rect x="20" y="424" width="320" height="64" rx="10" fill="hsl(210 16% 90%)"/>
9
+ <rect x="20" y="540" width="320" height="44" rx="10" fill="hsl(204 60% 46%)"/>
10
+ </svg>
@@ -111,6 +111,12 @@ export default function Demo() {
111
111
  </CardHeader>
112
112
  <CardContent>枠線のみ</CardContent>
113
113
  </Card>
114
+ <Card variant="borderless">
115
+ <CardHeader>
116
+ <CardTitle level={2}>borderless</CardTitle>
117
+ </CardHeader>
118
+ <CardContent>塗りのみ · 枠線なし</CardContent>
119
+ </Card>
114
120
  <Card variant="featured">
115
121
  <CardHeader>
116
122
  <CardTitle level={2}>featured</CardTitle>
@@ -120,6 +126,40 @@ export default function Demo() {
120
126
  </ResponsiveGrid>
121
127
  </Flex>
122
128
 
129
+ <Flex direction="col" gap="sm">
130
+ <Text as="div" weight="medium">
131
+ hoverable · actions — Ant Design の hoverable と actions
132
+ </Text>
133
+ <ResponsiveGrid columns={{ sm: 1, md: 2 }}>
134
+ {/*
135
+ * `hoverable` は見た目だけのフラグです。カード全体が押せるように見えるなら、
136
+ * キーボードでも届く本物のコントロールを必ず同居させます(ここでは footer の
137
+ * Button)。div に onClick を置くのは禁止です。
138
+ */}
139
+ <Card hoverable>
140
+ <CardHeader>
141
+ <CardTitle level={2}>ホバーで浮き上がる</CardTitle>
142
+ <CardDescription>--card-hover-shadow まで一段上がります</CardDescription>
143
+ </CardHeader>
144
+ <CardFooter actions>
145
+ <Button variant="ghost">複製</Button>
146
+ <Button variant="ghost">共有</Button>
147
+ <Button variant="ghost">削除</Button>
148
+ </CardFooter>
149
+ </Card>
150
+ <Card hoverable accent="info" accentPlacement="perimeter">
151
+ <CardHeader>
152
+ <CardTitle level={2}>accent と併用</CardTitle>
153
+ <CardDescription>ホバー中もアテンションのリングは消えません</CardDescription>
154
+ </CardHeader>
155
+ <CardFooter actions>
156
+ <Button variant="ghost">承認</Button>
157
+ <Button variant="ghost">却下</Button>
158
+ </CardFooter>
159
+ </Card>
160
+ </ResponsiveGrid>
161
+ </Flex>
162
+
123
163
  <Flex direction="col" gap="sm">
124
164
  <Text as="div" weight="medium">
125
165
  Accent · accentPlacement=&quot;edge&quot; (既定 · 先頭エッジのレール)