@godxjp/ui 31.2.0 → 31.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent/START-HERE.md +6 -6
- package/agent/components/AuthExpiryProvider.json +40 -0
- package/agent/components/DataState.json +3 -1
- package/agent/components/InfiniteQueryState.json +1 -1
- package/agent/components/Tabs.json +5 -0
- package/agent/components-index.json +5 -0
- package/agent/components.json +49 -2
- package/agent/index.json +7 -7
- package/agent/llms.txt +6 -6
- package/agent/patterns/async-data-state.json +1 -1
- package/agent/patterns.json +1 -1
- package/agent/tokens.json +39 -3
- package/dist/components/admin/index.d.ts +2 -0
- package/dist/components/admin/index.js +2 -0
- package/dist/components/data-entry/upload.js +12 -1
- package/dist/components/feedback/alert.d.ts +4 -0
- package/dist/components/feedback/alert.js +29 -8
- package/dist/components/feedback/auth-expiry.d.ts +30 -0
- package/dist/components/feedback/auth-expiry.js +64 -0
- package/dist/components/feedback/index.d.ts +2 -0
- package/dist/components/feedback/index.js +2 -0
- package/dist/components/navigation/tabs.d.ts +2 -2
- package/dist/components/navigation/tabs.js +57 -10
- package/dist/components/query/data-state.js +9 -0
- package/dist/components/query/index.d.ts +2 -0
- package/dist/components/query/index.js +2 -0
- package/dist/components/query/infinite-query-state.js +9 -0
- package/dist/contracts/measurement.json +1 -1
- package/dist/i18n/messages/en.json +3 -0
- package/dist/i18n/messages/ja.json +3 -0
- package/dist/i18n/messages/vi.json +3 -0
- package/dist/props/components/feedback.prop.d.ts +13 -0
- package/dist/props/components/index.d.ts +1 -1
- package/dist/props/components/navigation.prop.d.ts +19 -1
- package/dist/props/registry.d.ts +11 -2
- package/dist/props/registry.js +13 -0
- package/dist/styles/alert-layout.css +16 -12
- package/dist/styles/control.css +18 -2
- package/dist/styles/data-entry-layout.css +4 -0
- package/dist/styles/form-layout.css +47 -5
- package/dist/styles/layers.json +35 -1
- package/dist/styles/layout.css +2 -1
- package/dist/tokens/components/feedback.css +2 -0
- package/dist/tokens/components/segmented.css +4 -0
- package/dist/tokens/semantic/layout.css +2 -0
- package/docs/FRAME-COVERAGE-REPORT.md +4 -2
- package/docs/data-entry/segmented.tsx +2 -0
- package/docs/feedback/auth-expiry.tsx +104 -0
- package/docs/i18n/messages/en.json +6 -0
- package/docs/i18n/messages/ja.json +6 -0
- package/docs/i18n/messages/vi.json +6 -0
- package/docs/navigation/tabs.tsx +43 -0
- package/docs/query/data-state.tsx +84 -12
- package/docs/showcase/table-view-tabs.tsx +15 -13
- package/docs/themes/flat.css +4 -0
- package/docs/themes/glassmorphism.css +2 -0
- package/docs/themes/neubrutalism.css +6 -0
- package/package.json +2 -2
package/dist/styles/control.css
CHANGED
|
@@ -1282,13 +1282,29 @@
|
|
|
1282
1282
|
margin-inline-start: var(--segmented-count-gap);
|
|
1283
1283
|
border-radius: var(--segmented-count-radius);
|
|
1284
1284
|
padding-inline: var(--segmented-count-space-inline);
|
|
1285
|
-
|
|
1286
|
-
|
|
1285
|
+
|
|
1286
|
+
background: var(--segmented-count-background, hsl(var(--background)));
|
|
1287
|
+
color: var(--segmented-count-color, hsl(var(--muted-foreground)));
|
|
1287
1288
|
font-size: var(--segmented-count-font-size);
|
|
1288
1289
|
line-height: 1;
|
|
1289
1290
|
font-variant-numeric: tabular-nums;
|
|
1290
1291
|
}
|
|
1291
1292
|
|
|
1293
|
+
.ui-segmented-item[data-state="checked"] .ui-segmented-count {
|
|
1294
|
+
background: var(
|
|
1295
|
+
--segmented-count-selected-background,
|
|
1296
|
+
hsl(var(--primary) / var(--segmented-count-selected-background-alpha, 100%))
|
|
1297
|
+
);
|
|
1298
|
+
color: var(--segmented-count-selected-color, hsl(var(--primary-foreground)));
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
@media (forced-colors: active) {
|
|
1302
|
+
.ui-segmented-item[data-state="checked"] .ui-segmented-count {
|
|
1303
|
+
outline: var(--segmented-count-forced-outline-width, var(--stroke-hairline)) solid
|
|
1304
|
+
currentColor;
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1292
1308
|
.ui-tag-input {
|
|
1293
1309
|
display: flex;
|
|
1294
1310
|
flex-wrap: wrap;
|
|
@@ -60,6 +60,9 @@
|
|
|
60
60
|
inline-size: 100%;
|
|
61
61
|
|
|
62
62
|
align-self: start;
|
|
63
|
+
|
|
64
|
+
--form-field-control-band: initial;
|
|
65
|
+
--form-field-first-line: initial;
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
.ui-form-field[data-layout="inline"] {
|
|
@@ -84,6 +87,40 @@
|
|
|
84
87
|
|
|
85
88
|
min-height: var(--control-height);
|
|
86
89
|
align-content: center;
|
|
90
|
+
|
|
91
|
+
grid-template-rows: minmax(var(--form-field-control-band, auto), auto);
|
|
92
|
+
align-items: center;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.ui-form-field-control:has(> .ui-form-field-note:first-child) {
|
|
96
|
+
grid-template-rows: none;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.ui-form-field-control
|
|
100
|
+
> fieldset
|
|
101
|
+
> :is(.ui-choice-group[data-orientation="vertical"], .ui-choice-field) {
|
|
102
|
+
align-self: start;
|
|
103
|
+
margin-block-start: max(
|
|
104
|
+
0px,
|
|
105
|
+
calc(
|
|
106
|
+
(
|
|
107
|
+
var(--form-field-control-band, 0px) - var(--font-size-base) *
|
|
108
|
+
var(--control-label-line-height)
|
|
109
|
+
) /
|
|
110
|
+
2
|
|
111
|
+
)
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.ui-form-field:has(
|
|
116
|
+
> .ui-form-field-control
|
|
117
|
+
> fieldset
|
|
118
|
+
> :is(.ui-control-multiline, [data-slot="textarea-affix-wrapper"])
|
|
119
|
+
) {
|
|
120
|
+
--form-field-first-line: calc(
|
|
121
|
+
var(--control-border-width, var(--stroke-hairline)) + var(--control-multiline-padding-block) +
|
|
122
|
+
0.5lh
|
|
123
|
+
);
|
|
87
124
|
}
|
|
88
125
|
|
|
89
126
|
.ui-form-field-control > * {
|
|
@@ -96,13 +133,14 @@
|
|
|
96
133
|
) {
|
|
97
134
|
grid-template-columns: var(--form-label-width, max-content) minmax(0, 1fr);
|
|
98
135
|
align-items: start;
|
|
136
|
+
--form-field-control-band: var(--control-height);
|
|
99
137
|
column-gap: var(--form-label-gap);
|
|
100
138
|
row-gap: var(--space-stack-xs);
|
|
101
139
|
}
|
|
102
140
|
|
|
103
141
|
.ui-form-field[data-collapse-below="false"]:is([data-layout="horizontal"], [data-layout="inline"])
|
|
104
142
|
> .ui-form-field-label {
|
|
105
|
-
min-block-size: var(--control-height);
|
|
143
|
+
min-block-size: calc(2 * var(--form-field-first-line, var(--control-height) / 2));
|
|
106
144
|
flex-wrap: wrap;
|
|
107
145
|
}
|
|
108
146
|
.ui-form-field[data-collapse-below="false"]:is([data-layout="horizontal"], [data-layout="inline"])
|
|
@@ -131,12 +169,13 @@
|
|
|
131
169
|
) {
|
|
132
170
|
grid-template-columns: var(--form-label-width, max-content) minmax(0, 1fr);
|
|
133
171
|
align-items: start;
|
|
172
|
+
--form-field-control-band: var(--control-height);
|
|
134
173
|
column-gap: var(--form-label-gap);
|
|
135
174
|
row-gap: var(--space-stack-xs);
|
|
136
175
|
}
|
|
137
176
|
.ui-form-field[data-collapse-below="sm"]:is([data-layout="horizontal"], [data-layout="inline"])
|
|
138
177
|
> .ui-form-field-label {
|
|
139
|
-
min-block-size: var(--control-height);
|
|
178
|
+
min-block-size: calc(2 * var(--form-field-first-line, var(--control-height) / 2));
|
|
140
179
|
flex-wrap: wrap;
|
|
141
180
|
}
|
|
142
181
|
.ui-form-field[data-collapse-below="sm"]:is([data-layout="horizontal"], [data-layout="inline"])
|
|
@@ -165,12 +204,13 @@
|
|
|
165
204
|
) {
|
|
166
205
|
grid-template-columns: var(--form-label-width, max-content) minmax(0, 1fr);
|
|
167
206
|
align-items: start;
|
|
207
|
+
--form-field-control-band: var(--control-height);
|
|
168
208
|
column-gap: var(--form-label-gap);
|
|
169
209
|
row-gap: var(--space-stack-xs);
|
|
170
210
|
}
|
|
171
211
|
.ui-form-field[data-collapse-below="md"]:is([data-layout="horizontal"], [data-layout="inline"])
|
|
172
212
|
> .ui-form-field-label {
|
|
173
|
-
min-block-size: var(--control-height);
|
|
213
|
+
min-block-size: calc(2 * var(--form-field-first-line, var(--control-height) / 2));
|
|
174
214
|
flex-wrap: wrap;
|
|
175
215
|
}
|
|
176
216
|
.ui-form-field[data-collapse-below="md"]:is([data-layout="horizontal"], [data-layout="inline"])
|
|
@@ -199,12 +239,13 @@
|
|
|
199
239
|
) {
|
|
200
240
|
grid-template-columns: var(--form-label-width, max-content) minmax(0, 1fr);
|
|
201
241
|
align-items: start;
|
|
242
|
+
--form-field-control-band: var(--control-height);
|
|
202
243
|
column-gap: var(--form-label-gap);
|
|
203
244
|
row-gap: var(--space-stack-xs);
|
|
204
245
|
}
|
|
205
246
|
.ui-form-field[data-collapse-below="lg"]:is([data-layout="horizontal"], [data-layout="inline"])
|
|
206
247
|
> .ui-form-field-label {
|
|
207
|
-
min-block-size: var(--control-height);
|
|
248
|
+
min-block-size: calc(2 * var(--form-field-first-line, var(--control-height) / 2));
|
|
208
249
|
flex-wrap: wrap;
|
|
209
250
|
}
|
|
210
251
|
.ui-form-field[data-collapse-below="lg"]:is([data-layout="horizontal"], [data-layout="inline"])
|
|
@@ -233,12 +274,13 @@
|
|
|
233
274
|
) {
|
|
234
275
|
grid-template-columns: var(--form-label-width, max-content) minmax(0, 1fr);
|
|
235
276
|
align-items: start;
|
|
277
|
+
--form-field-control-band: var(--control-height);
|
|
236
278
|
column-gap: var(--form-label-gap);
|
|
237
279
|
row-gap: var(--space-stack-xs);
|
|
238
280
|
}
|
|
239
281
|
.ui-form-field[data-collapse-below="xl"]:is([data-layout="horizontal"], [data-layout="inline"])
|
|
240
282
|
> .ui-form-field-label {
|
|
241
|
-
min-block-size: var(--control-height);
|
|
283
|
+
min-block-size: calc(2 * var(--form-field-first-line, var(--control-height) / 2));
|
|
242
284
|
flex-wrap: wrap;
|
|
243
285
|
}
|
|
244
286
|
.ui-form-field[data-collapse-below="xl"]:is([data-layout="horizontal"], [data-layout="inline"])
|
package/dist/styles/layers.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "31.
|
|
2
|
+
"version": "31.4.0",
|
|
3
3
|
"generatedBy": "scripts/gen-style-layers.mjs — do not edit by hand; run `pnpm gen:style-layers`",
|
|
4
4
|
"base": "base.css",
|
|
5
5
|
"fonts": "fonts.css",
|
|
@@ -67,6 +67,8 @@
|
|
|
67
67
|
"layers": [
|
|
68
68
|
"layout.css",
|
|
69
69
|
"control.css",
|
|
70
|
+
"text-layout.css",
|
|
71
|
+
"dialog-layout.css",
|
|
70
72
|
"alert-layout.css"
|
|
71
73
|
]
|
|
72
74
|
},
|
|
@@ -74,6 +76,7 @@
|
|
|
74
76
|
"layers": [
|
|
75
77
|
"layout.css",
|
|
76
78
|
"control.css",
|
|
79
|
+
"text-layout.css",
|
|
77
80
|
"dialog-layout.css",
|
|
78
81
|
"alert-layout.css",
|
|
79
82
|
"form-layout.css"
|
|
@@ -83,6 +86,7 @@
|
|
|
83
86
|
"layers": [
|
|
84
87
|
"layout.css",
|
|
85
88
|
"control.css",
|
|
89
|
+
"text-layout.css",
|
|
86
90
|
"dialog-layout.css",
|
|
87
91
|
"alert-layout.css",
|
|
88
92
|
"form-layout.css"
|
|
@@ -99,6 +103,7 @@
|
|
|
99
103
|
"shell-layout.css",
|
|
100
104
|
"layout.css",
|
|
101
105
|
"control.css",
|
|
106
|
+
"text-layout.css",
|
|
102
107
|
"dialog-layout.css",
|
|
103
108
|
"alert-layout.css",
|
|
104
109
|
"form-layout.css"
|
|
@@ -157,6 +162,9 @@
|
|
|
157
162
|
"layout.css"
|
|
158
163
|
]
|
|
159
164
|
},
|
|
165
|
+
"AuthExpiryProvider": {
|
|
166
|
+
"layers": []
|
|
167
|
+
},
|
|
160
168
|
"AuthFooter": {
|
|
161
169
|
"layers": [
|
|
162
170
|
"shell-layout.css"
|
|
@@ -195,6 +203,8 @@
|
|
|
195
203
|
"layers": [
|
|
196
204
|
"layout.css",
|
|
197
205
|
"control.css",
|
|
206
|
+
"text-layout.css",
|
|
207
|
+
"dialog-layout.css",
|
|
198
208
|
"alert-layout.css"
|
|
199
209
|
]
|
|
200
210
|
},
|
|
@@ -241,6 +251,8 @@
|
|
|
241
251
|
"layers": [
|
|
242
252
|
"layout.css",
|
|
243
253
|
"control.css",
|
|
254
|
+
"text-layout.css",
|
|
255
|
+
"dialog-layout.css",
|
|
244
256
|
"alert-layout.css"
|
|
245
257
|
]
|
|
246
258
|
},
|
|
@@ -357,6 +369,7 @@
|
|
|
357
369
|
"layers": [
|
|
358
370
|
"layout.css",
|
|
359
371
|
"control.css",
|
|
372
|
+
"text-layout.css",
|
|
360
373
|
"dialog-layout.css",
|
|
361
374
|
"alert-layout.css",
|
|
362
375
|
"form-layout.css"
|
|
@@ -390,6 +403,8 @@
|
|
|
390
403
|
"layers": [
|
|
391
404
|
"layout.css",
|
|
392
405
|
"control.css",
|
|
406
|
+
"text-layout.css",
|
|
407
|
+
"dialog-layout.css",
|
|
393
408
|
"alert-layout.css"
|
|
394
409
|
]
|
|
395
410
|
},
|
|
@@ -397,6 +412,7 @@
|
|
|
397
412
|
"layers": [
|
|
398
413
|
"layout.css",
|
|
399
414
|
"control.css",
|
|
415
|
+
"text-layout.css",
|
|
400
416
|
"table-layout.css",
|
|
401
417
|
"dialog-layout.css",
|
|
402
418
|
"alert-layout.css",
|
|
@@ -423,6 +439,7 @@
|
|
|
423
439
|
"layers": [
|
|
424
440
|
"layout.css",
|
|
425
441
|
"control.css",
|
|
442
|
+
"text-layout.css",
|
|
426
443
|
"dialog-layout.css",
|
|
427
444
|
"alert-layout.css",
|
|
428
445
|
"form-layout.css"
|
|
@@ -490,6 +507,8 @@
|
|
|
490
507
|
"layers": [
|
|
491
508
|
"layout.css",
|
|
492
509
|
"control.css",
|
|
510
|
+
"text-layout.css",
|
|
511
|
+
"dialog-layout.css",
|
|
493
512
|
"alert-layout.css",
|
|
494
513
|
"form-layout.css"
|
|
495
514
|
]
|
|
@@ -498,6 +517,8 @@
|
|
|
498
517
|
"layers": [
|
|
499
518
|
"layout.css",
|
|
500
519
|
"control.css",
|
|
520
|
+
"text-layout.css",
|
|
521
|
+
"dialog-layout.css",
|
|
501
522
|
"alert-layout.css"
|
|
502
523
|
]
|
|
503
524
|
},
|
|
@@ -505,6 +526,8 @@
|
|
|
505
526
|
"layers": [
|
|
506
527
|
"layout.css",
|
|
507
528
|
"control.css",
|
|
529
|
+
"text-layout.css",
|
|
530
|
+
"dialog-layout.css",
|
|
508
531
|
"alert-layout.css",
|
|
509
532
|
"form-layout.css"
|
|
510
533
|
]
|
|
@@ -516,6 +539,8 @@
|
|
|
516
539
|
"layers": [
|
|
517
540
|
"layout.css",
|
|
518
541
|
"control.css",
|
|
542
|
+
"text-layout.css",
|
|
543
|
+
"dialog-layout.css",
|
|
519
544
|
"alert-layout.css",
|
|
520
545
|
"form-layout.css"
|
|
521
546
|
]
|
|
@@ -524,6 +549,8 @@
|
|
|
524
549
|
"layers": [
|
|
525
550
|
"layout.css",
|
|
526
551
|
"control.css",
|
|
552
|
+
"text-layout.css",
|
|
553
|
+
"dialog-layout.css",
|
|
527
554
|
"alert-layout.css",
|
|
528
555
|
"form-layout.css"
|
|
529
556
|
]
|
|
@@ -549,6 +576,8 @@
|
|
|
549
576
|
"layers": [
|
|
550
577
|
"layout.css",
|
|
551
578
|
"control.css",
|
|
579
|
+
"text-layout.css",
|
|
580
|
+
"dialog-layout.css",
|
|
552
581
|
"alert-layout.css"
|
|
553
582
|
]
|
|
554
583
|
},
|
|
@@ -649,6 +678,7 @@
|
|
|
649
678
|
"shell-layout.css",
|
|
650
679
|
"layout.css",
|
|
651
680
|
"control.css",
|
|
681
|
+
"text-layout.css",
|
|
652
682
|
"dialog-layout.css",
|
|
653
683
|
"alert-layout.css",
|
|
654
684
|
"form-layout.css"
|
|
@@ -666,6 +696,7 @@
|
|
|
666
696
|
"layers": [
|
|
667
697
|
"layout.css",
|
|
668
698
|
"control.css",
|
|
699
|
+
"text-layout.css",
|
|
669
700
|
"dialog-layout.css",
|
|
670
701
|
"alert-layout.css",
|
|
671
702
|
"form-layout.css",
|
|
@@ -1103,6 +1134,7 @@
|
|
|
1103
1134
|
"layers": [
|
|
1104
1135
|
"layout.css",
|
|
1105
1136
|
"control.css",
|
|
1137
|
+
"text-layout.css",
|
|
1106
1138
|
"dialog-layout.css",
|
|
1107
1139
|
"alert-layout.css",
|
|
1108
1140
|
"data-display-layout.css",
|
|
@@ -1150,6 +1182,7 @@
|
|
|
1150
1182
|
"layers": [
|
|
1151
1183
|
"layout.css",
|
|
1152
1184
|
"control.css",
|
|
1185
|
+
"text-layout.css",
|
|
1153
1186
|
"dialog-layout.css",
|
|
1154
1187
|
"alert-layout.css",
|
|
1155
1188
|
"data-display-layout.css",
|
|
@@ -1162,6 +1195,7 @@
|
|
|
1162
1195
|
"layers": [
|
|
1163
1196
|
"layout.css",
|
|
1164
1197
|
"control.css",
|
|
1198
|
+
"text-layout.css",
|
|
1165
1199
|
"dialog-layout.css",
|
|
1166
1200
|
"alert-layout.css",
|
|
1167
1201
|
"form-layout.css"
|
package/dist/styles/layout.css
CHANGED
|
@@ -133,6 +133,8 @@
|
|
|
133
133
|
--query-load-more-space-block-start: var(--space-stack-md);
|
|
134
134
|
--query-loading-more-space-block-start: var(--space-stack-sm);
|
|
135
135
|
|
|
136
|
+
--query-auth-alert-max-inline-size: 36rem;
|
|
137
|
+
|
|
136
138
|
--tooltip-max-width: 20rem;
|
|
137
139
|
--tooltip-space-inline: var(--space-2);
|
|
138
140
|
--tooltip-space-block: var(--space-1);
|
|
@@ -46,4 +46,8 @@
|
|
|
46
46
|
--segmented-count-gap: var(--space-1);
|
|
47
47
|
--segmented-count-background: initial;
|
|
48
48
|
--segmented-count-color: initial;
|
|
49
|
+
--segmented-count-selected-background: initial;
|
|
50
|
+
--segmented-count-selected-background-alpha: initial;
|
|
51
|
+
--segmented-count-selected-color: initial;
|
|
52
|
+
--segmented-count-forced-outline-width: initial;
|
|
49
53
|
}
|
|
@@ -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: **152** · zero-frame: **
|
|
6
|
+
- Public components: **176**
|
|
7
|
+
- With ≥1 frame: **152** · zero-frame: **24**
|
|
8
8
|
- Fully covered (every contract axis declared): **0**
|
|
9
9
|
|
|
10
10
|
## UNTESTED — no `/frame/**` route
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
- [ ] `Paragraph`
|
|
21
21
|
- [ ] `Link`
|
|
22
22
|
- [ ] `ServiceCatalogCta`
|
|
23
|
+
- [ ] `AuthExpiryProvider`
|
|
23
24
|
- [ ] `SkeletonRows`
|
|
24
25
|
- [ ] `OverlayPortalProvider`
|
|
25
26
|
- [ ] `SkeletonDetail`
|
|
@@ -101,6 +102,7 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
|
|
|
101
102
|
| TimelineGrid | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
|
|
102
103
|
| Table | ✓ | N/A | N/A | N/A | · | · | · | · | · | · |
|
|
103
104
|
| DataState | ✓ | N/A | · | N/A | · | · | · | · | · | · |
|
|
105
|
+
| AuthExpiryProvider | **✗** | N/A | N/A | N/A | · | · | · | · | · | · |
|
|
104
106
|
| InfiniteQueryState | ✓ | N/A | · | N/A | · | · | · | · | · | · |
|
|
105
107
|
| Form | ✓ | ✓ | · | N/A | · | · | · | · | · | · |
|
|
106
108
|
| FormField | ✓ | N/A | · | N/A | · | · | · | · | · | · |
|
|
@@ -90,6 +90,8 @@ export default function Demo() {
|
|
|
90
90
|
<CardDescription>
|
|
91
91
|
一覧の上の状態フィルター。4 つが 1 行に収まらない幅では、トラックが 2 行目に折り返し
|
|
92
92
|
ます。ラベルも件数も切り詰めません。`check:segmented-wrap` がこのカードを測ります。
|
|
93
|
+
件数は Tabs と同じ扱いで、選択中の項目だけ強調し、ほかは控えめな色です。0 件を隠す
|
|
94
|
+
ときは `showZero: false`。
|
|
93
95
|
</CardDescription>
|
|
94
96
|
</CardHeader>
|
|
95
97
|
<CardContent>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { QueryClient, QueryClientProvider, useMutation, useQuery } from "@tanstack/react-query";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
Card,
|
|
6
|
+
CardContent,
|
|
7
|
+
CardDescription,
|
|
8
|
+
CardHeader,
|
|
9
|
+
CardTitle,
|
|
10
|
+
DataTable,
|
|
11
|
+
type ColumnDef,
|
|
12
|
+
} from "@godxjp/ui/data-display";
|
|
13
|
+
import { SkeletonTable } from "@godxjp/ui/feedback";
|
|
14
|
+
import { Button, Text } from "@godxjp/ui/general";
|
|
15
|
+
import { useTranslation } from "@godxjp/ui/i18n";
|
|
16
|
+
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
17
|
+
import { AlertMutationFeedback, AuthExpiryProvider, DataState } from "@godxjp/ui/query";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* AuthExpiryProvider · the app root owns an expired session (gh#1022). Every DataState /
|
|
21
|
+
* InfiniteQueryState / AlertMutationFeedback / AlertQueryError underneath calls `onAuthExpired`
|
|
22
|
+
* automatically, once for any number of simultaneous 401s, and shows a neutral pending state
|
|
23
|
+
* instead of an error alert. A real app redirects to its IdP here:
|
|
24
|
+
* window.location.assign(`/auth/login?return_to=${encodeURIComponent(location.href)}`)
|
|
25
|
+
*/
|
|
26
|
+
const queryClient = new QueryClient({
|
|
27
|
+
defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
type Member = { id: string; name: string };
|
|
31
|
+
|
|
32
|
+
const expired = () => Object.assign(new Error("Access token expired"), { status: 401 });
|
|
33
|
+
|
|
34
|
+
function MembersCard() {
|
|
35
|
+
const { t } = useTranslation();
|
|
36
|
+
const columns: ColumnDef<Member>[] = [
|
|
37
|
+
{ key: "id", header: "ID" },
|
|
38
|
+
{ key: "name", header: t("authExpiryDocs.nameColumn") },
|
|
39
|
+
];
|
|
40
|
+
const query = useQuery<Member[]>({
|
|
41
|
+
queryKey: ["auth-expiry-members"],
|
|
42
|
+
queryFn: async () => {
|
|
43
|
+
throw expired();
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
return (
|
|
47
|
+
<Card>
|
|
48
|
+
<CardHeader>
|
|
49
|
+
<CardTitle level={2}>{t("authExpiryDocs.membersTitle")}</CardTitle>
|
|
50
|
+
<CardDescription>A 401 keeps the skeleton and announces the redirect.</CardDescription>
|
|
51
|
+
</CardHeader>
|
|
52
|
+
<CardContent flush>
|
|
53
|
+
<DataState query={query} skeleton={<SkeletonTable rows={3} columns={2} />}>
|
|
54
|
+
{(d) => <DataTable data={d} columns={columns} getRowId={(r) => r.id} />}
|
|
55
|
+
</DataState>
|
|
56
|
+
</CardContent>
|
|
57
|
+
</Card>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function InviteCard() {
|
|
62
|
+
const { t } = useTranslation();
|
|
63
|
+
const mutation = useMutation({
|
|
64
|
+
mutationFn: async () => {
|
|
65
|
+
throw expired();
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
return (
|
|
69
|
+
<Card>
|
|
70
|
+
<CardHeader>
|
|
71
|
+
<CardTitle level={2}>{t("authExpiryDocs.inviteTitle")}</CardTitle>
|
|
72
|
+
<CardDescription>A 401 on submit shows a muted status line, not an alert.</CardDescription>
|
|
73
|
+
</CardHeader>
|
|
74
|
+
<CardContent>
|
|
75
|
+
<Flex direction="col" gap="md" align="start">
|
|
76
|
+
<Button onClick={() => mutation.mutate()}>{t("authExpiryDocs.send")}</Button>
|
|
77
|
+
<AlertMutationFeedback mutation={mutation} />
|
|
78
|
+
</Flex>
|
|
79
|
+
</CardContent>
|
|
80
|
+
</Card>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export default function Demo() {
|
|
85
|
+
const [calls, setCalls] = useState(0);
|
|
86
|
+
return (
|
|
87
|
+
<QueryClientProvider client={queryClient}>
|
|
88
|
+
<AuthExpiryProvider onAuthExpired={() => setCalls((n) => n + 1)}>
|
|
89
|
+
<PageContainer
|
|
90
|
+
title="AuthExpiryProvider"
|
|
91
|
+
subtitle="Expired session handled once at the app root, never as a page error"
|
|
92
|
+
>
|
|
93
|
+
<Flex direction="col" gap="lg">
|
|
94
|
+
<Text size="sm" tone="muted">
|
|
95
|
+
onAuthExpired calls: {calls}
|
|
96
|
+
</Text>
|
|
97
|
+
<MembersCard />
|
|
98
|
+
<InviteCard />
|
|
99
|
+
</Flex>
|
|
100
|
+
</PageContainer>
|
|
101
|
+
</AuthExpiryProvider>
|
|
102
|
+
</QueryClientProvider>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
@@ -1438,5 +1438,11 @@
|
|
|
1438
1438
|
"sample": "Mẫu",
|
|
1439
1439
|
"date": "Tháng 9/2026 · ngày dùng cho demo"
|
|
1440
1440
|
}
|
|
1441
|
+
},
|
|
1442
|
+
"authExpiryDocs": {
|
|
1443
|
+
"membersTitle": "Thành viên",
|
|
1444
|
+
"nameColumn": "Họ tên",
|
|
1445
|
+
"inviteTitle": "Gửi lời mời",
|
|
1446
|
+
"send": "Gửi"
|
|
1441
1447
|
}
|
|
1442
1448
|
}
|
package/docs/navigation/tabs.tsx
CHANGED
|
@@ -146,6 +146,7 @@ export default function Demo() {
|
|
|
146
146
|
},
|
|
147
147
|
]);
|
|
148
148
|
const [editableTab, setEditableTab] = useState("je-0042");
|
|
149
|
+
const [inboxStatus, setInboxStatus] = useState("open");
|
|
149
150
|
|
|
150
151
|
return (
|
|
151
152
|
<PageContainer
|
|
@@ -646,6 +647,48 @@ export default function Demo() {
|
|
|
646
647
|
</CardContent>
|
|
647
648
|
</Card>
|
|
648
649
|
|
|
650
|
+
{/* STRIP-ONLY (gh#1021). The strip drives a region OUTSIDE the Tabs, so no tabpanel is
|
|
651
|
+
rendered and the view below is never remounted by a tab switch. */}
|
|
652
|
+
<Card>
|
|
653
|
+
<CardHeader>
|
|
654
|
+
<CardTitle level={2}>controls · タブ列だけ(外部の領域を切り替える)</CardTitle>
|
|
655
|
+
<CardDescription>
|
|
656
|
+
controls に外部領域の id を渡すと tabpanel を描かず、選択中のタブの aria-controls
|
|
657
|
+
がその領域を指す。領域は Tabs の外にあるのでタブを切り替えても再マウントされない。
|
|
658
|
+
compound の TabsTrigger も items と同じ count を描く。
|
|
659
|
+
</CardDescription>
|
|
660
|
+
</CardHeader>
|
|
661
|
+
<CardContent>
|
|
662
|
+
<Flex direction="col" gap="md">
|
|
663
|
+
<Tabs
|
|
664
|
+
aria-label="対応状況"
|
|
665
|
+
controls="tabs-inbox-view"
|
|
666
|
+
variant="line"
|
|
667
|
+
value={inboxStatus}
|
|
668
|
+
onValueChange={setInboxStatus}
|
|
669
|
+
items={[
|
|
670
|
+
{ value: "open", label: "未対応", count: 12, countLabel: "件" },
|
|
671
|
+
{ value: "doing", label: "対応中", count: 3, countLabel: "件" },
|
|
672
|
+
{ value: "done", label: "完了", count: 128, countLabel: "件" },
|
|
673
|
+
]}
|
|
674
|
+
/>
|
|
675
|
+
<section id="tabs-inbox-view" aria-label="スレッド一覧">
|
|
676
|
+
<Text as="p">表示中: {inboxStatus}</Text>
|
|
677
|
+
</section>
|
|
678
|
+
<Tabs aria-label="保存ビュー" controls="tabs-inbox-view" defaultValue="mine">
|
|
679
|
+
<TabsList variant="line">
|
|
680
|
+
<TabsTrigger value="mine" count={4} countLabel="件">
|
|
681
|
+
自分の担当
|
|
682
|
+
</TabsTrigger>
|
|
683
|
+
<TabsTrigger value="all" count={143} countLabel="件">
|
|
684
|
+
すべて
|
|
685
|
+
</TabsTrigger>
|
|
686
|
+
</TabsList>
|
|
687
|
+
</Tabs>
|
|
688
|
+
</Flex>
|
|
689
|
+
</CardContent>
|
|
690
|
+
</Card>
|
|
691
|
+
|
|
649
692
|
<Card>
|
|
650
693
|
<CardHeader>
|
|
651
694
|
<CardTitle level={2}>indicator · animated</CardTitle>
|