@neuravision/construct 2.0.3 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +272 -0
- package/README.md +148 -152
- package/behaviors/combobox.js +447 -0
- package/behaviors/drawer.js +18 -0
- package/behaviors/dropdown.js +296 -0
- package/behaviors/index.d.ts +333 -0
- package/behaviors/index.js +9 -0
- package/behaviors/internal/dialog-controller.js +351 -0
- package/behaviors/internal/dom.js +377 -0
- package/behaviors/internal/overlay.js +241 -0
- package/behaviors/internal/popup-layer.js +188 -0
- package/behaviors/modal.js +17 -0
- package/behaviors/popover.js +269 -0
- package/behaviors/select-menu.js +326 -0
- package/behaviors/tabs.js +230 -0
- package/behaviors/toggle-group.js +234 -0
- package/behaviors/tooltip.js +233 -0
- package/components/README.md +279 -83
- package/components/_shared.css +11 -10
- package/components/_shell-shared.css +20 -4
- package/components/app-shell-v2.css +21 -14
- package/components/app-shell.css +23 -14
- package/components/badge.css +15 -0
- package/components/button.css +103 -15
- package/components/card.css +53 -8
- package/components/checkbox.css +3 -2
- package/components/chip.css +1 -1
- package/components/datepicker.css +3 -1
- package/components/datum.css +204 -0
- package/components/index.css +5 -0
- package/components/meter.css +182 -0
- package/components/navbar.css +88 -3
- package/components/slider.css +2 -1
- package/components/status.css +107 -0
- package/components/switch.css +4 -3
- package/components/tooltip.css +4 -0
- package/docs/architecture.md +79 -0
- package/docs/behaviors.md +101 -0
- package/docs/fonts.md +70 -0
- package/docs/governance.md +85 -0
- package/docs/guidelines.md +42 -23
- package/examples/react/README.md +20 -0
- package/examples/react/SettingsModal.jsx +66 -0
- package/examples/react/construct.css +5 -0
- package/fonts.css +10 -0
- package/foundations.css +8 -1
- package/package.json +72 -21
- package/schemas/components.schema.json +107 -0
- package/schemas/examples/theme.example.json +27 -0
- package/schemas/primitives.schema.json +135 -0
- package/schemas/semantic.schema.json +223 -0
- package/schemas/theme.schema.json +63 -0
- package/scripts/build-tokens.mjs +1417 -0
- package/scripts/construct-theme.mjs +43 -0
- package/scripts/validate-tokens.mjs +25 -0
- package/standalone/accordion.css +3 -0
- package/standalone/alert.css +3 -0
- package/standalone/app-shell-v2.css +4 -0
- package/standalone/app-shell.css +4 -0
- package/standalone/avatar.css +3 -0
- package/standalone/badge.css +3 -0
- package/standalone/banner.css +3 -0
- package/standalone/breadcrumbs.css +3 -0
- package/standalone/button.css +3 -0
- package/standalone/card.css +3 -0
- package/standalone/chart.css +3 -0
- package/standalone/checkbox.css +3 -0
- package/standalone/chip.css +3 -0
- package/standalone/combobox.css +3 -0
- package/standalone/core.css +4 -0
- package/standalone/data-table.css +3 -0
- package/standalone/datepicker.css +3 -0
- package/standalone/datum.css +3 -0
- package/standalone/divider.css +3 -0
- package/standalone/drawer.css +3 -0
- package/standalone/dropdown.css +3 -0
- package/standalone/empty-state.css +3 -0
- package/standalone/field.css +3 -0
- package/standalone/file-upload.css +3 -0
- package/standalone/icon.css +3 -0
- package/standalone/input.css +3 -0
- package/standalone/list.css +3 -0
- package/standalone/meter.css +3 -0
- package/standalone/modal.css +3 -0
- package/standalone/navbar.css +3 -0
- package/standalone/pagination.css +3 -0
- package/standalone/popover.css +3 -0
- package/standalone/progress-bar.css +3 -0
- package/standalone/select-menu.css +3 -0
- package/standalone/select.css +3 -0
- package/standalone/sidebar.css +3 -0
- package/standalone/skeleton.css +3 -0
- package/standalone/skip-link.css +3 -0
- package/standalone/slider.css +3 -0
- package/standalone/spinner.css +3 -0
- package/standalone/status.css +3 -0
- package/standalone/switch.css +3 -0
- package/standalone/table.css +3 -0
- package/standalone/tabs.css +3 -0
- package/standalone/textarea.css +3 -0
- package/standalone/toast.css +3 -0
- package/standalone/toggle-group.css +3 -0
- package/standalone/toolbar.css +3 -0
- package/standalone/tooltip.css +3 -0
- package/standalone/tree.css +3 -0
- package/tokens/README.md +130 -126
- package/tokens/components.json +54 -0
- package/tokens/primitives.json +268 -0
- package/tokens/semantic.dark.json +93 -0
- package/tokens/semantic.high-contrast.json +93 -0
- package/tokens/semantic.light.json +178 -0
- package/tokens/tokens.css +532 -28
- package/tokens/tokens.js +335 -25
- package/tokens/tokens.json +764 -21
- package/tokens/tokens.ts +335 -25
package/components/_shared.css
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
:root {
|
|
2
|
-
--ct-control-bg: var(--
|
|
3
|
-
--ct-control-bg-hover: var(--
|
|
4
|
-
--ct-control-bg-disabled: var(--
|
|
5
|
-
--ct-control-border: var(--
|
|
6
|
-
--ct-control-border-hover: var(--
|
|
7
|
-
--ct-control-border-focus: var(--
|
|
8
|
-
--ct-control-text: var(--
|
|
9
|
-
--ct-control-placeholder: var(--
|
|
10
|
-
--ct-control-radius: var(--
|
|
2
|
+
--ct-control-bg: var(--component-control-background);
|
|
3
|
+
--ct-control-bg-hover: var(--component-control-background-hover);
|
|
4
|
+
--ct-control-bg-disabled: var(--component-control-background-disabled);
|
|
5
|
+
--ct-control-border: var(--component-control-border);
|
|
6
|
+
--ct-control-border-hover: var(--component-control-border-hover);
|
|
7
|
+
--ct-control-border-focus: var(--component-control-border-focus);
|
|
8
|
+
--ct-control-text: var(--component-control-text);
|
|
9
|
+
--ct-control-placeholder: var(--component-control-placeholder);
|
|
10
|
+
--ct-control-radius: var(--component-control-radius);
|
|
11
11
|
--ct-control-transition: border-color var(--duration-fast) var(--easing-standard),
|
|
12
12
|
box-shadow var(--duration-fast) var(--easing-standard),
|
|
13
13
|
background var(--duration-fast) var(--easing-standard),
|
|
@@ -106,11 +106,12 @@
|
|
|
106
106
|
outline-color: var(--color-state-danger);
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
/* ──
|
|
109
|
+
/* ── Construct 44×44 target policy (WCAG 2.2 SC 2.5.5 is AAA) ─── */
|
|
110
110
|
|
|
111
111
|
@media (pointer: coarse) {
|
|
112
112
|
:root {
|
|
113
113
|
--control-height-sm: 44px;
|
|
114
|
+
--control-height-md: 44px;
|
|
114
115
|
--control-height-calendar-day: 44px;
|
|
115
116
|
}
|
|
116
117
|
}
|
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
/* Crosses component boundary: shells orchestrate child layout. */
|
|
4
4
|
/* ─────────────────────────────────────────────────────────────── */
|
|
5
5
|
|
|
6
|
+
/* Both layouts expose the canonical `--ct-shell-*` sizing and motion
|
|
7
|
+
controls. Their historical variable names are compatibility aliases. */
|
|
8
|
+
|
|
9
|
+
:is(.ct-app-shell, .ct-app-shell-v2) {
|
|
10
|
+
min-width: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
:is(.ct-app-shell__main, .ct-app-shell-v2__main),
|
|
14
|
+
:is(.ct-app-shell__sidebar, .ct-app-shell-v2__sidebar),
|
|
15
|
+
:is(.ct-app-shell__panel, .ct-app-shell-v2__panel) {
|
|
16
|
+
min-width: 0;
|
|
17
|
+
min-height: 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
6
20
|
|
|
7
21
|
/* ── Collapsed: Hide Labels & Badges ── */
|
|
8
22
|
|
|
@@ -16,8 +30,8 @@
|
|
|
16
30
|
white-space: nowrap;
|
|
17
31
|
/* Collapsing: labels fade out first, then width snaps */
|
|
18
32
|
transition:
|
|
19
|
-
opacity
|
|
20
|
-
width 0ms linear
|
|
33
|
+
opacity var(--ct-shell-motion-duration) var(--ct-shell-motion-easing),
|
|
34
|
+
width 0ms linear var(--ct-shell-motion-duration);
|
|
21
35
|
}
|
|
22
36
|
|
|
23
37
|
|
|
@@ -30,7 +44,9 @@
|
|
|
30
44
|
opacity: 1;
|
|
31
45
|
width: auto;
|
|
32
46
|
/* Expanding: labels fade in after sidebar width finishes growing */
|
|
33
|
-
transition:
|
|
47
|
+
transition:
|
|
48
|
+
opacity var(--ct-shell-motion-duration) var(--ct-shell-motion-easing)
|
|
49
|
+
var(--ct-shell-motion-duration);
|
|
34
50
|
}
|
|
35
51
|
|
|
36
52
|
|
|
@@ -44,7 +60,7 @@
|
|
|
44
60
|
|
|
45
61
|
/* ── Tablet: Auto-Collapse to Rail ── */
|
|
46
62
|
|
|
47
|
-
@media (max-width: 1199px) {
|
|
63
|
+
@media (max-width: 1199px) { /* < lg breakpoint (1200px) */
|
|
48
64
|
:is(.ct-app-shell, .ct-app-shell-v2):not([data-sidebar-state]) .ct-nav-item__label,
|
|
49
65
|
:is(.ct-app-shell, .ct-app-shell-v2):not([data-sidebar-state]) .ct-nav-item__badge,
|
|
50
66
|
:is(.ct-app-shell, .ct-app-shell-v2):not([data-sidebar-state]) .ct-sidebar__header span,
|
|
@@ -17,24 +17,31 @@
|
|
|
17
17
|
/* │ ╰────────╯ ╰───────────────────┴──────────────╯ │ */
|
|
18
18
|
/* ╰─────────────────────────────────────────────────────╯ */
|
|
19
19
|
/* */
|
|
20
|
-
/* Shell breakpoints:
|
|
21
|
-
/*
|
|
22
|
-
/* Tablet:
|
|
20
|
+
/* Shell breakpoints (from the public primitive scale): */
|
|
21
|
+
/* Compact: <900px (< md) */
|
|
22
|
+
/* Tablet: 900–1199px */
|
|
23
23
|
/* Desktop: >=1200px */
|
|
24
24
|
/* ─────────────────────────────────────────────────────────────── */
|
|
25
25
|
|
|
26
26
|
.ct-app-shell-v2 {
|
|
27
|
-
/* ── Public Tokens ── */
|
|
28
|
-
--ct-
|
|
29
|
-
--ct-
|
|
30
|
-
--ct-
|
|
27
|
+
/* ── Shared Public Tokens ── */
|
|
28
|
+
--ct-shell-sidebar-width: 260px;
|
|
29
|
+
--ct-shell-sidebar-rail-width: 64px;
|
|
30
|
+
--ct-shell-panel-width: 340px;
|
|
31
|
+
--ct-shell-motion-duration: 250ms;
|
|
32
|
+
--ct-shell-motion-easing: cubic-bezier(0.32, 0.72, 0, 1);
|
|
33
|
+
|
|
34
|
+
/* V2 aliases remain public for backward compatibility. */
|
|
35
|
+
--ct-v2-sidebar-width: var(--ct-shell-sidebar-width);
|
|
36
|
+
--ct-v2-sidebar-rail-width: var(--ct-shell-sidebar-rail-width);
|
|
37
|
+
--ct-v2-panel-width: var(--ct-shell-panel-width);
|
|
31
38
|
--ct-v2-gap: var(--space-4);
|
|
32
39
|
--ct-v2-radius: var(--radius-lg);
|
|
33
40
|
--ct-v2-canvas-bg: var(--color-bg-muted);
|
|
34
41
|
--ct-v2-surface-bg: var(--color-bg-canvas);
|
|
35
42
|
--ct-v2-surface-shadow: var(--shadow-xs);
|
|
36
|
-
--ct-v2-transition-duration:
|
|
37
|
-
--ct-v2-transition-easing:
|
|
43
|
+
--ct-v2-transition-duration: var(--ct-shell-motion-duration);
|
|
44
|
+
--ct-v2-transition-easing: var(--ct-shell-motion-easing);
|
|
38
45
|
|
|
39
46
|
/* ── Internal ── */
|
|
40
47
|
--_v2-sidebar-w: var(--ct-v2-sidebar-width);
|
|
@@ -362,13 +369,13 @@
|
|
|
362
369
|
|
|
363
370
|
/* Delay grid shrink on collapse so labels fade out first */
|
|
364
371
|
.ct-app-shell-v2[data-sidebar-state='collapsed'] {
|
|
365
|
-
transition-delay:
|
|
372
|
+
transition-delay: var(--ct-shell-motion-duration);
|
|
366
373
|
}
|
|
367
374
|
|
|
368
375
|
|
|
369
|
-
/* ── Responsive: Tablet (
|
|
376
|
+
/* ── Responsive: Tablet (900–1199px) ── */
|
|
370
377
|
|
|
371
|
-
@media (max-width: 1199px) {
|
|
378
|
+
@media (max-width: 1199px) { /* < lg breakpoint (1200px) */
|
|
372
379
|
/* Auto-collapse sidebar to rail when no explicit state */
|
|
373
380
|
.ct-app-shell-v2:not([data-sidebar-state]) {
|
|
374
381
|
--_v2-sidebar-w: var(--ct-v2-sidebar-rail-width);
|
|
@@ -390,9 +397,9 @@
|
|
|
390
397
|
}
|
|
391
398
|
|
|
392
399
|
|
|
393
|
-
/* ── Responsive:
|
|
400
|
+
/* ── Responsive: Compact (< md breakpoint, 900px) ── */
|
|
394
401
|
|
|
395
|
-
@media (max-width:
|
|
402
|
+
@media (max-width: 899px) { /* < md breakpoint (900px) */
|
|
396
403
|
.ct-app-shell-v2 {
|
|
397
404
|
--ct-v2-gap: var(--space-3);
|
|
398
405
|
}
|
package/components/app-shell.css
CHANGED
|
@@ -1,23 +1,32 @@
|
|
|
1
|
-
/* ── App Shell
|
|
1
|
+
/* ── App Shell (compatibility layout) ─────────────────────────── */
|
|
2
2
|
/* CSS Grid layout shell that orchestrates Navbar, Sidebar, */
|
|
3
3
|
/* Main content, optional Panel, and optional Footer. */
|
|
4
|
+
/* New applications should prefer App Shell V2. `.ct-app-shell` */
|
|
5
|
+
/* remains supported as the non-floating compatibility contract. */
|
|
4
6
|
/* */
|
|
5
|
-
/* Shell breakpoints (
|
|
6
|
-
/*
|
|
7
|
-
/* Tablet:
|
|
7
|
+
/* Shell breakpoints (from the public primitive scale): */
|
|
8
|
+
/* Compact: <900px (< md) */
|
|
9
|
+
/* Tablet: 900–1199px */
|
|
8
10
|
/* Desktop: 1200–1439px */
|
|
9
11
|
/* Wide: >=1440px */
|
|
10
12
|
/* ────────────────────────────────────────────────────────────── */
|
|
11
13
|
|
|
12
14
|
.ct-app-shell {
|
|
13
|
-
/* ── Public Tokens ── */
|
|
14
|
-
--ct-sidebar-width: 260px;
|
|
15
|
-
--ct-sidebar-rail-width: 56px;
|
|
16
|
-
--ct-panel-width: 320px;
|
|
15
|
+
/* ── Shared Public Tokens ── */
|
|
16
|
+
--ct-shell-sidebar-width: 260px;
|
|
17
|
+
--ct-shell-sidebar-rail-width: 56px;
|
|
18
|
+
--ct-shell-panel-width: 320px;
|
|
19
|
+
--ct-shell-motion-duration: 200ms;
|
|
20
|
+
--ct-shell-motion-easing: ease-out;
|
|
21
|
+
|
|
22
|
+
/* Legacy aliases remain public for backward compatibility. */
|
|
23
|
+
--ct-sidebar-width: var(--ct-shell-sidebar-width);
|
|
24
|
+
--ct-sidebar-rail-width: var(--ct-shell-sidebar-rail-width);
|
|
25
|
+
--ct-panel-width: var(--ct-shell-panel-width);
|
|
17
26
|
--ct-header-height: auto;
|
|
18
27
|
--ct-footer-height: auto;
|
|
19
|
-
--ct-shell-transition-duration:
|
|
20
|
-
--ct-shell-transition-easing:
|
|
28
|
+
--ct-shell-transition-duration: var(--ct-shell-motion-duration);
|
|
29
|
+
--ct-shell-transition-easing: var(--ct-shell-motion-easing);
|
|
21
30
|
|
|
22
31
|
/* ── Internal Variables ── */
|
|
23
32
|
--_sidebar-width: var(--ct-sidebar-width);
|
|
@@ -249,7 +258,7 @@
|
|
|
249
258
|
|
|
250
259
|
/* Collapsing: delay grid shrink so labels fade out first */
|
|
251
260
|
.ct-app-shell[data-sidebar-state='collapsed'] {
|
|
252
|
-
transition-delay:
|
|
261
|
+
transition-delay: var(--ct-shell-motion-duration);
|
|
253
262
|
}
|
|
254
263
|
|
|
255
264
|
|
|
@@ -260,7 +269,7 @@
|
|
|
260
269
|
}
|
|
261
270
|
|
|
262
271
|
|
|
263
|
-
/* ── Responsive: Tablet (
|
|
272
|
+
/* ── Responsive: Tablet (900–1199px) ── */
|
|
264
273
|
|
|
265
274
|
@media (max-width: 1199px) { /* < lg breakpoint (1200px) */
|
|
266
275
|
/* Auto-collapse sidebar to rail when no explicit state is set */
|
|
@@ -286,9 +295,9 @@
|
|
|
286
295
|
}
|
|
287
296
|
|
|
288
297
|
|
|
289
|
-
/* ── Responsive:
|
|
298
|
+
/* ── Responsive: Compact (< md breakpoint, 900px) ── */
|
|
290
299
|
|
|
291
|
-
@media (max-width:
|
|
300
|
+
@media (max-width: 899px) { /* < md breakpoint (900px) */
|
|
292
301
|
/* Auto-hide sidebar when no explicit state is set */
|
|
293
302
|
.ct-app-shell:not([data-sidebar-state]) {
|
|
294
303
|
--_sidebar-width: 0px;
|
package/components/badge.css
CHANGED
|
@@ -38,6 +38,21 @@
|
|
|
38
38
|
background: var(--ct-badge-accent);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/* Explicit neutral alias for generated/conditional variant class lists. */
|
|
42
|
+
.ct-badge--neutral {
|
|
43
|
+
--ct-badge-bg: var(--color-bg-muted);
|
|
44
|
+
--ct-badge-border: var(--color-border-subtle);
|
|
45
|
+
--ct-badge-color: var(--color-text-secondary);
|
|
46
|
+
--ct-badge-accent: var(--ct-badge-color);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.ct-badge--sm {
|
|
50
|
+
gap: var(--space-1);
|
|
51
|
+
padding: 0 var(--space-2);
|
|
52
|
+
font-size: var(--font-size-2xs);
|
|
53
|
+
line-height: var(--line-height-xs);
|
|
54
|
+
}
|
|
55
|
+
|
|
41
56
|
.ct-badge--info {
|
|
42
57
|
--ct-badge-bg: var(--color-state-info-surface);
|
|
43
58
|
--ct-badge-border: var(--color-state-info-border);
|
package/components/button.css
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
.ct-button {
|
|
2
|
-
--ct-button-bg: var(--
|
|
3
|
-
--ct-button-bg-hover: var(--
|
|
4
|
-
--ct-button-bg-active: var(--
|
|
5
|
-
--ct-button-border:
|
|
6
|
-
--ct-button-color: var(--
|
|
7
|
-
--ct-button-height: var(--
|
|
8
|
-
--ct-button-padding-x: var(--
|
|
9
|
-
--ct-button-font-size: var(--font-size
|
|
10
|
-
--ct-button-line-height: var(--line-height
|
|
11
|
-
|
|
2
|
+
--ct-button-bg: var(--component-button-background);
|
|
3
|
+
--ct-button-bg-hover: var(--component-button-background-hover);
|
|
4
|
+
--ct-button-bg-active: var(--component-button-background-active);
|
|
5
|
+
--ct-button-border: var(--component-button-border);
|
|
6
|
+
--ct-button-color: var(--component-button-color);
|
|
7
|
+
--ct-button-height: var(--component-button-height);
|
|
8
|
+
--ct-button-padding-x: var(--component-button-padding-x);
|
|
9
|
+
--ct-button-font-size: var(--component-button-font-size);
|
|
10
|
+
--ct-button-line-height: var(--component-button-line-height);
|
|
11
|
+
--ct-button-font-weight: var(--component-button-font-weight);
|
|
12
|
+
--ct-button-radius: var(--component-button-radius);
|
|
13
|
+
--ct-button-gap: var(--component-button-gap);
|
|
14
|
+
--ct-button-loading-spinner-size: var(--component-button-loading-spinner-size);
|
|
15
|
+
|
|
16
|
+
position: relative;
|
|
12
17
|
display: inline-flex;
|
|
13
18
|
align-items: center;
|
|
14
19
|
justify-content: center;
|
|
@@ -32,12 +37,12 @@
|
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
@media (hover: hover) {
|
|
35
|
-
.ct-button:hover {
|
|
40
|
+
.ct-button:not(:disabled):not([aria-disabled='true']):not([aria-busy='true']):not([data-loading='true']):hover {
|
|
36
41
|
background: var(--ct-button-bg-hover);
|
|
37
42
|
}
|
|
38
43
|
}
|
|
39
44
|
|
|
40
|
-
.ct-button:active {
|
|
45
|
+
.ct-button:not(:disabled):not([aria-disabled='true']):not([aria-busy='true']):not([data-loading='true']):active {
|
|
41
46
|
background: var(--ct-button-bg-active);
|
|
42
47
|
transform: translateY(1px);
|
|
43
48
|
}
|
|
@@ -52,6 +57,56 @@
|
|
|
52
57
|
opacity: var(--opacity-disabled);
|
|
53
58
|
transform: none;
|
|
54
59
|
cursor: not-allowed;
|
|
60
|
+
pointer-events: none;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* Loading contract:
|
|
64
|
+
- set `aria-busy="true"` and `data-loading="true"`;
|
|
65
|
+
- native buttons must also use `disabled` to block keyboard activation;
|
|
66
|
+
- wrap the stable accessible label in `.ct-button__content`;
|
|
67
|
+
- keep `.ct-button__loader` decorative (`aria-hidden="true"`). */
|
|
68
|
+
.ct-button__content {
|
|
69
|
+
display: inline-flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
justify-content: center;
|
|
72
|
+
gap: inherit;
|
|
73
|
+
opacity: 1;
|
|
74
|
+
transition: opacity var(--duration-fast) var(--easing-standard);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.ct-button__loader {
|
|
78
|
+
position: absolute;
|
|
79
|
+
inset: 0;
|
|
80
|
+
display: grid;
|
|
81
|
+
place-items: center;
|
|
82
|
+
opacity: 0;
|
|
83
|
+
pointer-events: none;
|
|
84
|
+
transition: opacity var(--duration-fast) var(--easing-standard);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.ct-button__loader::before {
|
|
88
|
+
content: '';
|
|
89
|
+
width: var(--ct-button-loading-spinner-size);
|
|
90
|
+
height: var(--ct-button-loading-spinner-size);
|
|
91
|
+
border: var(--border-medium) solid currentColor;
|
|
92
|
+
border-inline-end-color: transparent;
|
|
93
|
+
border-radius: var(--radius-round);
|
|
94
|
+
animation: ct-spin var(--ct-spinner-duration) linear infinite;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.ct-button:is([aria-busy='true'], [data-loading='true']) {
|
|
98
|
+
opacity: 1;
|
|
99
|
+
transform: none;
|
|
100
|
+
cursor: wait;
|
|
101
|
+
pointer-events: none;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.ct-button:is([aria-busy='true'], [data-loading='true']) .ct-button__content {
|
|
105
|
+
opacity: 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.ct-button:is([aria-busy='true'], [data-loading='true']) .ct-button__loader {
|
|
109
|
+
opacity: 1;
|
|
55
110
|
}
|
|
56
111
|
|
|
57
112
|
.ct-button--secondary {
|
|
@@ -88,8 +143,8 @@
|
|
|
88
143
|
|
|
89
144
|
.ct-button--danger {
|
|
90
145
|
--ct-button-bg: var(--color-state-danger);
|
|
91
|
-
--ct-button-bg-hover: color-mix(in srgb, var(--color-state-danger) 85%,
|
|
92
|
-
--ct-button-bg-active: color-mix(in srgb, var(--color-state-danger) 70%,
|
|
146
|
+
--ct-button-bg-hover: color-mix(in srgb, var(--color-state-danger) 85%, var(--color-state-danger-text));
|
|
147
|
+
--ct-button-bg-active: color-mix(in srgb, var(--color-state-danger) 70%, var(--color-state-danger-text));
|
|
93
148
|
--ct-button-border: transparent;
|
|
94
149
|
--ct-button-color: var(--color-state-on-solid);
|
|
95
150
|
}
|
|
@@ -138,8 +193,41 @@
|
|
|
138
193
|
justify-content: center;
|
|
139
194
|
}
|
|
140
195
|
|
|
196
|
+
@media (pointer: coarse) {
|
|
197
|
+
.ct-button {
|
|
198
|
+
min-width: var(--control-height-sm);
|
|
199
|
+
min-height: var(--control-height-sm);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.ct-button--link {
|
|
203
|
+
min-height: var(--control-height-sm);
|
|
204
|
+
padding-inline: var(--space-2);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
141
208
|
@media (prefers-reduced-motion: reduce) {
|
|
142
|
-
.ct-button
|
|
209
|
+
.ct-button,
|
|
210
|
+
.ct-button__content,
|
|
211
|
+
.ct-button__loader {
|
|
212
|
+
transition: none;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.ct-button:not(:disabled):not([aria-disabled='true']):not([aria-busy='true']):not([data-loading='true']):active {
|
|
143
216
|
transform: none;
|
|
144
217
|
}
|
|
218
|
+
|
|
219
|
+
.ct-button__loader::before {
|
|
220
|
+
animation: none;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
@media (forced-colors: active) {
|
|
225
|
+
.ct-button {
|
|
226
|
+
border-color: currentColor;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.ct-button__loader::before {
|
|
230
|
+
border-color: currentColor;
|
|
231
|
+
border-inline-end-color: transparent;
|
|
232
|
+
}
|
|
145
233
|
}
|
package/components/card.css
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
.ct-card {
|
|
2
|
-
--ct-card-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
--ct-card-bg: var(--component-card-background);
|
|
3
|
+
--ct-card-border: var(--component-card-border);
|
|
4
|
+
--ct-card-radius: var(--component-card-radius);
|
|
5
|
+
--ct-card-padding: var(--component-card-padding);
|
|
6
|
+
--ct-card-shadow: var(--component-card-shadow);
|
|
7
|
+
--ct-card-shadow-hover: var(--component-card-shadow-hover);
|
|
8
|
+
|
|
9
|
+
background: var(--ct-card-bg);
|
|
10
|
+
border: var(--border-thin) solid var(--ct-card-border);
|
|
11
|
+
border-radius: var(--ct-card-radius);
|
|
6
12
|
padding: var(--ct-card-padding);
|
|
7
|
-
box-shadow: var(--shadow
|
|
13
|
+
box-shadow: var(--ct-card-shadow);
|
|
8
14
|
}
|
|
9
15
|
|
|
10
16
|
.ct-card--sm {
|
|
@@ -47,7 +53,7 @@
|
|
|
47
53
|
@media (hover: hover) {
|
|
48
54
|
:is(a, button, [role='button'], [role='link']).ct-card--interactive:hover {
|
|
49
55
|
border-color: var(--color-border-strong);
|
|
50
|
-
box-shadow: var(--shadow-
|
|
56
|
+
box-shadow: var(--ct-card-shadow-hover);
|
|
51
57
|
}
|
|
52
58
|
}
|
|
53
59
|
|
|
@@ -55,7 +61,7 @@
|
|
|
55
61
|
outline: 2px solid var(--color-focus-ring);
|
|
56
62
|
outline-offset: 2px;
|
|
57
63
|
border-color: var(--color-border-strong);
|
|
58
|
-
box-shadow: var(--shadow-
|
|
64
|
+
box-shadow: var(--ct-card-shadow-hover);
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
.ct-card--interactive[aria-selected='true'] {
|
|
@@ -64,9 +70,20 @@
|
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
.ct-card--interactive[aria-disabled='true'],
|
|
67
|
-
.ct-card--interactive:disabled
|
|
73
|
+
.ct-card--interactive:disabled,
|
|
74
|
+
.ct-card--interactive[data-state='disabled'] {
|
|
68
75
|
opacity: var(--opacity-disabled);
|
|
69
76
|
cursor: not-allowed;
|
|
77
|
+
pointer-events: none;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.ct-card[aria-busy='true'],
|
|
81
|
+
.ct-card[data-state='loading'] {
|
|
82
|
+
cursor: wait;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.ct-card[data-state='error'] {
|
|
86
|
+
border-color: var(--color-state-danger-border);
|
|
70
87
|
}
|
|
71
88
|
|
|
72
89
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -74,3 +91,31 @@
|
|
|
74
91
|
transition: none;
|
|
75
92
|
}
|
|
76
93
|
}
|
|
94
|
+
|
|
95
|
+
/* ── Datum ──
|
|
96
|
+
The reference-line grammar applied to cards. `--datum` adds a corner
|
|
97
|
+
registration mark (like an engineering drawing); the active/current
|
|
98
|
+
state carries the same orange leading edge as list and sidebar items.
|
|
99
|
+
Both are opt-in and additive — they don't change default cards. */
|
|
100
|
+
.ct-card--datum {
|
|
101
|
+
position: relative;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.ct-card--datum::before {
|
|
105
|
+
content: '';
|
|
106
|
+
position: absolute;
|
|
107
|
+
top: calc(-1 * var(--border-thin));
|
|
108
|
+
left: calc(-1 * var(--border-thin));
|
|
109
|
+
width: 18px;
|
|
110
|
+
height: 18px;
|
|
111
|
+
border-top: var(--border-medium) solid var(--color-brand-accent);
|
|
112
|
+
border-left: var(--border-medium) solid var(--color-brand-accent);
|
|
113
|
+
border-top-left-radius: var(--radius-lg);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.ct-card--active,
|
|
117
|
+
.ct-card[data-state='active'] {
|
|
118
|
+
/* The datum: an orange leading edge marks the active/current card,
|
|
119
|
+
consistent with .ct-list__item and .ct-sidebar active states. */
|
|
120
|
+
box-shadow: inset var(--border-thick) 0 0 0 var(--color-brand-accent), var(--ct-card-shadow);
|
|
121
|
+
}
|
package/components/checkbox.css
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
appearance: none;
|
|
14
14
|
width: var(--space-6);
|
|
15
15
|
height: var(--space-6);
|
|
16
|
-
border: var(--border-thin) solid var(--
|
|
16
|
+
border: var(--border-thin) solid var(--ct-control-border);
|
|
17
17
|
background: var(--color-bg-elevated);
|
|
18
18
|
cursor: pointer;
|
|
19
19
|
display: grid;
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
transform var(--duration-fast) var(--easing-standard);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
/*
|
|
27
|
+
/* Construct 44×44 target policy: meets the size in WCAG 2.2 SC 2.5.5
|
|
28
|
+
(AAA) and exceeds the AA minimum in SC 2.5.8. */
|
|
28
29
|
@media (pointer: coarse) {
|
|
29
30
|
.ct-check__input::after,
|
|
30
31
|
.ct-radio__input::after {
|
package/components/chip.css
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/* ─── Datepicker ────────────────────────────────────────────────── */
|
|
2
2
|
|
|
3
3
|
.ct-datepicker {
|
|
4
|
+
--ct-datepicker-selected-surface: color-mix(in srgb, var(--color-brand-primary) 12%, transparent);
|
|
5
|
+
|
|
4
6
|
position: relative;
|
|
5
7
|
display: inline-block;
|
|
6
8
|
}
|
|
@@ -150,7 +152,7 @@
|
|
|
150
152
|
/* ── Range selection ────────────────────────────────────────────── */
|
|
151
153
|
|
|
152
154
|
.ct-datepicker__day[data-in-range] {
|
|
153
|
-
background: var(--
|
|
155
|
+
background: var(--ct-datepicker-selected-surface);
|
|
154
156
|
border-radius: 0;
|
|
155
157
|
}
|
|
156
158
|
|