@godxjp/ui 28.10.0 → 28.12.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 +2 -2
- package/agent/components/Attachments.json +2 -1
- package/agent/components/ServiceLauncherCard.json +10 -3
- package/agent/components-index.json +1 -1
- package/agent/components.json +12 -4
- package/agent/index.json +3 -3
- package/agent/llms.txt +4 -4
- package/agent/tokens.json +30 -25
- package/dist/components/data-display/service-launcher-card.d.ts +19 -0
- package/dist/components/data-display/service-launcher-card.js +14 -1
- package/dist/components/data-entry/attachments.js +77 -33
- package/dist/components/ui/avatar.d.ts +1 -18
- package/dist/components/ui/avatar.js +1 -36
- package/dist/contracts/measurement.json +1 -1
- package/dist/i18n/messages/en.json +167 -0
- package/dist/i18n/messages/ja.json +167 -0
- package/dist/i18n/messages/vi.json +167 -0
- package/dist/lib/image-loading-status.d.ts +25 -0
- package/dist/lib/image-loading-status.js +41 -0
- package/dist/props/registry.d.ts +5 -1
- package/dist/props/registry.js +12 -1
- package/dist/styles/card-layout.css +6 -0
- package/dist/styles/control.css +2 -2
- package/dist/styles/data-entry-layout.css +245 -2
- package/dist/tokens/components/attachments.css +18 -9
- package/dist/tokens/components/segmented.css +2 -2
- package/docs/DESIGN-AUTHORITY.md +38 -0
- package/docs/assets/service-mark-rose.svg +6 -0
- package/docs/assets/service-mark-teal.svg +5 -0
- package/docs/data-display/service-launcher-card.tsx +232 -92
- package/docs/showcase/table-pagination.tsx +18 -7
- package/package.json +4 -3
|
@@ -19,8 +19,20 @@ import {
|
|
|
19
19
|
ServiceLauncherCardSkeleton,
|
|
20
20
|
} from "@godxjp/ui/data-display";
|
|
21
21
|
import { Button, Text } from "@godxjp/ui/general";
|
|
22
|
+
import { useTranslation } from "@godxjp/ui/i18n";
|
|
22
23
|
import { Flex, PageContainer, ResponsiveGrid } from "@godxjp/ui/layout";
|
|
23
24
|
|
|
25
|
+
/* Committed SVGs, imported so the bundler rewrites each URL against PREVIEW_BASE. A docs page must
|
|
26
|
+
* never fetch a third-party image: offline it cannot render, and on CI the request never settles,
|
|
27
|
+
* `networkidle` never fires and `page.goto` times out. */
|
|
28
|
+
import serviceMarkRose from "../assets/service-mark-rose.svg";
|
|
29
|
+
import serviceMarkTeal from "../assets/service-mark-teal.svg";
|
|
30
|
+
|
|
31
|
+
/* A URL that is GUARANTEED to fail, with no network round-trip to hang on: the bytes are not an
|
|
32
|
+
* image, so the browser's decode fails locally. That is the production case this section exists to
|
|
33
|
+
* show — `logo_path` in the database outlives the file on disk. */
|
|
34
|
+
const BROKEN_LOGO_URL = "data:image/svg+xml,not-an-image";
|
|
35
|
+
|
|
24
36
|
/**
|
|
25
37
|
* ServiceLauncherCard — one tile for one application in an organization's launcher.
|
|
26
38
|
*
|
|
@@ -36,6 +48,10 @@ import { Flex, PageContainer, ResponsiveGrid } from "@godxjp/ui/layout";
|
|
|
36
48
|
* own entitlement contract. There is no `href`, no `available`, no `entitlement` prop to find.
|
|
37
49
|
*
|
|
38
50
|
* ResponsiveGrid owns the 3 → 2 → 1 ladder. The page writes no grid tracks and no page-local CSS.
|
|
51
|
+
*
|
|
52
|
+
* All copy is localized through useTranslation() — see docs/showcase/table-pagination.tsx for the
|
|
53
|
+
* pattern this follows. `metadata` (hostnames, version strings, pixel dimensions) is domain DATA
|
|
54
|
+
* and stays literal; it is what the gate does not scan and what localizing would be wrong for.
|
|
39
55
|
*/
|
|
40
56
|
|
|
41
57
|
/** A section heading. Headings are headings, not Cards — a Card here would nest borders. */
|
|
@@ -62,240 +78,364 @@ function Section({
|
|
|
62
78
|
}
|
|
63
79
|
|
|
64
80
|
export default function Demo() {
|
|
81
|
+
const { t } = useTranslation();
|
|
82
|
+
|
|
83
|
+
// Status-tone labels are consumer copy, not the component's — shared across the tiles that
|
|
84
|
+
// reuse the same real-world status (e.g. "stopped" appears on both the data-sync and analytics
|
|
85
|
+
// tiles). `attentionRequired` / `openServiceEnglish` stay identical across locales on purpose:
|
|
86
|
+
// section 5's third tile is deliberately an English-named service in a JP admin portal.
|
|
87
|
+
const status = {
|
|
88
|
+
available: t("serviceLauncherShowcase.status.available"),
|
|
89
|
+
active: t("serviceLauncherShowcase.status.active"),
|
|
90
|
+
maintenance: t("serviceLauncherShowcase.status.maintenance"),
|
|
91
|
+
stopped: t("serviceLauncherShowcase.status.stopped"),
|
|
92
|
+
adminOnly: t("serviceLauncherShowcase.status.adminOnly"),
|
|
93
|
+
preparing: t("serviceLauncherShowcase.status.preparing"),
|
|
94
|
+
archived: t("serviceLauncherShowcase.status.archived"),
|
|
95
|
+
unapplied: t("serviceLauncherShowcase.status.unapplied"),
|
|
96
|
+
noPermission: t("serviceLauncherShowcase.status.noPermission"),
|
|
97
|
+
attentionRequired: t("serviceLauncherShowcase.status.attentionRequired"),
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const action = {
|
|
101
|
+
openService: t("serviceLauncherShowcase.action.openService"),
|
|
102
|
+
open: t("serviceLauncherShowcase.action.open"),
|
|
103
|
+
viewStatus: t("serviceLauncherShowcase.action.viewStatus"),
|
|
104
|
+
viewHistory: t("serviceLauncherShowcase.action.viewHistory"),
|
|
105
|
+
checkPermissions: t("serviceLauncherShowcase.action.checkPermissions"),
|
|
106
|
+
openSettings: t("serviceLauncherShowcase.action.openSettings"),
|
|
107
|
+
viewArchive: t("serviceLauncherShowcase.action.viewArchive"),
|
|
108
|
+
openRequestForm: t("serviceLauncherShowcase.action.openRequestForm"),
|
|
109
|
+
openList: t("serviceLauncherShowcase.action.openList"),
|
|
110
|
+
openServiceEnglish: t("serviceLauncherShowcase.action.openServiceEnglish"),
|
|
111
|
+
};
|
|
112
|
+
|
|
65
113
|
return (
|
|
66
114
|
<PageContainer
|
|
67
|
-
title="
|
|
68
|
-
subtitle="
|
|
115
|
+
title={t("serviceLauncherShowcase.page.title")}
|
|
116
|
+
subtitle={t("serviceLauncherShowcase.page.subtitle")}
|
|
69
117
|
>
|
|
70
118
|
<Flex direction="col" gap="lg">
|
|
71
119
|
<Section
|
|
72
|
-
title="
|
|
73
|
-
why="
|
|
120
|
+
title={t("serviceLauncherShowcase.sections.basics.heading")}
|
|
121
|
+
why={t("serviceLauncherShowcase.sections.basics.why")}
|
|
74
122
|
>
|
|
75
123
|
<ResponsiveGrid columns={{ sm: 1, md: 2, lg: 3 }}>
|
|
76
124
|
<ServiceLauncherCard
|
|
77
125
|
icon={Clock3}
|
|
78
|
-
title="
|
|
79
|
-
statusLabel=
|
|
126
|
+
title={t("serviceLauncherShowcase.sections.basics.attendance.title")}
|
|
127
|
+
statusLabel={status.available}
|
|
80
128
|
statusTone="success"
|
|
81
|
-
description="
|
|
129
|
+
description={t("serviceLauncherShowcase.sections.basics.attendance.description")}
|
|
82
130
|
metadata="attend.corp.example.jp · v4.2"
|
|
83
|
-
action={<Button
|
|
131
|
+
action={<Button>{action.openService}</Button>}
|
|
84
132
|
/>
|
|
85
133
|
<ServiceLauncherCard
|
|
86
134
|
icon={ReceiptText}
|
|
87
|
-
title="
|
|
88
|
-
statusLabel=
|
|
135
|
+
title={t("serviceLauncherShowcase.sections.basics.expense.title")}
|
|
136
|
+
statusLabel={status.available}
|
|
89
137
|
statusTone="success"
|
|
90
|
-
description="
|
|
138
|
+
description={t("serviceLauncherShowcase.sections.basics.expense.description")}
|
|
91
139
|
metadata="keihi.corp.example.jp · v2.8"
|
|
92
|
-
action={<Button
|
|
140
|
+
action={<Button>{action.openService}</Button>}
|
|
93
141
|
/>
|
|
94
142
|
<ServiceLauncherCard
|
|
95
143
|
icon={Calendar}
|
|
96
|
-
title="
|
|
97
|
-
statusLabel=
|
|
144
|
+
title={t("serviceLauncherShowcase.sections.basics.meetingRoom.title")}
|
|
145
|
+
statusLabel={status.available}
|
|
98
146
|
statusTone="success"
|
|
99
|
-
description="
|
|
147
|
+
description={t("serviceLauncherShowcase.sections.basics.meetingRoom.description")}
|
|
100
148
|
metadata="rooms.corp.example.jp · v1.9"
|
|
101
|
-
action={<Button
|
|
149
|
+
action={<Button>{action.openService}</Button>}
|
|
102
150
|
/>
|
|
103
151
|
</ResponsiveGrid>
|
|
104
152
|
</Section>
|
|
105
153
|
|
|
106
154
|
<Section
|
|
107
|
-
title="
|
|
108
|
-
why="
|
|
155
|
+
title={t("serviceLauncherShowcase.sections.statusTones.heading")}
|
|
156
|
+
why={t("serviceLauncherShowcase.sections.statusTones.why")}
|
|
109
157
|
>
|
|
110
158
|
<ResponsiveGrid columns={{ sm: 1, md: 2, lg: 3 }}>
|
|
111
159
|
<ServiceLauncherCard
|
|
112
160
|
icon={Mail}
|
|
113
161
|
titleLevel={3}
|
|
114
|
-
title="
|
|
115
|
-
statusLabel=
|
|
162
|
+
title={t("serviceLauncherShowcase.sections.statusTones.mail.title")}
|
|
163
|
+
statusLabel={status.active}
|
|
116
164
|
statusTone="success"
|
|
117
|
-
description="
|
|
165
|
+
description={t("serviceLauncherShowcase.sections.statusTones.mail.description")}
|
|
118
166
|
metadata="mail.corp.example.jp"
|
|
119
|
-
action={<Button
|
|
167
|
+
action={<Button>{action.openService}</Button>}
|
|
120
168
|
/>
|
|
121
169
|
<ServiceLauncherCard
|
|
122
170
|
icon={Server}
|
|
123
171
|
titleLevel={3}
|
|
124
|
-
title="
|
|
125
|
-
statusLabel=
|
|
172
|
+
title={t("serviceLauncherShowcase.sections.statusTones.fileShare.title")}
|
|
173
|
+
statusLabel={status.maintenance}
|
|
126
174
|
statusTone="warning"
|
|
127
|
-
description="
|
|
175
|
+
description={t("serviceLauncherShowcase.sections.statusTones.fileShare.description")}
|
|
128
176
|
metadata="files.corp.example.jp"
|
|
129
|
-
action={<Button variant="outline"
|
|
177
|
+
action={<Button variant="outline">{action.viewStatus}</Button>}
|
|
130
178
|
/>
|
|
131
179
|
<ServiceLauncherCard
|
|
132
180
|
icon={Database}
|
|
133
181
|
titleLevel={3}
|
|
134
|
-
title="
|
|
135
|
-
statusLabel=
|
|
182
|
+
title={t("serviceLauncherShowcase.sections.statusTones.dataSync.title")}
|
|
183
|
+
statusLabel={status.stopped}
|
|
136
184
|
statusTone="destructive"
|
|
137
|
-
description="
|
|
185
|
+
description={t("serviceLauncherShowcase.sections.statusTones.dataSync.description")}
|
|
138
186
|
metadata="sync.corp.example.jp"
|
|
139
|
-
action={<Button variant="outline"
|
|
187
|
+
action={<Button variant="outline">{action.viewHistory}</Button>}
|
|
140
188
|
/>
|
|
141
189
|
<ServiceLauncherCard
|
|
142
190
|
icon={ShieldCheck}
|
|
143
191
|
titleLevel={3}
|
|
144
|
-
title="
|
|
145
|
-
statusLabel=
|
|
192
|
+
title={t("serviceLauncherShowcase.sections.statusTones.iam.title")}
|
|
193
|
+
statusLabel={status.adminOnly}
|
|
146
194
|
statusTone="info"
|
|
147
|
-
description="
|
|
195
|
+
description={t("serviceLauncherShowcase.sections.statusTones.iam.description")}
|
|
148
196
|
metadata="iam.corp.example.jp"
|
|
149
|
-
action={<Button variant="outline"
|
|
197
|
+
action={<Button variant="outline">{action.checkPermissions}</Button>}
|
|
150
198
|
/>
|
|
151
199
|
<ServiceLauncherCard
|
|
152
200
|
icon={PlugZap}
|
|
153
201
|
titleLevel={3}
|
|
154
|
-
title="
|
|
155
|
-
statusLabel=
|
|
202
|
+
title={t("serviceLauncherShowcase.sections.statusTones.integrations.title")}
|
|
203
|
+
statusLabel={status.preparing}
|
|
156
204
|
statusTone="neutral"
|
|
157
|
-
description=
|
|
205
|
+
description={t(
|
|
206
|
+
"serviceLauncherShowcase.sections.statusTones.integrations.description",
|
|
207
|
+
)}
|
|
158
208
|
metadata="connect.corp.example.jp"
|
|
159
|
-
action={<Button variant="outline"
|
|
209
|
+
action={<Button variant="outline">{action.openSettings}</Button>}
|
|
160
210
|
/>
|
|
161
211
|
<ServiceLauncherCard
|
|
162
212
|
icon={BookOpen}
|
|
163
213
|
titleLevel={3}
|
|
164
|
-
title="
|
|
165
|
-
statusLabel=
|
|
214
|
+
title={t("serviceLauncherShowcase.sections.statusTones.legacyKb.title")}
|
|
215
|
+
statusLabel={status.archived}
|
|
166
216
|
statusTone="muted"
|
|
167
|
-
description="
|
|
217
|
+
description={t("serviceLauncherShowcase.sections.statusTones.legacyKb.description")}
|
|
168
218
|
metadata="kb-archive.corp.example.jp"
|
|
169
|
-
action={<Button variant="outline"
|
|
219
|
+
action={<Button variant="outline">{action.viewArchive}</Button>}
|
|
170
220
|
/>
|
|
171
221
|
</ResponsiveGrid>
|
|
172
222
|
</Section>
|
|
173
223
|
|
|
174
224
|
<Section
|
|
175
|
-
title="
|
|
176
|
-
why="
|
|
225
|
+
title={t("serviceLauncherShowcase.sections.disabledReason.heading")}
|
|
226
|
+
why={t("serviceLauncherShowcase.sections.disabledReason.why")}
|
|
177
227
|
>
|
|
178
228
|
<ResponsiveGrid columns={{ sm: 1, md: 2, lg: 3 }}>
|
|
179
229
|
<ServiceLauncherCard
|
|
180
230
|
icon={Boxes}
|
|
181
231
|
titleLevel={3}
|
|
182
|
-
title="
|
|
183
|
-
statusLabel=
|
|
232
|
+
title={t("serviceLauncherShowcase.sections.disabledReason.inventory.title")}
|
|
233
|
+
statusLabel={status.unapplied}
|
|
184
234
|
statusTone="warning"
|
|
185
|
-
description=
|
|
235
|
+
description={t(
|
|
236
|
+
"serviceLauncherShowcase.sections.disabledReason.inventory.description",
|
|
237
|
+
)}
|
|
186
238
|
metadata="zaiko.corp.example.jp"
|
|
187
|
-
disabledReason="
|
|
188
|
-
action={<Button disabled
|
|
239
|
+
disabledReason={t("serviceLauncherShowcase.sections.disabledReason.inventory.reason")}
|
|
240
|
+
action={<Button disabled>{action.openService}</Button>}
|
|
189
241
|
/>
|
|
190
242
|
<ServiceLauncherCard
|
|
191
243
|
icon={FileText}
|
|
192
244
|
titleLevel={3}
|
|
193
|
-
title="
|
|
194
|
-
statusLabel=
|
|
245
|
+
title={t("serviceLauncherShowcase.sections.disabledReason.contracts.title")}
|
|
246
|
+
statusLabel={status.noPermission}
|
|
195
247
|
statusTone="info"
|
|
196
|
-
description=
|
|
248
|
+
description={t(
|
|
249
|
+
"serviceLauncherShowcase.sections.disabledReason.contracts.description",
|
|
250
|
+
)}
|
|
197
251
|
metadata="keiyaku.corp.example.jp"
|
|
198
|
-
disabledReason="
|
|
199
|
-
action={<Button disabled
|
|
252
|
+
disabledReason={t("serviceLauncherShowcase.sections.disabledReason.contracts.reason")}
|
|
253
|
+
action={<Button disabled>{action.openService}</Button>}
|
|
200
254
|
/>
|
|
201
255
|
<ServiceLauncherCard
|
|
202
256
|
icon={Database}
|
|
203
257
|
titleLevel={3}
|
|
204
|
-
title="
|
|
205
|
-
statusLabel=
|
|
258
|
+
title={t("serviceLauncherShowcase.sections.disabledReason.analytics.title")}
|
|
259
|
+
statusLabel={status.stopped}
|
|
206
260
|
statusTone="destructive"
|
|
207
|
-
description=
|
|
261
|
+
description={t(
|
|
262
|
+
"serviceLauncherShowcase.sections.disabledReason.analytics.description",
|
|
263
|
+
)}
|
|
208
264
|
metadata="bi.corp.example.jp"
|
|
209
|
-
disabledReason="
|
|
210
|
-
action={<Button disabled
|
|
265
|
+
disabledReason={t("serviceLauncherShowcase.sections.disabledReason.analytics.reason")}
|
|
266
|
+
action={<Button disabled>{action.openService}</Button>}
|
|
211
267
|
/>
|
|
212
268
|
</ResponsiveGrid>
|
|
213
269
|
</Section>
|
|
214
270
|
|
|
215
271
|
<Section
|
|
216
|
-
title="
|
|
217
|
-
why="
|
|
272
|
+
title={t("serviceLauncherShowcase.sections.loadingCatalog.heading")}
|
|
273
|
+
why={t("serviceLauncherShowcase.sections.loadingCatalog.why")}
|
|
218
274
|
>
|
|
219
275
|
<ResponsiveGrid columns={{ sm: 1, md: 2, lg: 3 }}>
|
|
220
|
-
<ServiceLauncherCardSkeleton
|
|
276
|
+
<ServiceLauncherCardSkeleton
|
|
277
|
+
label={t("serviceLauncherShowcase.sections.loadingCatalog.skeletonLabel")}
|
|
278
|
+
/>
|
|
221
279
|
<ServiceCatalogCta
|
|
222
|
-
title="
|
|
223
|
-
action={<Button variant="outline"
|
|
280
|
+
title={t("serviceLauncherShowcase.sections.loadingCatalog.addApp.title")}
|
|
281
|
+
action={<Button variant="outline">{action.openRequestForm}</Button>}
|
|
224
282
|
/>
|
|
225
283
|
<ServiceCatalogCta
|
|
226
284
|
icon={LayoutGrid}
|
|
227
|
-
title="
|
|
228
|
-
action={<Button variant="ghost"
|
|
285
|
+
title={t("serviceLauncherShowcase.sections.loadingCatalog.allApps.title")}
|
|
286
|
+
action={<Button variant="ghost">{action.openList}</Button>}
|
|
229
287
|
/>
|
|
230
288
|
</ResponsiveGrid>
|
|
231
289
|
</Section>
|
|
232
290
|
|
|
233
291
|
<Section
|
|
234
|
-
title="
|
|
235
|
-
why="
|
|
292
|
+
title={t("serviceLauncherShowcase.sections.edgeCases.heading")}
|
|
293
|
+
why={t("serviceLauncherShowcase.sections.edgeCases.why")}
|
|
236
294
|
>
|
|
237
295
|
<ResponsiveGrid columns={{ sm: 1, md: 2, lg: 3 }}>
|
|
238
296
|
<ServiceLauncherCard
|
|
239
297
|
icon={ShieldCheck}
|
|
240
298
|
titleLevel={3}
|
|
241
|
-
title="
|
|
242
|
-
statusLabel=
|
|
299
|
+
title={t("serviceLauncherShowcase.sections.edgeCases.hrPortal.title")}
|
|
300
|
+
statusLabel={status.available}
|
|
243
301
|
statusTone="success"
|
|
244
|
-
description="
|
|
302
|
+
description={t("serviceLauncherShowcase.sections.edgeCases.hrPortal.description")}
|
|
245
303
|
metadata="workforce-identity-administration.ap-northeast-1.corp.example.jp · v11.0"
|
|
246
|
-
action={<Button
|
|
304
|
+
action={<Button>{action.openService}</Button>}
|
|
247
305
|
/>
|
|
248
306
|
<ServiceLauncherCard
|
|
249
307
|
icon={Clock3}
|
|
250
308
|
titleLevel={3}
|
|
251
|
-
title="
|
|
252
|
-
statusLabel=
|
|
309
|
+
title={t("serviceLauncherShowcase.sections.edgeCases.dailyReport.title")}
|
|
310
|
+
statusLabel={status.available}
|
|
253
311
|
statusTone="success"
|
|
254
312
|
metadata="nippo.corp.example.jp"
|
|
255
|
-
action={<Button
|
|
313
|
+
action={<Button>{action.openService}</Button>}
|
|
256
314
|
/>
|
|
257
315
|
<ServiceLauncherCard
|
|
258
316
|
icon={Server}
|
|
259
317
|
titleLevel={3}
|
|
260
|
-
title="
|
|
261
|
-
statusLabel=
|
|
318
|
+
title={t("serviceLauncherShowcase.sections.edgeCases.warningConsole.title")}
|
|
319
|
+
statusLabel={status.attentionRequired}
|
|
262
320
|
statusTone="warning"
|
|
263
|
-
description=
|
|
321
|
+
description={t(
|
|
322
|
+
"serviceLauncherShowcase.sections.edgeCases.warningConsole.description",
|
|
323
|
+
)}
|
|
264
324
|
metadata="workforce-identity-administration.ap-southeast-1.corp.example.com"
|
|
265
|
-
disabledReason="
|
|
266
|
-
action={<Button disabled>
|
|
325
|
+
disabledReason={t("serviceLauncherShowcase.sections.edgeCases.warningConsole.reason")}
|
|
326
|
+
action={<Button disabled>{action.openServiceEnglish}</Button>}
|
|
267
327
|
/>
|
|
268
328
|
</ResponsiveGrid>
|
|
269
329
|
</Section>
|
|
270
330
|
|
|
271
331
|
<Section
|
|
272
|
-
title="
|
|
273
|
-
why="
|
|
332
|
+
title={t("serviceLauncherShowcase.sections.minimalTiles.heading")}
|
|
333
|
+
why={t("serviceLauncherShowcase.sections.minimalTiles.why")}
|
|
274
334
|
>
|
|
275
335
|
<ResponsiveGrid columns={{ sm: 1, md: 2, lg: 3 }}>
|
|
276
336
|
<ServiceLauncherCard
|
|
277
337
|
icon={BookOpen}
|
|
278
338
|
titleLevel={3}
|
|
279
|
-
title="
|
|
280
|
-
action={<Button variant="outline"
|
|
339
|
+
title={t("serviceLauncherShowcase.sections.minimalTiles.wiki.title")}
|
|
340
|
+
action={<Button variant="outline">{action.open}</Button>}
|
|
281
341
|
/>
|
|
282
342
|
<ServiceLauncherCard
|
|
283
343
|
icon={Mail}
|
|
284
344
|
titleLevel={3}
|
|
285
|
-
title="
|
|
286
|
-
description="
|
|
287
|
-
action={<Button variant="outline"
|
|
345
|
+
title={t("serviceLauncherShowcase.sections.minimalTiles.contact.title")}
|
|
346
|
+
description={t("serviceLauncherShowcase.sections.minimalTiles.contact.description")}
|
|
347
|
+
action={<Button variant="outline">{action.open}</Button>}
|
|
288
348
|
/>
|
|
289
349
|
<ServiceLauncherCard
|
|
290
350
|
icon={Calendar}
|
|
291
351
|
titleLevel={3}
|
|
292
|
-
title="
|
|
293
|
-
statusLabel=
|
|
352
|
+
title={t("serviceLauncherShowcase.sections.minimalTiles.calendar.title")}
|
|
353
|
+
statusLabel={status.available}
|
|
294
354
|
statusTone="success"
|
|
295
|
-
description="
|
|
355
|
+
description={t("serviceLauncherShowcase.sections.minimalTiles.calendar.description")}
|
|
296
356
|
metadata="calendar.corp.example.jp · v3.1"
|
|
297
|
-
disabledReason="
|
|
298
|
-
action={<Button variant="outline"
|
|
357
|
+
disabledReason={t("serviceLauncherShowcase.sections.minimalTiles.calendar.reason")}
|
|
358
|
+
action={<Button variant="outline">{action.open}</Button>}
|
|
359
|
+
/>
|
|
360
|
+
</ResponsiveGrid>
|
|
361
|
+
</Section>
|
|
362
|
+
|
|
363
|
+
<Section
|
|
364
|
+
title={t("serviceLauncherShowcase.sections.logo.heading")}
|
|
365
|
+
why={t("serviceLauncherShowcase.sections.logo.why")}
|
|
366
|
+
>
|
|
367
|
+
<ResponsiveGrid columns={{ sm: 1, md: 2, lg: 3 }}>
|
|
368
|
+
{/* 1 · a real uploaded mark, square */}
|
|
369
|
+
<ServiceLauncherCard
|
|
370
|
+
icon={Clock3}
|
|
371
|
+
logo={serviceMarkTeal}
|
|
372
|
+
titleLevel={3}
|
|
373
|
+
title={t("serviceLauncherShowcase.sections.logo.uploaded.title")}
|
|
374
|
+
statusLabel={status.available}
|
|
375
|
+
statusTone="success"
|
|
376
|
+
description={t("serviceLauncherShowcase.sections.logo.uploaded.description")}
|
|
377
|
+
metadata="attend.corp.example.jp · v4.2"
|
|
378
|
+
action={<Button>{action.openService}</Button>}
|
|
379
|
+
/>
|
|
380
|
+
{/* 2 · the SAME tile with no upload yet — the fallback, side by side */}
|
|
381
|
+
<ServiceLauncherCard
|
|
382
|
+
icon={Clock3}
|
|
383
|
+
titleLevel={3}
|
|
384
|
+
title={t("serviceLauncherShowcase.sections.logo.missing.title")}
|
|
385
|
+
statusLabel={status.available}
|
|
386
|
+
statusTone="success"
|
|
387
|
+
description={t("serviceLauncherShowcase.sections.logo.missing.description")}
|
|
388
|
+
metadata="attend.corp.example.jp · v4.2"
|
|
389
|
+
action={<Button>{action.openService}</Button>}
|
|
390
|
+
/>
|
|
391
|
+
{/* 3 · the URL is set but the file is gone — the state that reaches production */}
|
|
392
|
+
<ServiceLauncherCard
|
|
393
|
+
icon={Database}
|
|
394
|
+
logo={BROKEN_LOGO_URL}
|
|
395
|
+
titleLevel={3}
|
|
396
|
+
title={t("serviceLauncherShowcase.sections.logo.broken.title")}
|
|
397
|
+
statusLabel={status.available}
|
|
398
|
+
statusTone="success"
|
|
399
|
+
description={t("serviceLauncherShowcase.sections.logo.broken.description")}
|
|
400
|
+
metadata="sync.corp.example.jp"
|
|
401
|
+
action={<Button>{action.openService}</Button>}
|
|
402
|
+
/>
|
|
403
|
+
{/* 4 · a WIDE wordmark — contain letterboxes it, never crops it */}
|
|
404
|
+
<ServiceLauncherCard
|
|
405
|
+
icon={ReceiptText}
|
|
406
|
+
logo={serviceMarkRose}
|
|
407
|
+
titleLevel={3}
|
|
408
|
+
title={t("serviceLauncherShowcase.sections.logo.wideMark.title")}
|
|
409
|
+
statusLabel={status.available}
|
|
410
|
+
statusTone="success"
|
|
411
|
+
description={t("serviceLauncherShowcase.sections.logo.wideMark.description")}
|
|
412
|
+
metadata="keihi.corp.example.jp · v2.8"
|
|
413
|
+
action={<Button>{action.openService}</Button>}
|
|
414
|
+
/>
|
|
415
|
+
{/* 5 · logo + disabledReason — the medallion mutes, the mark stays the mark */}
|
|
416
|
+
<ServiceLauncherCard
|
|
417
|
+
icon={ShieldCheck}
|
|
418
|
+
logo={serviceMarkTeal}
|
|
419
|
+
titleLevel={3}
|
|
420
|
+
title={t("serviceLauncherShowcase.sections.logo.withReason.title")}
|
|
421
|
+
statusLabel={status.noPermission}
|
|
422
|
+
statusTone="info"
|
|
423
|
+
description={t("serviceLauncherShowcase.sections.logo.withReason.description")}
|
|
424
|
+
metadata="iam.corp.example.jp"
|
|
425
|
+
disabledReason={t("serviceLauncherShowcase.sections.logo.withReason.reason")}
|
|
426
|
+
action={<Button disabled>{action.openService}</Button>}
|
|
427
|
+
/>
|
|
428
|
+
{/* 6 · logo="" — an empty projection value is the same as no logo */}
|
|
429
|
+
<ServiceLauncherCard
|
|
430
|
+
icon={Mail}
|
|
431
|
+
logo=""
|
|
432
|
+
titleLevel={3}
|
|
433
|
+
title={t("serviceLauncherShowcase.sections.logo.emptyString.title")}
|
|
434
|
+
statusLabel={status.active}
|
|
435
|
+
statusTone="success"
|
|
436
|
+
description={t("serviceLauncherShowcase.sections.logo.emptyString.description")}
|
|
437
|
+
metadata="mail.corp.example.jp"
|
|
438
|
+
action={<Button>{action.openService}</Button>}
|
|
299
439
|
/>
|
|
300
440
|
</ResponsiveGrid>
|
|
301
441
|
</Section>
|
|
@@ -334,15 +334,26 @@ function CursorPeriodCard() {
|
|
|
334
334
|
<CardContent flush>
|
|
335
335
|
<DataTable data={rows} columns={columns} getRowId={(row) => row.id} density="compact" />
|
|
336
336
|
</CardContent>
|
|
337
|
-
{/* `DataTable.Pagination` owns its own
|
|
338
|
-
* of a FLUSH container. Here it shares a padded `CardContent` with the period label,
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
337
|
+
{/* `DataTable.Pagination` owns its own insets ON BOTH AXES, because it is normally the lone
|
|
338
|
+
* child of a FLUSH container. Here it shares a padded `CardContent` with the period label,
|
|
339
|
+
* so both stack.
|
|
340
|
+
*
|
|
341
|
+
* The first pass at this zeroed only the INLINE knob and declared it done — a two-axis
|
|
342
|
+
* defect fixed on one axis, which looks fixed from the side you were measuring. The block
|
|
343
|
+
* one kept stacking: 16px from the CardContent plus 7.36px of the slot's own, so this
|
|
344
|
+
* footer sat 27px off the last row while the other two cards sat at 20px.
|
|
345
|
+
*
|
|
346
|
+
* Zeroing both hands the insets to the container that already supplies them; that is what
|
|
347
|
+
* these knobs are for, and an instance override is the right tier for one element in one
|
|
348
|
+
* arrangement (docs/CUSTOMER-THEMING.md, tier 4). */}
|
|
343
349
|
<CardContent
|
|
344
350
|
className="border-t"
|
|
345
|
-
style={
|
|
351
|
+
style={
|
|
352
|
+
{
|
|
353
|
+
"--table-pagination-padding-x": "0",
|
|
354
|
+
"--table-pagination-padding-y": "0",
|
|
355
|
+
} as React.CSSProperties
|
|
356
|
+
}
|
|
346
357
|
>
|
|
347
358
|
<Flex direction="row" align="center" justify="between" wrap gap="sm">
|
|
348
359
|
<Text size="xs" tone="muted" tabular>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@godxjp/ui",
|
|
3
|
-
"version": "28.
|
|
4
|
-
"godxUiMcp": "28.
|
|
3
|
+
"version": "28.12.0",
|
|
4
|
+
"godxUiMcp": "28.12.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -414,7 +414,8 @@
|
|
|
414
414
|
"verify": "pnpm typecheck && pnpm lint && pnpm format && pnpm build && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:token-width-wins && pnpm check:no-external-assets && pnpm check:token-scale-bypass && pnpm check:radix-surface && pnpm check:dist-tokens-resolve && pnpm check:no-hardcoded-geometry && pnpm check:no-hardcoded-css-values && pnpm check:disclosure-duplication && pnpm check:no-inline-magic-numbers && pnpm check:no-tailwind-class-assertions && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-lockstep && pnpm check:mcp-sync && pnpm check:doc-prop-existence && pnpm check:mcp-catalog-coverage && pnpm check:mcp-orphans && pnpm check:mcp-pattern-imports && pnpm check:audit-sync && pnpm check:frame-coverage && pnpm test",
|
|
415
415
|
"verify:browser": "pnpm check:contrast && pnpm check:text-ink-clip && pnpm check:frame-overflow && pnpm check:font-fallback-metrics && pnpm check:visual-audit",
|
|
416
416
|
"verify:ci": "pnpm verify:ci:static && pnpm check:frame-contracts && pnpm test",
|
|
417
|
-
"verify:ci:static": "pnpm build && pnpm check:packed-public-contract && pnpm typecheck && pnpm typecheck:docs && pnpm lint && pnpm preview:build && pnpm check:registry && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:use-client && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:token-width-wins && pnpm check:no-external-assets && pnpm check:token-scale-bypass && pnpm check:no-antd-runtime && pnpm check:radix-surface && pnpm check:dist-tokens-resolve && pnpm check:no-hardcoded-geometry && pnpm check:no-hardcoded-css-values && pnpm check:disclosure-duplication && pnpm check:no-inline-magic-numbers && pnpm check:no-tailwind-class-assertions && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-lockstep && pnpm check:measurement-contract && pnpm check:mcp-token-sync && pnpm check:email-token-sync && pnpm check:mcp-sync && pnpm check:doc-prop-existence && pnpm check:mcp-catalog-coverage && pnpm check:mcp-orphans && pnpm check:mcp-catalog-completeness && pnpm check:mcp-pattern-imports && pnpm check:audit-sync && pnpm run audit && pnpm check:frame-coverage-report && pnpm check:gate-coverage && pnpm check:mcp-prop-sync && pnpm check:catalog-contradictions && pnpm check:catalog-snippets && pnpm check:absorbed-names && pnpm check:agent-catalog",
|
|
417
|
+
"verify:ci:static:gates": "pnpm build && pnpm check:packed-public-contract && pnpm typecheck && pnpm typecheck:docs && pnpm lint && pnpm preview:build && pnpm check:registry && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:use-client && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:token-width-wins && pnpm check:no-external-assets && pnpm check:token-scale-bypass && pnpm check:no-antd-runtime && pnpm check:radix-surface && pnpm check:dist-tokens-resolve && pnpm check:no-hardcoded-geometry && pnpm check:no-hardcoded-css-values && pnpm check:disclosure-duplication && pnpm check:no-inline-magic-numbers && pnpm check:no-tailwind-class-assertions && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-lockstep && pnpm check:measurement-contract && pnpm check:mcp-token-sync && pnpm check:email-token-sync && pnpm check:mcp-sync && pnpm check:doc-prop-existence && pnpm check:mcp-catalog-coverage && pnpm check:mcp-orphans && pnpm check:mcp-catalog-completeness && pnpm check:mcp-pattern-imports && pnpm check:audit-sync && pnpm run audit && pnpm check:frame-coverage-report && pnpm check:gate-coverage && pnpm check:mcp-prop-sync && pnpm check:catalog-contradictions && pnpm check:catalog-snippets && pnpm check:absorbed-names && pnpm check:agent-catalog",
|
|
418
|
+
"verify:ci:static": "node scripts/run-gate-list.mjs verify:ci:static:gates",
|
|
418
419
|
"verify:publish-tree": "pnpm build && pnpm check:packed-public-contract && pnpm check:use-client && pnpm check:dist-tokens-resolve",
|
|
419
420
|
"verify:release": "pnpm verify:static && pnpm check:frame-contracts && pnpm check:frame-coverage",
|
|
420
421
|
"verify:static": "pnpm build && pnpm check:packed-public-contract && pnpm typecheck && pnpm typecheck:docs && pnpm lint && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:use-client && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:token-scale-bypass && pnpm check:radix-surface && pnpm check:dist-tokens-resolve && pnpm check:no-hardcoded-geometry && pnpm check:no-hardcoded-css-values && pnpm check:disclosure-duplication && pnpm check:no-inline-magic-numbers && pnpm check:no-tailwind-class-assertions && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-lockstep && pnpm check:mcp-sync && pnpm check:doc-prop-existence && pnpm check:mcp-catalog-coverage && pnpm check:mcp-orphans && pnpm check:mcp-pattern-imports && pnpm check:audit-sync && pnpm check:mcp-prop-sync && pnpm check:contrast && pnpm check:visual-audit && pnpm test",
|