@cyberskill/design 1.2.0 → 1.3.9
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 +11 -9
- package/README.md +28 -24
- package/SKILL.md +18 -9
- package/THIRD-PARTY-NOTICES.md +35 -0
- package/VERSION +1 -1
- package/_ds_bundle.js +701 -1342
- package/_esm/cs.mjs +2 -2
- package/_esm/react.mjs +6 -1
- package/_vendor/NOTICE.md +16 -0
- package/_vendor/babel/README.md +7 -0
- package/_vendor/babel/babel.min.js +4 -0
- package/_vendor/react/README.md +3 -0
- package/_vendor/react/react-dom.production.min.js +1 -0
- package/_vendor/react/react.production.min.js +1 -0
- package/assets/aurora-hoa.webp +0 -0
- package/assets/aurora-kim.webp +0 -0
- package/assets/aurora-moc.webp +0 -0
- package/assets/aurora-tho.webp +0 -0
- package/assets/aurora-thuy.webp +0 -0
- package/base/ai.css +8 -3
- package/base/collections.css +10 -4
- package/base/components.css +5 -2
- package/base/controls.css +58 -21
- package/base/data.css +1 -1
- package/base/feedback.css +9 -2
- package/base/forms.css +1 -1
- package/base/glass.css +1 -1
- package/base/interaction.css +6 -2
- package/base/navigation.css +1 -1
- package/base/reset.css +7 -1
- package/base/responsive.css +13 -12
- package/base/shell.css +8 -2
- package/components/_i18n/i18n.js +28 -3
- package/components/_i18n/strings.js +42 -24
- package/components/ai/ChatMessage.d.ts +2 -0
- package/components/ai/ChatMessage.jsx +8 -4
- package/components/ai/ConfidenceMeter.d.ts +2 -0
- package/components/ai/HumanReviewGate.d.ts +2 -0
- package/components/ai/PromptInput.d.ts +2 -0
- package/components/ai/TypingIndicator.d.ts +2 -0
- package/components/ai/ai-conversation.card.html +3 -3
- package/components/ai/ai-lumi.card.html +3 -3
- package/components/ai/ai.card.html +3 -3
- package/components/brand/brand.card.html +3 -3
- package/components/button/buttons.card.html +3 -3
- package/components/data/Image.jsx +18 -2
- package/components/data/Sortable.d.ts +5 -1
- package/components/data/Sortable.jsx +42 -9
- package/components/data/Sortable.prompt.md +4 -2
- package/components/data/Terminal.jsx +3 -2
- package/components/data/Tooltip.d.ts +2 -0
- package/components/data/Tooltip.jsx +6 -3
- package/components/data/Tree.d.ts +2 -1
- package/components/data/Tree.jsx +137 -16
- package/components/data/Tree.prompt.md +1 -1
- package/components/data/collections.card.html +3 -3
- package/components/data/data.card.html +3 -3
- package/components/datatable/DataTable.d.ts +24 -1
- package/components/datatable/DataTable.jsx +78 -5
- package/components/datatable/DataTable.prompt.md +2 -1
- package/components/datatable/datatable.card.html +20 -16
- package/components/dialog/dialog.card.html +3 -3
- package/components/feedback/Alert.d.ts +2 -0
- package/components/feedback/Alert.jsx +8 -2
- package/components/feedback/EmptyState.d.ts +2 -0
- package/components/feedback/EmptyState.jsx +6 -3
- package/components/feedback/ProgressBar.d.ts +2 -0
- package/components/feedback/ProgressBar.jsx +6 -3
- package/components/feedback/Toast.jsx +15 -1
- package/components/feedback/Toast.prompt.md +2 -1
- package/components/feedback/feedback-2.card.html +3 -3
- package/components/feedback/feedback.card.html +3 -3
- package/components/forms/Cascader.jsx +7 -2
- package/components/forms/FileUpload.d.ts +2 -0
- package/components/forms/Form.d.ts +3 -1
- package/components/forms/Form.jsx +9 -1
- package/components/forms/Form.prompt.md +1 -1
- package/components/forms/Mentions.d.ts +1 -1
- package/components/forms/Mentions.jsx +59 -7
- package/components/forms/Mentions.prompt.md +3 -1
- package/components/forms/Rating.d.ts +3 -2
- package/components/forms/Rating.jsx +34 -3
- package/components/forms/Rating.prompt.md +1 -1
- package/components/forms/Select.d.ts +2 -0
- package/components/forms/Select.jsx +6 -2
- package/components/forms/Slider.d.ts +2 -0
- package/components/forms/Slider.jsx +5 -2
- package/components/forms/Switch.d.ts +2 -0
- package/components/forms/Switch.jsx +7 -9
- package/components/forms/Toggle.d.ts +2 -0
- package/components/forms/Toggle.jsx +14 -2
- package/components/forms/forms-2.card.html +3 -3
- package/components/forms/forms.card.html +3 -3
- package/components/icon/Icon.d.ts +1 -1
- package/components/icon/Icon.prompt.md +1 -1
- package/components/icon/icon.card.html +3 -3
- package/components/logo/logo.card.html +3 -3
- package/components/navigation/CommandPalette.d.ts +2 -0
- package/components/navigation/Menu.d.ts +2 -0
- package/components/navigation/Menu.jsx +60 -6
- package/components/navigation/Steps.d.ts +2 -0
- package/components/navigation/Steps.jsx +6 -3
- package/components/navigation/Tabs.d.ts +2 -0
- package/components/navigation/Tabs.jsx +6 -3
- package/components/navigation/Toolbar.d.ts +3 -2
- package/components/navigation/Toolbar.jsx +117 -11
- package/components/navigation/Toolbar.prompt.md +1 -1
- package/components/navigation/navigation.card.html +3 -3
- package/components/navigation/shell.card.html +3 -3
- package/components/overlays/ContextMenu.d.ts +2 -0
- package/components/overlays/ContextMenu.jsx +6 -3
- package/components/overlays/Drawer.d.ts +2 -0
- package/components/overlays/alertdialog.card.html +3 -3
- package/components/overlays/overlays.card.html +3 -3
- package/components/textfield/textfield.card.html +3 -3
- package/dist/styles.min.css +312 -64
- package/docs/benchmark-rubric.md +2 -2
- package/docs/ci-cd.md +18 -13
- package/docs/consumer-grant.md +4 -1
- package/docs/consuming.md +16 -12
- package/docs/contrast-report.md +81 -1
- package/docs/conventions.md +18 -5
- package/docs/decisions.md +41 -3
- package/docs/deploy.md +19 -6
- package/docs/design-styles.md +2 -2
- package/docs/doctrine.md +51 -0
- package/docs/figma.md +2 -0
- package/docs/live-hub.md +3 -1
- package/docs/products.md +1 -1
- package/docs/quality-gates.md +24 -12
- package/docs/release-notes.md +1 -1
- package/docs/release-runbook.md +78 -0
- package/docs/storybook.md +3 -3
- package/docs/sync.md +8 -8
- package/docs/template-schema-v2.md +1 -1
- package/docs/vi/benchmark-rubric.md +2 -2
- package/docs/vi/ci-cd.md +17 -14
- package/docs/vi/consumer-grant.md +4 -1
- package/docs/vi/consuming.md +16 -12
- package/docs/vi/contrast-report.md +81 -1
- package/docs/vi/conventions.md +19 -6
- package/docs/vi/decisions.md +40 -3
- package/docs/vi/deploy.md +19 -6
- package/docs/vi/design-styles.md +1 -1
- package/docs/vi/doctrine.md +51 -0
- package/docs/vi/figma.md +2 -0
- package/docs/vi/live-hub.md +3 -1
- package/docs/vi/products.md +1 -1
- package/docs/vi/quality-gates.md +23 -12
- package/docs/vi/release-notes.md +1 -1
- package/docs/vi/release-runbook.md +78 -0
- package/docs/vi/storybook.md +3 -3
- package/docs/vi/sync.md +7 -7
- package/docs/vi/template-schema-v2.md +1 -1
- package/docs/viewer.html +16 -5
- package/fonts/OFL.txt +98 -0
- package/guidelines/atomic-view.html +2 -2
- package/guidelines/brand-imagery.html +1 -1
- package/guidelines/elements-variants.html +5 -5
- package/guidelines/spacing-breakpoints.html +2 -1
- package/guidelines/surfaces-glass.html +1 -1
- package/llms.txt +18 -11
- package/package.json +28 -8
- package/templates/app-shell/AppShell.dc.html +3 -3
- package/templates/app-shell/content-schema.json +7 -0
- package/templates/article/Article.dc.html +3 -3
- package/templates/article/content-schema.json +7 -0
- package/templates/auth/Auth.dc.html +26 -10
- package/templates/auth/content-schema.json +25 -0
- package/templates/dashboard/Dashboard.dc.html +4 -4
- package/templates/dashboard/content-schema.json +7 -0
- package/templates/delivery-change-note/DeliveryChangeNote.dc.html +2 -2
- package/templates/delivery-runbook/DeliveryRunbook.dc.html +2 -2
- package/templates/email-safe/email-announcement.html +2 -2
- package/templates/email-safe/email-dunning.html +2 -2
- package/templates/email-safe/email-investor.html +2 -2
- package/templates/email-safe/email-launch.html +2 -2
- package/templates/email-safe/email-newsletter.html +2 -2
- package/templates/email-safe/email-status.html +2 -2
- package/templates/email-safe/email-transactional.html +2 -2
- package/templates/finance-dunning-email/FinanceDunningEmail.dc.html +2 -2
- package/templates/finance-expense-report/FinanceExpenseReport.dc.html +2 -2
- package/templates/finance-invoice/FinanceInvoice.dc.html +2 -2
- package/templates/finance-quote/FinanceQuote.dc.html +4 -4
- package/templates/hr-interview-kit/HrInterviewKit.dc.html +1 -1
- package/templates/marketing-case-study/MarketingCaseStudy.dc.html +1 -1
- package/templates/marketing-page/MarketingPage.dc.html +3 -3
- package/templates/marketing-page/content-schema.json +1 -0
- package/templates/settings/Settings.dc.html +3 -3
- package/templates/settings/content-schema.json +7 -0
- package/tokens/element-seeds.json +2 -2
- package/tokens/elements.css +193 -19
- package/tokens/native/CSTokens.kt +3 -2
- package/tokens/native/CSTokens.swift +3 -2
- package/tokens/native/cs_tokens.dart +3 -2
- package/tokens/provenance.json +8 -8
- package/tokens/spacing.css +2 -1
- package/tokens/tokens.dtcg.json +19 -14
- package/tokens/tokens.js +16 -15
- package/tokens/tokens.json +15 -14
- package/ui_kits/deck/index.html +1 -1
- package/ui_kits/status-hub/StatusHub.jsx +1 -1
- package/ui_kits/status-hub/login.html +52 -10
- package/ui_kits/status-hub/project.html +1 -1
- package/ui_kits/status-hub/settings.html +1 -1
- package/ui_kits/website/Website.jsx +1 -1
- package/ui_kits/website/careers.html +2 -2
- package/ui_kits/website/chat.html +1 -1
- package/ui_kits/website/site.css +1 -1
- package/ui_kits/website/work.html +2 -2
- package/assets/aurora-hoa.png +0 -0
- package/assets/aurora-kim.png +0 -0
- package/assets/aurora-moc.png +0 -0
- package/assets/aurora-thuy.png +0 -0
- package/docs/decisions/container-query-migration.md +0 -18
- package/docs/decisions/overlay-manager-design.md +0 -101
- package/docs/plans/cyberskill-design-system-audit-and-12-month-evolution-plan.md +0 -1490
- package/docs/status/assets/favicon.svg +0 -5
- package/docs/status/assets/status-legacy.css +0 -399
- package/docs/status/assets/status-legacy.js +0 -505
- package/docs/status/assets/status.css +0 -644
- package/docs/status/assets/status.js +0 -1308
- package/docs/status/data/status-feed.json +0 -1
- package/docs/status/data/task/TASK-REL-001.js +0 -1
- package/docs/status/data/task/TASK-REL-002.js +0 -1
- package/docs/status/index.html +0 -46
- package/docs/status/roadmap.html +0 -4
- package/docs/status/status-legacy.html +0 -122
- package/docs/tasks/BACKLOG.md +0 -26
- package/docs/tasks/_state/commit-links.yaml +0 -14
- package/docs/tasks/release/TASK-REL-001-launch-1-1-0/spec.md +0 -55
- package/docs/tasks/release/TASK-REL-002-republish-1-1-1/spec.md +0 -54
package/tokens/tokens.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// CyberSkill design tokens — generated from tokens/*.css (v1.
|
|
1
|
+
// CyberSkill design tokens — generated from tokens/*.css (v1.3.9). Do not edit by hand.
|
|
2
2
|
export const tokens = {
|
|
3
3
|
"$meta": {
|
|
4
4
|
"system": "CyberSkill Design System",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.3.9",
|
|
6
6
|
"generated": "2026-07-23",
|
|
7
7
|
"note": "Generated from tokens/*.css. Root grouped by category; theme/element scopes carry overrides only. Regenerate after any token change (see docs/conventions.md)."
|
|
8
8
|
},
|
|
@@ -66,7 +66,7 @@ export const tokens = {
|
|
|
66
66
|
"--cs-accent-ink": "#45210E",
|
|
67
67
|
"--cs-accent-glow": "rgba(244, 186, 23, 0.48)",
|
|
68
68
|
"--cs-accent-grad-a": "#F4BA17",
|
|
69
|
-
"--cs-accent-grad-b": "#
|
|
69
|
+
"--cs-accent-grad-b": "#F3B958",
|
|
70
70
|
"--cs-accent-on-strong": "#1A1108"
|
|
71
71
|
},
|
|
72
72
|
"depth": {
|
|
@@ -135,6 +135,7 @@ export const tokens = {
|
|
|
135
135
|
},
|
|
136
136
|
"breakpoint": {
|
|
137
137
|
"--cs-breakpoint-xs": "0px",
|
|
138
|
+
"--cs-breakpoint-phone": "360px",
|
|
138
139
|
"--cs-breakpoint-sm": "640px",
|
|
139
140
|
"--cs-breakpoint-md": "768px",
|
|
140
141
|
"--cs-breakpoint-lg": "1024px",
|
|
@@ -274,9 +275,9 @@ export const tokens = {
|
|
|
274
275
|
"--cs-accent-ink": "#292414",
|
|
275
276
|
"--cs-accent-glow": "rgba(248, 233, 192, 0.48)",
|
|
276
277
|
"--cs-accent-grad-a": "#F8E9C0",
|
|
277
|
-
"--cs-accent-grad-b": "#
|
|
278
|
+
"--cs-accent-grad-b": "#F3B958",
|
|
278
279
|
"--cs-color-text-accent": "#90825E",
|
|
279
|
-
"--cs-color-link": "#
|
|
280
|
+
"--cs-color-link": "#7B6D4A"
|
|
280
281
|
},
|
|
281
282
|
"tho": {
|
|
282
283
|
"--cs-accent": "#F4BA17",
|
|
@@ -288,7 +289,7 @@ export const tokens = {
|
|
|
288
289
|
"--cs-accent-ink": "#45210E",
|
|
289
290
|
"--cs-accent-glow": "rgba(244, 186, 23, 0.48)",
|
|
290
291
|
"--cs-accent-grad-a": "#F4BA17",
|
|
291
|
-
"--cs-accent-grad-b": "#
|
|
292
|
+
"--cs-accent-grad-b": "#F3B958"
|
|
292
293
|
},
|
|
293
294
|
"tho.clay": {
|
|
294
295
|
"--cs-accent": "#513801",
|
|
@@ -300,7 +301,7 @@ export const tokens = {
|
|
|
300
301
|
"--cs-accent-ink": "#2D220E",
|
|
301
302
|
"--cs-accent-glow": "rgba(81, 56, 1, 0.48)",
|
|
302
303
|
"--cs-accent-grad-a": "#513801",
|
|
303
|
-
"--cs-accent-grad-b": "#
|
|
304
|
+
"--cs-accent-grad-b": "#F3B958",
|
|
304
305
|
"--cs-color-text-accent": "#201300",
|
|
305
306
|
"--cs-color-link": "#201300"
|
|
306
307
|
},
|
|
@@ -316,7 +317,7 @@ export const tokens = {
|
|
|
316
317
|
"--cs-accent-grad-a": "#FFE1D8",
|
|
317
318
|
"--cs-accent-grad-b": "#F4BA17",
|
|
318
319
|
"--cs-color-text-accent": "#967C75",
|
|
319
|
-
"--cs-color-link": "#
|
|
320
|
+
"--cs-color-link": "#846B64"
|
|
320
321
|
},
|
|
321
322
|
"hoa": {
|
|
322
323
|
"--cs-accent": "#FCAF91",
|
|
@@ -330,7 +331,7 @@ export const tokens = {
|
|
|
330
331
|
"--cs-accent-grad-a": "#FCAF91",
|
|
331
332
|
"--cs-accent-grad-b": "#F4BA17",
|
|
332
333
|
"--cs-color-text-accent": "#B47054",
|
|
333
|
-
"--cs-color-link": "#
|
|
334
|
+
"--cs-color-link": "#A15E43"
|
|
334
335
|
},
|
|
335
336
|
"hoa.lava": {
|
|
336
337
|
"--cs-accent": "#622B06",
|
|
@@ -358,7 +359,7 @@ export const tokens = {
|
|
|
358
359
|
"--cs-accent-grad-a": "#C0F5FC",
|
|
359
360
|
"--cs-accent-grad-b": "#A3D768",
|
|
360
361
|
"--cs-color-text-accent": "#5A8A90",
|
|
361
|
-
"--cs-color-link": "#
|
|
362
|
+
"--cs-color-link": "#48787E"
|
|
362
363
|
},
|
|
363
364
|
"thuy": {
|
|
364
365
|
"--cs-accent": "#2EDBF7",
|
|
@@ -372,7 +373,7 @@ export const tokens = {
|
|
|
372
373
|
"--cs-accent-grad-a": "#2EDBF7",
|
|
373
374
|
"--cs-accent-grad-b": "#A3D768",
|
|
374
375
|
"--cs-color-text-accent": "#108EA0",
|
|
375
|
-
"--cs-color-link": "#
|
|
376
|
+
"--cs-color-link": "#027B8B"
|
|
376
377
|
},
|
|
377
378
|
"thuy.ocean": {
|
|
378
379
|
"--cs-accent": "#004554",
|
|
@@ -400,7 +401,7 @@ export const tokens = {
|
|
|
400
401
|
"--cs-accent-grad-a": "#E1F1C8",
|
|
401
402
|
"--cs-accent-grad-b": "#FCAF91",
|
|
402
403
|
"--cs-color-text-accent": "#7C8965",
|
|
403
|
-
"--cs-color-link": "#
|
|
404
|
+
"--cs-color-link": "#687451"
|
|
404
405
|
},
|
|
405
406
|
"moc": {
|
|
406
407
|
"--cs-accent": "#A3D768",
|
|
@@ -414,7 +415,7 @@ export const tokens = {
|
|
|
414
415
|
"--cs-accent-grad-a": "#A3D768",
|
|
415
416
|
"--cs-accent-grad-b": "#FCAF91",
|
|
416
417
|
"--cs-color-text-accent": "#629122",
|
|
417
|
-
"--cs-color-link": "#
|
|
418
|
+
"--cs-color-link": "#517B13"
|
|
418
419
|
},
|
|
419
420
|
"moc.forest": {
|
|
420
421
|
"--cs-accent": "#1A4A01",
|
|
@@ -442,7 +443,7 @@ export const tokens = {
|
|
|
442
443
|
"--cs-accent-grad-a": "#FEE5C7",
|
|
443
444
|
"--cs-accent-grad-b": "#2EDBF7",
|
|
444
445
|
"--cs-color-text-accent": "#947F65",
|
|
445
|
-
"--cs-color-link": "#
|
|
446
|
+
"--cs-color-link": "#826D54"
|
|
446
447
|
},
|
|
447
448
|
"kim": {
|
|
448
449
|
"--cs-accent": "#F3B958",
|
|
@@ -456,7 +457,7 @@ export const tokens = {
|
|
|
456
457
|
"--cs-accent-grad-a": "#F3B958",
|
|
457
458
|
"--cs-accent-grad-b": "#2EDBF7",
|
|
458
459
|
"--cs-color-text-accent": "#AC780B",
|
|
459
|
-
"--cs-color-link": "#
|
|
460
|
+
"--cs-color-link": "#966700"
|
|
460
461
|
},
|
|
461
462
|
"kim.steel": {
|
|
462
463
|
"--cs-accent": "#503901",
|
package/tokens/tokens.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$meta": {
|
|
3
3
|
"system": "CyberSkill Design System",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.3.9",
|
|
5
5
|
"generated": "2026-07-23",
|
|
6
6
|
"note": "Generated from tokens/*.css. Root grouped by category; theme/element scopes carry overrides only. Regenerate after any token change (see docs/conventions.md)."
|
|
7
7
|
},
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"--cs-accent-ink": "#45210E",
|
|
66
66
|
"--cs-accent-glow": "rgba(244, 186, 23, 0.48)",
|
|
67
67
|
"--cs-accent-grad-a": "#F4BA17",
|
|
68
|
-
"--cs-accent-grad-b": "#
|
|
68
|
+
"--cs-accent-grad-b": "#F3B958",
|
|
69
69
|
"--cs-accent-on-strong": "#1A1108"
|
|
70
70
|
},
|
|
71
71
|
"depth": {
|
|
@@ -134,6 +134,7 @@
|
|
|
134
134
|
},
|
|
135
135
|
"breakpoint": {
|
|
136
136
|
"--cs-breakpoint-xs": "0px",
|
|
137
|
+
"--cs-breakpoint-phone": "360px",
|
|
137
138
|
"--cs-breakpoint-sm": "640px",
|
|
138
139
|
"--cs-breakpoint-md": "768px",
|
|
139
140
|
"--cs-breakpoint-lg": "1024px",
|
|
@@ -273,9 +274,9 @@
|
|
|
273
274
|
"--cs-accent-ink": "#292414",
|
|
274
275
|
"--cs-accent-glow": "rgba(248, 233, 192, 0.48)",
|
|
275
276
|
"--cs-accent-grad-a": "#F8E9C0",
|
|
276
|
-
"--cs-accent-grad-b": "#
|
|
277
|
+
"--cs-accent-grad-b": "#F3B958",
|
|
277
278
|
"--cs-color-text-accent": "#90825E",
|
|
278
|
-
"--cs-color-link": "#
|
|
279
|
+
"--cs-color-link": "#7B6D4A"
|
|
279
280
|
},
|
|
280
281
|
"tho": {
|
|
281
282
|
"--cs-accent": "#F4BA17",
|
|
@@ -287,7 +288,7 @@
|
|
|
287
288
|
"--cs-accent-ink": "#45210E",
|
|
288
289
|
"--cs-accent-glow": "rgba(244, 186, 23, 0.48)",
|
|
289
290
|
"--cs-accent-grad-a": "#F4BA17",
|
|
290
|
-
"--cs-accent-grad-b": "#
|
|
291
|
+
"--cs-accent-grad-b": "#F3B958"
|
|
291
292
|
},
|
|
292
293
|
"tho.clay": {
|
|
293
294
|
"--cs-accent": "#513801",
|
|
@@ -299,7 +300,7 @@
|
|
|
299
300
|
"--cs-accent-ink": "#2D220E",
|
|
300
301
|
"--cs-accent-glow": "rgba(81, 56, 1, 0.48)",
|
|
301
302
|
"--cs-accent-grad-a": "#513801",
|
|
302
|
-
"--cs-accent-grad-b": "#
|
|
303
|
+
"--cs-accent-grad-b": "#F3B958",
|
|
303
304
|
"--cs-color-text-accent": "#201300",
|
|
304
305
|
"--cs-color-link": "#201300"
|
|
305
306
|
},
|
|
@@ -315,7 +316,7 @@
|
|
|
315
316
|
"--cs-accent-grad-a": "#FFE1D8",
|
|
316
317
|
"--cs-accent-grad-b": "#F4BA17",
|
|
317
318
|
"--cs-color-text-accent": "#967C75",
|
|
318
|
-
"--cs-color-link": "#
|
|
319
|
+
"--cs-color-link": "#846B64"
|
|
319
320
|
},
|
|
320
321
|
"hoa": {
|
|
321
322
|
"--cs-accent": "#FCAF91",
|
|
@@ -329,7 +330,7 @@
|
|
|
329
330
|
"--cs-accent-grad-a": "#FCAF91",
|
|
330
331
|
"--cs-accent-grad-b": "#F4BA17",
|
|
331
332
|
"--cs-color-text-accent": "#B47054",
|
|
332
|
-
"--cs-color-link": "#
|
|
333
|
+
"--cs-color-link": "#A15E43"
|
|
333
334
|
},
|
|
334
335
|
"hoa.lava": {
|
|
335
336
|
"--cs-accent": "#622B06",
|
|
@@ -357,7 +358,7 @@
|
|
|
357
358
|
"--cs-accent-grad-a": "#C0F5FC",
|
|
358
359
|
"--cs-accent-grad-b": "#A3D768",
|
|
359
360
|
"--cs-color-text-accent": "#5A8A90",
|
|
360
|
-
"--cs-color-link": "#
|
|
361
|
+
"--cs-color-link": "#48787E"
|
|
361
362
|
},
|
|
362
363
|
"thuy": {
|
|
363
364
|
"--cs-accent": "#2EDBF7",
|
|
@@ -371,7 +372,7 @@
|
|
|
371
372
|
"--cs-accent-grad-a": "#2EDBF7",
|
|
372
373
|
"--cs-accent-grad-b": "#A3D768",
|
|
373
374
|
"--cs-color-text-accent": "#108EA0",
|
|
374
|
-
"--cs-color-link": "#
|
|
375
|
+
"--cs-color-link": "#027B8B"
|
|
375
376
|
},
|
|
376
377
|
"thuy.ocean": {
|
|
377
378
|
"--cs-accent": "#004554",
|
|
@@ -399,7 +400,7 @@
|
|
|
399
400
|
"--cs-accent-grad-a": "#E1F1C8",
|
|
400
401
|
"--cs-accent-grad-b": "#FCAF91",
|
|
401
402
|
"--cs-color-text-accent": "#7C8965",
|
|
402
|
-
"--cs-color-link": "#
|
|
403
|
+
"--cs-color-link": "#687451"
|
|
403
404
|
},
|
|
404
405
|
"moc": {
|
|
405
406
|
"--cs-accent": "#A3D768",
|
|
@@ -413,7 +414,7 @@
|
|
|
413
414
|
"--cs-accent-grad-a": "#A3D768",
|
|
414
415
|
"--cs-accent-grad-b": "#FCAF91",
|
|
415
416
|
"--cs-color-text-accent": "#629122",
|
|
416
|
-
"--cs-color-link": "#
|
|
417
|
+
"--cs-color-link": "#517B13"
|
|
417
418
|
},
|
|
418
419
|
"moc.forest": {
|
|
419
420
|
"--cs-accent": "#1A4A01",
|
|
@@ -441,7 +442,7 @@
|
|
|
441
442
|
"--cs-accent-grad-a": "#FEE5C7",
|
|
442
443
|
"--cs-accent-grad-b": "#2EDBF7",
|
|
443
444
|
"--cs-color-text-accent": "#947F65",
|
|
444
|
-
"--cs-color-link": "#
|
|
445
|
+
"--cs-color-link": "#826D54"
|
|
445
446
|
},
|
|
446
447
|
"kim": {
|
|
447
448
|
"--cs-accent": "#F3B958",
|
|
@@ -455,7 +456,7 @@
|
|
|
455
456
|
"--cs-accent-grad-a": "#F3B958",
|
|
456
457
|
"--cs-accent-grad-b": "#2EDBF7",
|
|
457
458
|
"--cs-color-text-accent": "#AC780B",
|
|
458
|
-
"--cs-color-link": "#
|
|
459
|
+
"--cs-color-link": "#966700"
|
|
459
460
|
},
|
|
460
461
|
"kim.steel": {
|
|
461
462
|
"--cs-accent": "#503901",
|
package/ui_kits/deck/index.html
CHANGED
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
</style>
|
|
41
41
|
</head>
|
|
42
42
|
<body>
|
|
43
|
-
<a class="cs-skip" href="#main" style="position:absolute;left:-999px;width:1px;height:1px;overflow:hidden">
|
|
43
|
+
<a class="cs-skip" href="#main" style="position:absolute;left:-999px;width:1px;height:1px;overflow:hidden">Bỏ qua đến nội dung</a>
|
|
44
44
|
<main id="main">
|
|
45
45
|
|
|
46
46
|
<deck-stage width="1920" height="1080">
|
|
@@ -139,7 +139,7 @@ function StatusHub() {
|
|
|
139
139
|
|
|
140
140
|
return (
|
|
141
141
|
<div className="sh" lang={lang} data-theme={dark ? "dark" : undefined}>
|
|
142
|
-
<a className="cs-skip" href="#main" style={{ position: "absolute", left: -999, width: 1, height: 1, overflow: "hidden" }}>Skip to content</a>
|
|
142
|
+
<a className="cs-skip" href="#main" style={{ position: "absolute", left: -999, width: 1, height: 1, overflow: "hidden" }}>{lang === "vi" ? "Bỏ qua đến nội dung" : "Skip to content"}</a>
|
|
143
143
|
<header className="hd">
|
|
144
144
|
<div className="hd-in">
|
|
145
145
|
<div className="hd-id">
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Status Hub" viewport="1280x760" name="Status Hub — sign in" subtitle="Umber split login with brand panel + form controls" -->
|
|
1
|
+
<!-- @dsCard group="Status Hub" viewport="1280x760" name="Status Hub — sign in" subtitle="Umber split login with brand panel + form controls (default / loading / error / invalid)" -->
|
|
2
2
|
<!DOCTYPE html>
|
|
3
3
|
<html lang="en">
|
|
4
4
|
<head>
|
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
html, body { margin: 0; min-height: 100vh; }
|
|
12
12
|
.login { display: grid; grid-template-columns: 1.05fr 1fr; min-height: 100vh; }
|
|
13
13
|
.pane-brand { position: relative; overflow: hidden; background: var(--cs-color-brand-umber); color: #fff; padding: 56px 60px; display: flex; flex-direction: column; }
|
|
14
|
-
.pane-brand::before { content: ""; position: absolute; inset: 0; background-image: url("../../assets/aurora-
|
|
14
|
+
.pane-brand::before { content: ""; position: absolute; inset: 0; background-image: url("../../assets/aurora-tho.webp"); background-size: cover; background-position: center; opacity: .42; }
|
|
15
15
|
.pane-brand::after { content: ""; position: absolute; inset: 0; background: linear-gradient(160deg, rgba(26,17,8,.35), rgba(26,17,8,.8)); }
|
|
16
16
|
.pane-brand > * { position: relative; z-index: 1; }
|
|
17
17
|
.brand-lock { display: flex; align-items: center; gap: 12px; font-weight: 800; font-size: 20px; }
|
|
18
18
|
.brand-lock img { width: 40px; height: 40px; }
|
|
19
|
-
.pane-brand
|
|
19
|
+
.pane-brand .brand-headline { font-size: 40px; font-weight: 800; letter-spacing: -.02em; line-height: 1.08; color: var(--cs-color-brand-ochre); margin: auto 0 8px; }
|
|
20
20
|
.pane-brand p { font-size: 17px; opacity: .9; margin: 0; max-width: 420px; }
|
|
21
21
|
.pane-form { display: grid; place-items: center; padding: 40px 24px; background: var(--cs-color-surface-page); }
|
|
22
22
|
.box { width: min(400px, 100%); }
|
|
@@ -25,37 +25,58 @@
|
|
|
25
25
|
form { display: grid; gap: 16px; }
|
|
26
26
|
.rowbetween { display: flex; align-items: center; justify-content: space-between; }
|
|
27
27
|
.fine { text-align: center; font-size: 13px; color: var(--cs-color-text-muted); margin-top: 4px; }
|
|
28
|
+
.state-bar { position: fixed; left: 20px; bottom: 20px; z-index: 60; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; padding: 10px 12px; border: 1px solid var(--cs-color-border-default); background: var(--cs-color-surface-panel); border-radius: 12px; box-shadow: var(--cs-shadow-md); font-size: 13px; }
|
|
29
|
+
.state-bar label { display: flex; align-items: center; gap: 6px; color: var(--cs-color-text-muted); }
|
|
30
|
+
.state-bar select { font: inherit; }
|
|
31
|
+
[hidden] { display: none !important; }
|
|
28
32
|
@media (max-width: 820px) { .login { grid-template-columns: 1fr; } .pane-brand { display: none; } }
|
|
29
33
|
</style>
|
|
30
34
|
</head>
|
|
31
35
|
<body>
|
|
32
|
-
<a class="cs-skip" href="#main" style="position:absolute;left:-999px;width:1px;height:1px;overflow:hidden">
|
|
36
|
+
<a class="cs-skip" href="#main" style="position:absolute;left:-999px;width:1px;height:1px;overflow:hidden">Bỏ qua đến nội dung</a>
|
|
33
37
|
<main id="main">
|
|
34
38
|
|
|
35
39
|
<div class="login">
|
|
36
40
|
<div class="pane-brand">
|
|
37
41
|
<div class="brand-lock"><img src="../../assets/logo-mark.svg" alt="" />CyberSkill</div>
|
|
38
|
-
<
|
|
42
|
+
<p class="brand-headline">Turn Your Will Into Real</p>
|
|
39
43
|
<p>Sign in to the Status Hub — one page, three lenses across every wish in flight.</p>
|
|
40
44
|
</div>
|
|
41
45
|
<div class="pane-form">
|
|
42
46
|
<div class="box">
|
|
43
47
|
<h1>Sign in</h1>
|
|
44
48
|
<p class="sub">Welcome back. Đăng nhập để tiếp tục.</p>
|
|
45
|
-
<form onsubmit="return false">
|
|
46
|
-
<
|
|
47
|
-
|
|
49
|
+
<form id="loginForm" onsubmit="return false">
|
|
50
|
+
<div id="errBanner" class="cs-alert cs-alert--danger" role="status" hidden>
|
|
51
|
+
<span class="cs-alert__icon" aria-hidden="true">!</span>
|
|
52
|
+
<div>
|
|
53
|
+
<p class="cs-alert__title">Sign-in failed</p>
|
|
54
|
+
<div class="cs-alert__body">Check your email and password, then try again.</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
<label id="emailField" class="cs-field"><span class="cs-field__label">Work email</span><input id="emailInput" class="cs-field__control" type="email" placeholder="you@cyberskill.world" /><span id="emailError" class="cs-field__error" role="alert" hidden>Enter a valid work email.</span></label>
|
|
58
|
+
<label class="cs-field"><span class="cs-field__label">Password</span><input class="cs-field__control" type="password" placeholder="••••••••" value="" /></label>
|
|
48
59
|
<div class="rowbetween">
|
|
49
|
-
<label class="cs-switch"><input type="checkbox" role="switch"
|
|
60
|
+
<label class="cs-switch"><input type="checkbox" role="switch" /><span class="cs-switch__track"></span><span class="cs-switch__label">Remember me</span></label>
|
|
50
61
|
<a href="#">Forgot password?</a>
|
|
51
62
|
</div>
|
|
52
|
-
<button type="submit" class="cs-button cs-button--primary cs-button--full">Sign in</button>
|
|
63
|
+
<button id="submitBtn" type="submit" class="cs-button cs-button--primary cs-button--full">Sign in</button>
|
|
53
64
|
<button type="button" class="cs-button cs-button--ghost cs-button--full">✦ Talk to Lumi instead</button>
|
|
54
65
|
</form>
|
|
55
66
|
<p class="fine">New here? <a href="#">Ask for access</a></p>
|
|
56
67
|
</div>
|
|
57
68
|
</div>
|
|
58
69
|
</div>
|
|
70
|
+
<div class="state-bar" aria-label="Demo form state">
|
|
71
|
+
<label>Form state
|
|
72
|
+
<select id="formState">
|
|
73
|
+
<option value="default" selected>default</option>
|
|
74
|
+
<option value="loading">loading</option>
|
|
75
|
+
<option value="error">error</option>
|
|
76
|
+
<option value="invalid">invalid</option>
|
|
77
|
+
</select>
|
|
78
|
+
</label>
|
|
79
|
+
</div>
|
|
59
80
|
<button id="themeToggle" aria-label="Toggle theme" style="position:fixed;right:20px;bottom:20px;z-index:60;border:1px solid var(--cs-color-border-default);background:var(--cs-color-surface-panel);color:var(--cs-color-text-primary);width:44px;height:44px;border-radius:999px;cursor:pointer;box-shadow:var(--cs-shadow-md)">☾</button>
|
|
60
81
|
<script>
|
|
61
82
|
document.getElementById("themeToggle").addEventListener("click", function () {
|
|
@@ -63,6 +84,27 @@
|
|
|
63
84
|
el.setAttribute("data-theme", dark ? "light" : "dark");
|
|
64
85
|
this.textContent = dark ? "☾" : "☀";
|
|
65
86
|
});
|
|
87
|
+
function applyState(state) {
|
|
88
|
+
var banner = document.getElementById("errBanner");
|
|
89
|
+
var emailField = document.getElementById("emailField");
|
|
90
|
+
var emailInput = document.getElementById("emailInput");
|
|
91
|
+
var emailError = document.getElementById("emailError");
|
|
92
|
+
var btn = document.getElementById("submitBtn");
|
|
93
|
+
banner.hidden = state !== "error";
|
|
94
|
+
var invalid = state === "invalid";
|
|
95
|
+
emailField.classList.toggle("is-invalid", invalid);
|
|
96
|
+
emailInput.setAttribute("aria-invalid", invalid ? "true" : "false");
|
|
97
|
+
if (!invalid) emailInput.removeAttribute("aria-invalid");
|
|
98
|
+
emailError.hidden = !invalid;
|
|
99
|
+
var loading = state === "loading";
|
|
100
|
+
btn.classList.toggle("is-loading", loading);
|
|
101
|
+
btn.disabled = loading;
|
|
102
|
+
btn.setAttribute("aria-busy", loading ? "true" : "false");
|
|
103
|
+
btn.textContent = loading ? "Signing in…" : "Sign in";
|
|
104
|
+
}
|
|
105
|
+
var sel = document.getElementById("formState");
|
|
106
|
+
sel.addEventListener("change", function () { applyState(sel.value); });
|
|
107
|
+
applyState(sel.value);
|
|
66
108
|
</script>
|
|
67
109
|
</main>
|
|
68
110
|
</body>
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
</style>
|
|
37
37
|
</head>
|
|
38
38
|
<body>
|
|
39
|
-
<a class="cs-skip" href="#main" style="position:absolute;left:-999px;width:1px;height:1px;overflow:hidden">
|
|
39
|
+
<a class="cs-skip" href="#main" style="position:absolute;left:-999px;width:1px;height:1px;overflow:hidden">Bỏ qua đến nội dung</a>
|
|
40
40
|
<main id="main">
|
|
41
41
|
|
|
42
42
|
<div class="sh">
|
|
@@ -67,7 +67,7 @@ function Website() {
|
|
|
67
67
|
|
|
68
68
|
return (
|
|
69
69
|
<div className="site" data-theme={dark ? "dark" : undefined}>
|
|
70
|
-
<a className="cs-skip" href="#main" style={{ position: "absolute", left: -999, width: 1, height: 1, overflow: "hidden" }}>Skip to content</a>
|
|
70
|
+
<a className="cs-skip" href="#main" style={{ position: "absolute", left: -999, width: 1, height: 1, overflow: "hidden" }}>{loc === "vi" ? "Bỏ qua đến nội dung" : "Skip to content"}</a>
|
|
71
71
|
<header className="hdr cs-surface-light">
|
|
72
72
|
<div className="container hdr-in">
|
|
73
73
|
<a className="brand" href="#top"><img src="../../assets/logo-mark.svg" alt="" />CyberSkill</a>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<style>
|
|
12
12
|
html, body { margin: 0; }
|
|
13
13
|
.car-hero { background: var(--cs-color-brand-umber); color: #fff; padding: 76px 0 64px; position: relative; overflow: hidden; }
|
|
14
|
-
.car-hero::before { content: ""; position: absolute; inset: 0; background-image: url("../../assets/aurora-
|
|
14
|
+
.car-hero::before { content: ""; position: absolute; inset: 0; background-image: url("../../assets/aurora-tho.webp"); background-size: cover; background-position: center; opacity: .32; }
|
|
15
15
|
.car-hero::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(26,17,8,.28), rgba(26,17,8,.78)); }
|
|
16
16
|
.car-hero .container { position: relative; z-index: 1; }
|
|
17
17
|
.car-hero h1 { font-size: clamp(36px, 5vw, 54px); font-weight: 800; letter-spacing: -.02em; color: var(--cs-color-brand-ochre); margin: 12px 0 6px; }
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
</style>
|
|
30
30
|
</head>
|
|
31
31
|
<body>
|
|
32
|
-
<a class="cs-skip" href="#main" style="position:absolute;left:-999px;width:1px;height:1px;overflow:hidden">
|
|
32
|
+
<a class="cs-skip" href="#main" style="position:absolute;left:-999px;width:1px;height:1px;overflow:hidden">Bỏ qua đến nội dung</a>
|
|
33
33
|
<main id="main">
|
|
34
34
|
|
|
35
35
|
<div class="site">
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
<script src="../../_ds_bundle.js"></script>
|
|
37
37
|
</head>
|
|
38
38
|
<body>
|
|
39
|
-
<a class="cs-skip" href="#main" style="position:absolute;left:-999px;width:1px;height:1px;overflow:hidden">
|
|
39
|
+
<a class="cs-skip" href="#main" style="position:absolute;left:-999px;width:1px;height:1px;overflow:hidden">Bỏ qua đến nội dung</a>
|
|
40
40
|
|
|
41
41
|
<div id="root"></div>
|
|
42
42
|
<script type="text/babel">
|
package/ui_kits/website/site.css
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
/* hero */
|
|
25
25
|
.hero { position: relative; overflow: hidden; background: var(--cs-color-brand-umber); color: #fff; }
|
|
26
|
-
.hero::before { content: ""; position: absolute; inset: 0; background-image: url("../../assets/aurora-
|
|
26
|
+
.hero::before { content: ""; position: absolute; inset: 0; background-image: url("../../assets/aurora-tho.webp"); background-size: cover; background-position: center; opacity: .5; }
|
|
27
27
|
.hero::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(26,17,8,.35), rgba(26,17,8,.82) 78%); }
|
|
28
28
|
.hero-in { position: relative; z-index: 1; display: grid; grid-template-columns: 1.35fr .65fr; gap: var(--cs-space-8); align-items: center; padding: 84px 0 96px; }
|
|
29
29
|
.hero .eyebrow { color: var(--cs-color-brand-ochre); }
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<style>
|
|
12
12
|
html, body { margin: 0; }
|
|
13
13
|
.work-hero { background: var(--cs-color-brand-umber); color: #fff; padding: 72px 0 60px; position: relative; overflow: hidden; }
|
|
14
|
-
.work-hero::before { content: ""; position: absolute; inset: 0; background-image: url("../../assets/aurora-
|
|
14
|
+
.work-hero::before { content: ""; position: absolute; inset: 0; background-image: url("../../assets/aurora-tho.webp"); background-size: cover; background-position: center; opacity: .34; }
|
|
15
15
|
.work-hero::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(26,17,8,.3), rgba(26,17,8,.75)); }
|
|
16
16
|
.work-hero .container { position: relative; z-index: 1; }
|
|
17
17
|
.work-hero h1 { font-size: clamp(36px, 5vw, 54px); font-weight: 800; letter-spacing: -.02em; color: var(--cs-color-brand-ochre); margin: 12px 0 6px; }
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
</style>
|
|
36
36
|
</head>
|
|
37
37
|
<body>
|
|
38
|
-
<a class="cs-skip" href="#main" style="position:absolute;left:-999px;width:1px;height:1px;overflow:hidden">
|
|
38
|
+
<a class="cs-skip" href="#main" style="position:absolute;left:-999px;width:1px;height:1px;overflow:hidden">Bỏ qua đến nội dung</a>
|
|
39
39
|
<main id="main">
|
|
40
40
|
|
|
41
41
|
<div class="site">
|
package/assets/aurora-hoa.png
DELETED
|
Binary file
|
package/assets/aurora-kim.png
DELETED
|
Binary file
|
package/assets/aurora-moc.png
DELETED
|
Binary file
|
package/assets/aurora-thuy.png
DELETED
|
Binary file
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# Container-query migration (G1 / CDS-RESP-001)
|
|
2
|
-
|
|
3
|
-
Status: **started Phase 4** (2026-08-08) — compatibility layer only.
|
|
4
|
-
Owner: design-system maintainer.
|
|
5
|
-
|
|
6
|
-
## Decision
|
|
7
|
-
|
|
8
|
-
Begin container-query adoption **behind a compatibility CSS opt-in**, without rewriting every template grid in one pass.
|
|
9
|
-
|
|
10
|
-
1. Hosts opt in with `.cs-cq` (`container-type: inline-size`).
|
|
11
|
-
2. Children may use `@container cs (max-width: …)` rules; first helper: `.cs-cq-stack`.
|
|
12
|
-
3. Existing `@media` rules in `base/responsive.css` remain the default authority until generated layout classes land.
|
|
13
|
-
|
|
14
|
-
## Acceptance for later waves
|
|
15
|
-
|
|
16
|
-
- Kit card grids and Status Hub lenses can size from parent width, not only viewport.
|
|
17
|
-
- No regression on `_audit/responsive-overflow-320.html` or zoom-text-spacing.
|
|
18
|
-
- Document any permanent media-only exceptions in this file.
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
# Overlay manager design (C8 / CDS-ARCH-001)
|
|
2
|
-
|
|
3
|
-
Status: **landed in Phase 3** (operator decision D5=A, 2026-08-08) — see `components/overlays/OverlayManager.jsx`.
|
|
4
|
-
Owner: design-system maintainer · Related: UX-009 depth tokens, CDS-A11Y-003 keyboard models.
|
|
5
|
-
|
|
6
|
-
## Problem
|
|
7
|
-
|
|
8
|
-
Overlays (Dialog, AlertDialog, Drawer, Popover, Menu, CommandPalette, Toast, Tour) currently each own:
|
|
9
|
-
|
|
10
|
-
- z-index (with dialog hardcoding `1000` historically — now tokenized to `--cs-depth-modal`)
|
|
11
|
-
- focus trap / restore
|
|
12
|
-
- body scroll-lock
|
|
13
|
-
- Escape handling
|
|
14
|
-
|
|
15
|
-
Nested overlays (toast while modal open; confirm inside drawer) race on DOM order and scroll-lock count. Keyboard models for complex widgets (CDS-A11Y-003) need a single stack authority.
|
|
16
|
-
|
|
17
|
-
## Goals
|
|
18
|
-
|
|
19
|
-
1. One stack owns paint order (depth tokens), focus scope, Escape routing, and scroll-lock refcount.
|
|
20
|
-
2. Toasts always paint above modals (`--cs-depth-toast` > `--cs-depth-modal`) — already the token doctrine.
|
|
21
|
-
3. Nested overlays: only the topmost modal-layer traps focus; Escape closes topmost first.
|
|
22
|
-
4. No third-party floating library required for v1; Floating UI may be adopted later for positioning only.
|
|
23
|
-
|
|
24
|
-
## Non-goals (v1)
|
|
25
|
-
|
|
26
|
-
- Rewriting every popover positioner
|
|
27
|
-
- Changing public component props (additive `layer` / `portal` opts only)
|
|
28
|
-
- SSR portal polyfills beyond “no `window` during render” (Tour already fixed)
|
|
29
|
-
|
|
30
|
-
## API sketch
|
|
31
|
-
|
|
32
|
-
```ts
|
|
33
|
-
// components/overlays/OverlayManager.jsx (Phase 3 land)
|
|
34
|
-
|
|
35
|
-
type LayerKind = 'dropdown' | 'popover' | 'modal' | 'toast' | 'tour';
|
|
36
|
-
|
|
37
|
-
type LayerRegistration = {
|
|
38
|
-
id: string;
|
|
39
|
-
kind: LayerKind;
|
|
40
|
-
/** Focus trap when kind is modal */
|
|
41
|
-
trapFocus?: boolean;
|
|
42
|
-
onEscape?: () => void;
|
|
43
|
-
/** Element that receives restore focus */
|
|
44
|
-
restoreEl?: HTMLElement | null;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
type OverlayManagerApi = {
|
|
48
|
-
register(layer: LayerRegistration): () => void; // unregister
|
|
49
|
-
top(): LayerRegistration | null;
|
|
50
|
-
/** Refcount scroll lock — lock while any modal registered */
|
|
51
|
-
scrollLocked: boolean;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
// React context
|
|
55
|
-
const OverlayContext = React.createContext<OverlayManagerApi | null>(null);
|
|
56
|
-
function OverlayProvider({ children }: { children: React.ReactNode }): JSX.Element;
|
|
57
|
-
function useOverlayLayer(opts: Omit<LayerRegistration, 'id'>): { id: string };
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### Depth mapping
|
|
61
|
-
|
|
62
|
-
| Kind | Token | Notes |
|
|
63
|
-
|------|-------|--------|
|
|
64
|
-
| dropdown | `--cs-depth-dropdown` (60) | Menus under sticky nav |
|
|
65
|
-
| popover | `--cs-depth-overlay` | HoverCard, Popover |
|
|
66
|
-
| modal | `--cs-depth-modal` (100) | Dialog, AlertDialog, Drawer, CommandPalette |
|
|
67
|
-
| toast | `--cs-depth-toast` (200) | Above modals |
|
|
68
|
-
| tour | `--cs-depth-toast` or dedicated | Full-viewport coachmarks |
|
|
69
|
-
|
|
70
|
-
### Focus & Escape
|
|
71
|
-
|
|
72
|
-
- Modal registration pushes a focus scope; Tab cycles within the topmost modal host (`.cs-dialog-layer` / drawer panel).
|
|
73
|
-
- Escape invokes `onEscape` of `top()` only; if none, bubbles.
|
|
74
|
-
- Unregister restores focus to `restoreEl` when that layer was topmost at close.
|
|
75
|
-
|
|
76
|
-
### Scroll-lock
|
|
77
|
-
|
|
78
|
-
- `document.documentElement` / `body` overflow hidden while `count(modal) > 0`.
|
|
79
|
-
- Nested modals increment; close decrements — no flicker unlock.
|
|
80
|
-
|
|
81
|
-
### Portal host
|
|
82
|
-
|
|
83
|
-
```html
|
|
84
|
-
<div id="cs-overlay-root" data-cs-overlay-root></div>
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
Components portal into `#cs-overlay-root` when present; otherwise document.body (today’s behavior). Kits and Atomic View mount the root once.
|
|
88
|
-
|
|
89
|
-
## Migration (Phase 3)
|
|
90
|
-
|
|
91
|
-
1. Ship `OverlayProvider` + `useOverlayLayer` beside existing components (no breaking change).
|
|
92
|
-
2. Wire Dialog / AlertDialog / Drawer / CommandPalette / ToastStack first.
|
|
93
|
-
3. Add a11y-gate rows: nested dialog+toast, nested dialog+alertdialog Escape order, scroll-lock refcount.
|
|
94
|
-
4. Then E3 keyboard models for Cascader / TreeSelect / Menubar adopt the same focus-scope helper.
|
|
95
|
-
|
|
96
|
-
## Acceptance
|
|
97
|
-
|
|
98
|
-
- Toast visible above open dialog (behavior gate — already green; keep).
|
|
99
|
-
- Nested AlertDialog inside Dialog: Escape closes alert first; focus returns to dialog.
|
|
100
|
-
- Zero raw `z-index` > 20 in `base/` outside token vars (token-contract).
|
|
101
|
-
- Design note remains the SoT until Phase 3 lands code under `components/overlays/`.
|