@neuravision/construct 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +227 -0
  3. package/components/README.md +566 -0
  4. package/components/_keyframes.css +23 -0
  5. package/components/_shared.css +120 -0
  6. package/components/accordion.css +124 -0
  7. package/components/alert.css +67 -0
  8. package/components/avatar.css +127 -0
  9. package/components/badge.css +67 -0
  10. package/components/banner.css +247 -0
  11. package/components/breadcrumbs.css +152 -0
  12. package/components/button.css +145 -0
  13. package/components/card.css +76 -0
  14. package/components/checkbox.css +120 -0
  15. package/components/chip.css +361 -0
  16. package/components/combobox.css +385 -0
  17. package/components/components.css +2 -0
  18. package/components/data-table.css +93 -0
  19. package/components/datepicker.css +268 -0
  20. package/components/divider.css +73 -0
  21. package/components/drawer.css +167 -0
  22. package/components/dropdown.css +401 -0
  23. package/components/empty-state.css +97 -0
  24. package/components/field.css +42 -0
  25. package/components/file-upload.css +111 -0
  26. package/components/icon.css +31 -0
  27. package/components/index.css +49 -0
  28. package/components/input.css +64 -0
  29. package/components/list.css +474 -0
  30. package/components/modal.css +164 -0
  31. package/components/navbar.css +587 -0
  32. package/components/pagination.css +131 -0
  33. package/components/popover.css +231 -0
  34. package/components/progress-bar.css +56 -0
  35. package/components/select-menu.css +267 -0
  36. package/components/select.css +30 -0
  37. package/components/sidebar.css +183 -0
  38. package/components/skeleton.css +38 -0
  39. package/components/skip-link.css +38 -0
  40. package/components/slider.css +305 -0
  41. package/components/spinner.css +72 -0
  42. package/components/switch.css +82 -0
  43. package/components/table.css +139 -0
  44. package/components/tabs.css +147 -0
  45. package/components/textarea.css +16 -0
  46. package/components/toast.css +71 -0
  47. package/components/toggle-group.css +196 -0
  48. package/components/toolbar.css +222 -0
  49. package/components/tooltip.css +124 -0
  50. package/docs/guidelines.md +141 -0
  51. package/foundations.css +299 -0
  52. package/package.json +66 -0
  53. package/tokens/README.md +179 -0
  54. package/tokens/tokens.css +434 -0
  55. package/tokens/tokens.js +1188 -0
  56. package/tokens/tokens.json +810 -0
  57. package/tokens/tokens.ts +1188 -0
@@ -0,0 +1,120 @@
1
+ :root {
2
+ --ct-control-bg: var(--color-bg-elevated);
3
+ --ct-control-bg-hover: var(--color-bg-surface);
4
+ --ct-control-bg-disabled: var(--color-bg-muted);
5
+ --ct-control-border: var(--color-border-default);
6
+ --ct-control-border-hover: var(--color-border-strong);
7
+ --ct-control-border-focus: var(--color-focus-ring);
8
+ --ct-control-text: var(--color-text-primary);
9
+ --ct-control-placeholder: var(--color-text-muted);
10
+ --ct-control-radius: var(--radius-control);
11
+ --ct-control-transition: border-color var(--duration-fast) var(--easing-standard),
12
+ box-shadow var(--duration-fast) var(--easing-standard),
13
+ background var(--duration-fast) var(--easing-standard),
14
+ color var(--duration-fast) var(--easing-standard);
15
+ --ct-button-font-weight: var(--font-weight-semibold);
16
+ --ct-button-radius: var(--radius-control);
17
+ --ct-button-gap: var(--space-3);
18
+ --ct-spinner-duration: 800ms;
19
+ --ct-skeleton-duration: 1400ms;
20
+ --ct-progress-duration: 1500ms;
21
+ --ct-confirmation-icon-size: 44px;
22
+ --ct-dropdown-min-width: 200px;
23
+ --ct-switch-width: 44px;
24
+ --ct-switch-height: 24px;
25
+ --ct-tooltip-bg: var(--color-slate-950);
26
+ --ct-tooltip-color: var(--color-text-inverse);
27
+ --ct-tooltip-radius: var(--radius-sm);
28
+ --ct-tooltip-shadow: var(--shadow-sm);
29
+ --ct-tooltip-max-width: 280px;
30
+ --ct-popover-width: 320px;
31
+ --ct-popover-bg: var(--color-bg-elevated);
32
+ --ct-popover-border: var(--color-border-default);
33
+ --ct-popover-radius: var(--radius-lg);
34
+ --ct-popover-shadow: var(--shadow-lg);
35
+ --ct-date-day-size: var(--control-height-calendar-day);
36
+ --ct-avatar-radius: 50%;
37
+ --ct-avatar-bg: var(--color-bg-muted);
38
+ --ct-avatar-color: var(--color-text-secondary);
39
+ --ct-avatar-status-size: 10px;
40
+ --ct-avatar-group-overlap: -8px;
41
+ }
42
+
43
+ :where(.ct-input, .ct-select, .ct-textarea, .ct-control) {
44
+ width: 100%;
45
+ border: var(--border-thin) solid var(--ct-control-border);
46
+ border-radius: var(--ct-control-radius);
47
+ background: var(--ct-control-bg);
48
+ color: var(--ct-control-text);
49
+ font-size: var(--ct-control-font-size, var(--font-size-md));
50
+ line-height: var(--ct-control-line-height, var(--line-height-md));
51
+ transition: var(--ct-control-transition);
52
+ }
53
+
54
+ :where(.ct-input, .ct-select, .ct-control) {
55
+ height: var(--ct-control-height, var(--control-height-md));
56
+ padding: 0 var(--ct-control-padding-x, var(--space-5));
57
+ }
58
+
59
+ :where(.ct-input, .ct-select, .ct-textarea, .ct-control)::placeholder {
60
+ color: var(--ct-control-placeholder);
61
+ }
62
+
63
+ @media (hover: hover) {
64
+ :where(.ct-input, .ct-select, .ct-textarea, .ct-control):hover {
65
+ border-color: var(--ct-control-border-hover);
66
+ }
67
+ }
68
+
69
+ :where(.ct-input, .ct-select, .ct-textarea, .ct-control):focus-visible {
70
+ border-color: var(--ct-control-border-focus);
71
+ outline: 2px solid var(--color-focus-ring);
72
+ outline-offset: 2px;
73
+ }
74
+
75
+ :where(.ct-input, .ct-select, .ct-textarea, .ct-control):disabled,
76
+ :where(.ct-input, .ct-select, .ct-textarea, .ct-control)[aria-disabled='true'] {
77
+ background: var(--ct-control-bg-disabled);
78
+ border-color: var(--color-border-subtle);
79
+ color: var(--color-text-muted);
80
+ }
81
+
82
+ :where(.ct-input, .ct-select, .ct-textarea, .ct-control)[aria-invalid='true'],
83
+ .ct-field--error :where(.ct-input, .ct-select, .ct-textarea, .ct-control) {
84
+ border-color: var(--color-state-danger);
85
+ }
86
+
87
+ :where(.ct-input, .ct-select, .ct-textarea, .ct-control)[aria-invalid='true']:focus-visible,
88
+ .ct-field--error :where(.ct-input, .ct-select, .ct-textarea, .ct-control):focus-visible {
89
+ border-color: var(--color-state-danger);
90
+ outline-color: var(--color-state-danger);
91
+ }
92
+
93
+ /* ── Touch-target minimums (WCAG 2.5.8: 44×44px) ────────────────── */
94
+
95
+ @media (pointer: coarse) {
96
+ :root {
97
+ --control-height-sm: 44px;
98
+ --control-height-calendar-day: 44px;
99
+ }
100
+ }
101
+
102
+ .ct-control--sm,
103
+ .ct-input--sm,
104
+ .ct-select--sm,
105
+ .ct-textarea--sm {
106
+ --ct-control-height: var(--control-height-sm);
107
+ --ct-control-padding-x: var(--space-4);
108
+ --ct-control-font-size: var(--font-size-sm);
109
+ --ct-control-line-height: var(--line-height-sm);
110
+ }
111
+
112
+ .ct-control--lg,
113
+ .ct-input--lg,
114
+ .ct-select--lg,
115
+ .ct-textarea--lg {
116
+ --ct-control-height: var(--control-height-lg);
117
+ --ct-control-padding-x: var(--space-6);
118
+ --ct-control-font-size: var(--font-size-lg);
119
+ --ct-control-line-height: var(--line-height-lg);
120
+ }
@@ -0,0 +1,124 @@
1
+ /* ── Accordion ────────────────────────────────────── */
2
+
3
+ .ct-accordion {
4
+ --ct-accordion-border: var(--color-border-default);
5
+ display: flex;
6
+ flex-direction: column;
7
+ }
8
+
9
+ .ct-accordion__item {
10
+ border-bottom: var(--border-thin) solid var(--ct-accordion-border);
11
+ }
12
+
13
+ .ct-accordion__item:last-child {
14
+ border-bottom: none;
15
+ }
16
+
17
+ .ct-accordion__trigger {
18
+ display: flex;
19
+ align-items: center;
20
+ justify-content: space-between;
21
+ gap: var(--space-3);
22
+ width: 100%;
23
+ padding: var(--space-4) var(--space-2);
24
+ font-family: inherit;
25
+ font-size: var(--font-size-sm);
26
+ font-weight: var(--font-weight-semibold);
27
+ line-height: var(--line-height-sm);
28
+ color: var(--color-text-primary);
29
+ background: transparent;
30
+ border: none;
31
+ cursor: pointer;
32
+ list-style: none;
33
+ transition: background var(--duration-fast) var(--easing-standard),
34
+ color var(--duration-fast) var(--easing-standard);
35
+ }
36
+
37
+ .ct-accordion__trigger::-webkit-details-marker {
38
+ display: none;
39
+ }
40
+
41
+ .ct-accordion__trigger::marker {
42
+ content: none;
43
+ }
44
+
45
+ @media (hover: hover) {
46
+ .ct-accordion__trigger:hover {
47
+ background: var(--color-bg-surface);
48
+ }
49
+ }
50
+
51
+ .ct-accordion__trigger:focus-visible {
52
+ outline: 2px solid var(--color-focus-ring);
53
+ outline-offset: -2px;
54
+ border-radius: var(--radius-sm);
55
+ }
56
+
57
+ .ct-accordion__heading {
58
+ margin: 0;
59
+ font: inherit;
60
+ }
61
+
62
+ .ct-accordion__icon {
63
+ flex-shrink: 0;
64
+ width: 1em;
65
+ height: 1em;
66
+ transition: transform var(--duration-fast) var(--easing-standard);
67
+ }
68
+
69
+ .ct-accordion__item[open] > .ct-accordion__trigger .ct-accordion__icon {
70
+ transform: rotate(180deg);
71
+ }
72
+
73
+ /* ── Content animation via ::details-content ── */
74
+
75
+ .ct-accordion__item::details-content {
76
+ overflow: hidden;
77
+ block-size: 0;
78
+ transition: block-size var(--duration-fast) var(--easing-standard),
79
+ content-visibility var(--duration-fast) allow-discrete;
80
+ }
81
+
82
+ .ct-accordion__item[open]::details-content {
83
+ block-size: max-content;
84
+ }
85
+
86
+ .ct-accordion__content {
87
+ padding: 0 var(--space-2) var(--space-4);
88
+ font-size: var(--font-size-sm);
89
+ line-height: var(--line-height-md);
90
+ color: var(--color-text-secondary);
91
+ }
92
+
93
+ /* ── Bordered variant ── */
94
+
95
+ .ct-accordion--bordered .ct-accordion__item {
96
+ border: var(--border-thin) solid var(--ct-accordion-border);
97
+ border-radius: var(--radius-md);
98
+ margin-bottom: var(--space-2);
99
+ }
100
+
101
+ .ct-accordion--bordered .ct-accordion__item:last-child {
102
+ margin-bottom: 0;
103
+ border-bottom: var(--border-thin) solid var(--ct-accordion-border);
104
+ }
105
+
106
+ .ct-accordion--bordered .ct-accordion__trigger {
107
+ padding: var(--space-4);
108
+ border-radius: var(--radius-md);
109
+ }
110
+
111
+ .ct-accordion--bordered .ct-accordion__item[open] > .ct-accordion__trigger {
112
+ border-radius: var(--radius-md) var(--radius-md) 0 0;
113
+ }
114
+
115
+ .ct-accordion--bordered .ct-accordion__content {
116
+ padding: 0 var(--space-4) var(--space-4);
117
+ }
118
+
119
+ @media (prefers-reduced-motion: reduce) {
120
+ .ct-accordion__icon,
121
+ .ct-accordion__item::details-content {
122
+ transition: none;
123
+ }
124
+ }
@@ -0,0 +1,67 @@
1
+ .ct-alert {
2
+ --ct-alert-bg: var(--color-bg-muted);
3
+ --ct-alert-border: var(--color-border-subtle);
4
+ --ct-alert-accent: var(--color-brand-primary);
5
+
6
+ display: grid;
7
+ grid-template-columns: auto 1fr;
8
+ gap: var(--space-4);
9
+ padding: var(--space-5) var(--space-6);
10
+ border-radius: var(--radius-md);
11
+ border: var(--border-thin) solid var(--ct-alert-border);
12
+ background: var(--ct-alert-bg);
13
+ color: var(--color-text-primary);
14
+ }
15
+
16
+ .ct-alert__icon {
17
+ width: var(--icon-md);
18
+ height: var(--icon-md);
19
+ display: inline-flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+ color: var(--ct-alert-accent);
23
+ }
24
+
25
+ .ct-alert__content {
26
+ display: grid;
27
+ gap: var(--space-2);
28
+ }
29
+
30
+ .ct-alert__title {
31
+ font-weight: var(--font-weight-semibold);
32
+ }
33
+
34
+ .ct-alert__description {
35
+ color: var(--color-text-secondary);
36
+ font-size: var(--font-size-sm);
37
+ }
38
+
39
+ .ct-alert__actions {
40
+ display: flex;
41
+ flex-wrap: wrap;
42
+ gap: var(--space-2);
43
+ }
44
+
45
+ .ct-alert[data-variant='info'] {
46
+ --ct-alert-bg: var(--color-state-info-surface);
47
+ --ct-alert-border: var(--color-state-info-border);
48
+ --ct-alert-accent: var(--color-state-info);
49
+ }
50
+
51
+ .ct-alert[data-variant='success'] {
52
+ --ct-alert-bg: var(--color-state-success-surface);
53
+ --ct-alert-border: var(--color-state-success-border);
54
+ --ct-alert-accent: var(--color-state-success);
55
+ }
56
+
57
+ .ct-alert[data-variant='warning'] {
58
+ --ct-alert-bg: var(--color-state-warning-surface);
59
+ --ct-alert-border: var(--color-state-warning-border);
60
+ --ct-alert-accent: var(--color-state-warning-text);
61
+ }
62
+
63
+ .ct-alert[data-variant='danger'] {
64
+ --ct-alert-bg: var(--color-state-danger-surface);
65
+ --ct-alert-border: var(--color-state-danger-border);
66
+ --ct-alert-accent: var(--color-state-danger);
67
+ }
@@ -0,0 +1,127 @@
1
+ /* ── Avatar ── */
2
+
3
+ .ct-avatar {
4
+ --ct-avatar-size: 32px;
5
+ --ct-avatar-font-size: var(--font-size-sm);
6
+
7
+ position: relative;
8
+ display: inline-flex;
9
+ align-items: center;
10
+ justify-content: center;
11
+ width: var(--ct-avatar-size);
12
+ height: var(--ct-avatar-size);
13
+ border-radius: var(--ct-avatar-radius);
14
+ background: var(--ct-avatar-bg);
15
+ color: var(--ct-avatar-color);
16
+ font-size: var(--ct-avatar-font-size);
17
+ font-weight: var(--font-weight-semibold);
18
+ line-height: 1;
19
+ flex-shrink: 0;
20
+ overflow: hidden;
21
+ user-select: none;
22
+ }
23
+
24
+ .ct-avatar--sm {
25
+ --ct-avatar-size: 24px;
26
+ --ct-avatar-font-size: var(--font-size-xs);
27
+ }
28
+
29
+ .ct-avatar--lg {
30
+ --ct-avatar-size: 48px;
31
+ --ct-avatar-font-size: var(--font-size-lg);
32
+ }
33
+
34
+ .ct-avatar--xl {
35
+ --ct-avatar-size: 64px;
36
+ --ct-avatar-font-size: var(--font-size-xl);
37
+ }
38
+
39
+ .ct-avatar__image {
40
+ width: 100%;
41
+ height: 100%;
42
+ object-fit: cover;
43
+ border-radius: inherit;
44
+ }
45
+
46
+ .ct-avatar__initials {
47
+ display: flex;
48
+ align-items: center;
49
+ justify-content: center;
50
+ width: 100%;
51
+ height: 100%;
52
+ text-transform: uppercase;
53
+ letter-spacing: var(--letter-spacing-wide);
54
+ }
55
+
56
+ .ct-avatar__icon {
57
+ display: flex;
58
+ align-items: center;
59
+ justify-content: center;
60
+ width: 60%;
61
+ height: 60%;
62
+ }
63
+
64
+ .ct-avatar__icon svg {
65
+ width: 100%;
66
+ height: 100%;
67
+ }
68
+
69
+ .ct-avatar__status {
70
+ position: absolute;
71
+ inset-block-end: 0;
72
+ inset-inline-end: 0;
73
+ width: var(--ct-avatar-status-size);
74
+ height: var(--ct-avatar-status-size);
75
+ border-radius: 50%;
76
+ border: 2px solid var(--color-bg-canvas);
77
+ background: var(--color-text-muted);
78
+ }
79
+
80
+ .ct-avatar__status[data-status='online'] {
81
+ background: var(--color-state-success);
82
+ }
83
+
84
+ .ct-avatar__status[data-status='offline'] {
85
+ background: var(--color-text-muted);
86
+ }
87
+
88
+ .ct-avatar__status[data-status='busy'] {
89
+ background: var(--color-state-danger);
90
+ }
91
+
92
+ .ct-avatar__status[data-status='away'] {
93
+ background: var(--color-state-warning);
94
+ }
95
+
96
+ /* ── Avatar Group ── */
97
+
98
+ .ct-avatar-group {
99
+ display: inline-flex;
100
+ flex-direction: row-reverse;
101
+ align-items: center;
102
+ }
103
+
104
+ .ct-avatar-group .ct-avatar {
105
+ border: 2px solid var(--color-bg-canvas);
106
+ margin-inline-start: var(--ct-avatar-group-overlap);
107
+ }
108
+
109
+ .ct-avatar-group .ct-avatar:last-child {
110
+ margin-inline-start: 0;
111
+ }
112
+
113
+ .ct-avatar-group__overflow {
114
+ display: inline-flex;
115
+ align-items: center;
116
+ justify-content: center;
117
+ width: var(--ct-avatar-size, 32px);
118
+ height: var(--ct-avatar-size, 32px);
119
+ border-radius: var(--ct-avatar-radius);
120
+ background: var(--color-bg-muted);
121
+ color: var(--color-text-secondary);
122
+ font-size: var(--font-size-xs);
123
+ font-weight: var(--font-weight-semibold);
124
+ border: 2px solid var(--color-bg-canvas);
125
+ margin-inline-start: var(--ct-avatar-group-overlap);
126
+ flex-shrink: 0;
127
+ }
@@ -0,0 +1,67 @@
1
+ .ct-badge {
2
+ --ct-badge-bg: var(--color-bg-muted);
3
+ --ct-badge-border: var(--color-border-subtle);
4
+ --ct-badge-color: var(--color-text-secondary);
5
+ --ct-badge-accent: var(--ct-badge-color);
6
+
7
+ display: inline-flex;
8
+ align-items: center;
9
+ gap: var(--space-2);
10
+ padding: var(--space-1) var(--space-3);
11
+ border-radius: var(--radius-pill);
12
+ border: var(--border-thin) solid var(--ct-badge-border);
13
+ background: var(--ct-badge-bg);
14
+ color: var(--ct-badge-color);
15
+ font-size: var(--font-size-xs);
16
+ font-weight: var(--font-weight-semibold);
17
+ line-height: var(--line-height-xs);
18
+ white-space: nowrap;
19
+ }
20
+
21
+ .ct-badge--icon {
22
+ padding-inline-end: var(--space-4);
23
+ }
24
+
25
+ .ct-badge__icon {
26
+ display: inline-flex;
27
+ align-items: center;
28
+ justify-content: center;
29
+ width: 1em;
30
+ height: 1em;
31
+ color: var(--ct-badge-accent);
32
+ }
33
+
34
+ .ct-badge__dot {
35
+ width: 8px;
36
+ height: 8px;
37
+ border-radius: var(--radius-round);
38
+ background: var(--ct-badge-accent);
39
+ }
40
+
41
+ .ct-badge--info {
42
+ --ct-badge-bg: var(--color-state-info-surface);
43
+ --ct-badge-border: var(--color-state-info-border);
44
+ --ct-badge-color: var(--color-text-primary);
45
+ --ct-badge-accent: var(--color-state-info);
46
+ }
47
+
48
+ .ct-badge--success {
49
+ --ct-badge-bg: var(--color-state-success-surface);
50
+ --ct-badge-border: var(--color-state-success-border);
51
+ --ct-badge-color: var(--color-text-primary);
52
+ --ct-badge-accent: var(--color-state-success);
53
+ }
54
+
55
+ .ct-badge--warning {
56
+ --ct-badge-bg: var(--color-state-warning-surface);
57
+ --ct-badge-border: var(--color-state-warning-border);
58
+ --ct-badge-color: var(--color-text-primary);
59
+ --ct-badge-accent: var(--color-state-warning-text);
60
+ }
61
+
62
+ .ct-badge--danger {
63
+ --ct-badge-bg: var(--color-state-danger-surface);
64
+ --ct-badge-border: var(--color-state-danger-border);
65
+ --ct-badge-color: var(--color-text-primary);
66
+ --ct-badge-accent: var(--color-state-danger);
67
+ }