@eagami/ui 4.4.0 → 4.5.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/README.md +1 -1
- package/fesm2022/eagami-ui.mjs +364 -20
- package/fesm2022/eagami-ui.mjs.map +1 -1
- package/package.json +19 -4
- package/types/eagami-ui.d.ts +1 -1
- package/src/styles/_mixins.scss +0 -68
- package/src/styles/_reset.scss +0 -62
- package/src/styles/_tooltip.scss +0 -39
- package/src/styles/eagami-ui.scss +0 -6
- package/src/styles/tokens/_colors.scss +0 -265
- package/src/styles/tokens/_elevation.scss +0 -87
- package/src/styles/tokens/_index.scss +0 -6
- package/src/styles/tokens/_motion.scss +0 -37
- package/src/styles/tokens/_shape.scss +0 -23
- package/src/styles/tokens/_spacing.scss +0 -73
- package/src/styles/tokens/_typography.scss +0 -147
package/package.json
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eagami/ui",
|
|
3
|
-
"version": "4.
|
|
4
|
-
"description": "Lightweight, accessible Angular UI component library built on CSS custom properties",
|
|
3
|
+
"version": "4.5.1",
|
|
4
|
+
"description": "Lightweight, accessible, themeable Angular UI component library and icon set built on CSS custom properties",
|
|
5
5
|
"author": "Michal Wiraszka <michal@eagami.com>",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"angular",
|
|
9
|
+
"angular-components",
|
|
9
10
|
"ui",
|
|
11
|
+
"components",
|
|
10
12
|
"component-library",
|
|
11
13
|
"design-system",
|
|
12
|
-
"accessible"
|
|
14
|
+
"accessible",
|
|
15
|
+
"a11y",
|
|
16
|
+
"dark-mode",
|
|
17
|
+
"theming",
|
|
18
|
+
"icons",
|
|
19
|
+
"signals",
|
|
20
|
+
"standalone",
|
|
21
|
+
"typescript",
|
|
22
|
+
"css-variables"
|
|
13
23
|
],
|
|
14
24
|
"homepage": "https://eagami.com/ui",
|
|
15
25
|
"repository": {
|
|
@@ -41,5 +51,10 @@
|
|
|
41
51
|
"default": "./fesm2022/eagami-ui.mjs"
|
|
42
52
|
}
|
|
43
53
|
},
|
|
44
|
-
"type": "module"
|
|
54
|
+
"type": "module",
|
|
55
|
+
"files": [
|
|
56
|
+
"fesm2022",
|
|
57
|
+
"types",
|
|
58
|
+
"README.md"
|
|
59
|
+
]
|
|
45
60
|
}
|
package/types/eagami-ui.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import * as _eagami_ui from '@eagami/ui';
|
|
|
7
7
|
* BCP 47 locale tags supported out of the box. Consumers select one of these
|
|
8
8
|
* via `provideEagamiUi({ locale })` or `EagamiI18nService.setLocale()`.
|
|
9
9
|
*/
|
|
10
|
-
type EagamiLocale = 'en' | '
|
|
10
|
+
type EagamiLocale = 'en' | 'de' | 'es-ES' | 'fr-FR' | 'is' | 'nl' | 'pl' | 'pt-BR' | 'el' | 'ru' | 'uk' | 'zh-CN';
|
|
11
11
|
/**
|
|
12
12
|
* Display metadata for a built-in locale: the language's name in its own
|
|
13
13
|
* language and a representative flag emoji.
|
package/src/styles/_mixins.scss
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
// Shared SCSS mixins for the library. Consume from a component stylesheet with:
|
|
2
|
-
// @use '../../styles/mixins' as ea;
|
|
3
|
-
// .ea-foo__close { @include ea.icon-button; }
|
|
4
|
-
|
|
5
|
-
// Standard focus indicator. The ring is a soft box-shadow halo, but box-shadow
|
|
6
|
-
// is dropped in forced-colors (Windows High Contrast) mode, which would leave
|
|
7
|
-
// keyboard users with no visible focus. Pair the halo with a real outline that
|
|
8
|
-
// only renders in forced-colors so the ring survives there. Pass the full
|
|
9
|
-
// box-shadow value to compose the ring with an existing shadow.
|
|
10
|
-
@mixin focus-ring($ring: var(--shadow-focus-ring)) {
|
|
11
|
-
box-shadow: $ring;
|
|
12
|
-
|
|
13
|
-
@media (forced-colors: active) {
|
|
14
|
-
outline: 2px solid Highlight;
|
|
15
|
-
outline-offset: 2px;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Floating surfaces (menus, dialogs, popovers, toasts) lean on elevation shadow
|
|
20
|
-
// for their boundary, but shadows are dropped in forced-colors mode. Add a
|
|
21
|
-
// hairline border there so the surface stays separated from the content behind.
|
|
22
|
-
@mixin elevated-surface-border {
|
|
23
|
-
@media (forced-colors: active) {
|
|
24
|
-
border: 1px solid CanvasText;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Standard icon button: clear, close/dismiss, password-toggle, nav, etc. The box
|
|
29
|
-
// is `--ea-icon-button-size` (em) so it scales with the host component's size and
|
|
30
|
-
// is consistent across components at a given size tier. The glyph is enlarged so
|
|
31
|
-
// it reads clearly inside the box regardless of how much padding the icon's own
|
|
32
|
-
// viewBox carries (the feather `x`, for instance, only fills its middle half).
|
|
33
|
-
@mixin icon-button {
|
|
34
|
-
display: inline-flex;
|
|
35
|
-
align-items: center;
|
|
36
|
-
justify-content: center;
|
|
37
|
-
flex-shrink: 0;
|
|
38
|
-
width: var(--ea-icon-button-size, 1.75em);
|
|
39
|
-
height: var(--ea-icon-button-size, 1.75em);
|
|
40
|
-
padding: 0;
|
|
41
|
-
border: none;
|
|
42
|
-
border-radius: var(--radius-sm);
|
|
43
|
-
background: none;
|
|
44
|
-
color: var(--color-text-secondary);
|
|
45
|
-
cursor: pointer;
|
|
46
|
-
transition: var(--transition-colors);
|
|
47
|
-
|
|
48
|
-
// Glyph sized via font-size (not width) so it overrides the icon's inline 1em
|
|
49
|
-
// host size and still scales with the box.
|
|
50
|
-
> * {
|
|
51
|
-
font-size: 1.25em;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
&:hover {
|
|
55
|
-
background-color: var(--color-state-hover);
|
|
56
|
-
color: var(--color-text-primary);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
&:focus-visible {
|
|
60
|
-
outline: none;
|
|
61
|
-
@include focus-ring;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
&:disabled {
|
|
65
|
-
cursor: not-allowed;
|
|
66
|
-
opacity: 0.5;
|
|
67
|
-
}
|
|
68
|
-
}
|
package/src/styles/_reset.scss
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
*,
|
|
2
|
-
*::before,
|
|
3
|
-
*::after {
|
|
4
|
-
box-sizing: border-box;
|
|
5
|
-
margin: 0;
|
|
6
|
-
padding: 0;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
html {
|
|
10
|
-
font-size: 16px;
|
|
11
|
-
-webkit-text-size-adjust: 100%;
|
|
12
|
-
tab-size: 4;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
body {
|
|
16
|
-
font-family: var(--font-family-sans);
|
|
17
|
-
font-size: var(--font-size-md);
|
|
18
|
-
line-height: var(--line-height-normal);
|
|
19
|
-
color: var(--color-text-primary);
|
|
20
|
-
background-color: var(--color-bg-canvas);
|
|
21
|
-
-webkit-font-smoothing: antialiased;
|
|
22
|
-
-moz-osx-font-smoothing: grayscale;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
img,
|
|
26
|
-
svg,
|
|
27
|
-
video {
|
|
28
|
-
display: block;
|
|
29
|
-
max-width: 100%;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
button,
|
|
33
|
-
input,
|
|
34
|
-
optgroup,
|
|
35
|
-
select,
|
|
36
|
-
textarea {
|
|
37
|
-
font-family: inherit;
|
|
38
|
-
font-size: 100%;
|
|
39
|
-
font-weight: inherit;
|
|
40
|
-
line-height: inherit;
|
|
41
|
-
color: inherit;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
button {
|
|
45
|
-
cursor: pointer;
|
|
46
|
-
background: transparent;
|
|
47
|
-
border: none;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
a {
|
|
51
|
-
color: var(--color-text-link);
|
|
52
|
-
text-decoration: underline;
|
|
53
|
-
|
|
54
|
-
&:hover {
|
|
55
|
-
color: var(--color-text-link-hover);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
:focus-visible {
|
|
60
|
-
outline: var(--border-width-medium) solid var(--color-border-focus);
|
|
61
|
-
outline-offset: 2px;
|
|
62
|
-
}
|
package/src/styles/_tooltip.scss
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
@use 'mixins' as ea;
|
|
2
|
-
|
|
3
|
-
// Guard against "sticky hover" on touch devices, which fire `mouseenter` on tap
|
|
4
|
-
// but never the matching `mouseleave`. The directive gates pointer listeners on
|
|
5
|
-
// `(hover: hover)`, but if a tooltip ever slips through keep it invisible on touch.
|
|
6
|
-
.ea-tooltip {
|
|
7
|
-
z-index: var(--z-index-tooltip);
|
|
8
|
-
position: absolute;
|
|
9
|
-
padding: var(--space-1-5) var(--space-2-5);
|
|
10
|
-
font-family: var(--font-family-sans);
|
|
11
|
-
font-size: var(--font-size-xs);
|
|
12
|
-
font-weight: var(--font-weight-medium);
|
|
13
|
-
line-height: var(--line-height-normal);
|
|
14
|
-
white-space: nowrap;
|
|
15
|
-
// When a max-width switches the bubble to multi-line, break long unbreakable
|
|
16
|
-
// strings (URLs, tokens) instead of letting them overflow the bubble.
|
|
17
|
-
overflow-wrap: anywhere;
|
|
18
|
-
border: var(--border-width-thin) solid var(--color-tooltip-border);
|
|
19
|
-
border-radius: var(--radius-md);
|
|
20
|
-
background-color: var(--color-tooltip-surface);
|
|
21
|
-
color: var(--color-neutral-0);
|
|
22
|
-
pointer-events: none;
|
|
23
|
-
animation: ea-tooltip-fade-in var(--duration-fast) var(--ease-out);
|
|
24
|
-
@include ea.elevated-surface-border;
|
|
25
|
-
|
|
26
|
-
@media (hover: none) {
|
|
27
|
-
display: none;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
@keyframes ea-tooltip-fade-in {
|
|
32
|
-
from {
|
|
33
|
-
opacity: 0;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
to {
|
|
37
|
-
opacity: 1;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
// Every token-declaring selector is wrapped in :where() so it contributes zero
|
|
2
|
-
// specificity. A consumer's own root-level token override (specificity 0,1,0)
|
|
3
|
-
// then wins in light mode, OS-dark, and forced dark alike, independent of
|
|
4
|
-
// stylesheet load order. The library's own light-to-dark switching still
|
|
5
|
-
// resolves correctly by source order, since the dark blocks come after the
|
|
6
|
-
// light ones at equal (zero) specificity.
|
|
7
|
-
:where(:root) {
|
|
8
|
-
--color-primary-50: #ecf3f9;
|
|
9
|
-
--color-primary-100: #d1e3f0;
|
|
10
|
-
--color-primary-200: #abcbe3;
|
|
11
|
-
--color-primary-300: #7dafd4;
|
|
12
|
-
--color-primary-400: #4b91c3;
|
|
13
|
-
--color-primary-500: #3674a1;
|
|
14
|
-
--color-primary-600: #2a5b7e;
|
|
15
|
-
--color-primary-700: #204560;
|
|
16
|
-
--color-primary-800: #162f41;
|
|
17
|
-
--color-primary-900: #0d1c26;
|
|
18
|
-
|
|
19
|
-
--color-secondary-50: #f2eff5;
|
|
20
|
-
--color-secondary-100: #dfd9e8;
|
|
21
|
-
--color-secondary-200: #c4b9d5;
|
|
22
|
-
--color-secondary-300: #a493be;
|
|
23
|
-
--color-secondary-400: #8169a5;
|
|
24
|
-
--color-secondary-500: #665086;
|
|
25
|
-
--color-secondary-600: #503f69;
|
|
26
|
-
--color-secondary-700: #3d3050;
|
|
27
|
-
--color-secondary-800: #292136;
|
|
28
|
-
--color-secondary-900: #181320;
|
|
29
|
-
|
|
30
|
-
--color-neutral-0: #ffffff;
|
|
31
|
-
--color-neutral-50: #f9fafb;
|
|
32
|
-
--color-neutral-100: #f3f4f6;
|
|
33
|
-
--color-neutral-200: #e5e7eb;
|
|
34
|
-
--color-neutral-300: #d1d5db;
|
|
35
|
-
--color-neutral-400: #9ca3af;
|
|
36
|
-
--color-neutral-500: #6b7280;
|
|
37
|
-
--color-neutral-600: #4b5563;
|
|
38
|
-
--color-neutral-700: #374151;
|
|
39
|
-
--color-neutral-800: #1f2937;
|
|
40
|
-
--color-neutral-900: #111827;
|
|
41
|
-
--color-neutral-950: #030712;
|
|
42
|
-
|
|
43
|
-
--color-success-50: #f0fdf4;
|
|
44
|
-
--color-success-100: #dcfce7;
|
|
45
|
-
--color-success-200: #bbf7d0;
|
|
46
|
-
--color-success-500: #22c55e;
|
|
47
|
-
--color-success-600: #16a34a;
|
|
48
|
-
--color-success-700: #15803d;
|
|
49
|
-
|
|
50
|
-
--color-warning-50: #fffbeb;
|
|
51
|
-
--color-warning-100: #fef3c7;
|
|
52
|
-
--color-warning-200: #fde68a;
|
|
53
|
-
--color-warning-500: #f59e0b;
|
|
54
|
-
--color-warning-600: #d97706;
|
|
55
|
-
--color-warning-700: #b45309;
|
|
56
|
-
|
|
57
|
-
--color-error-50: #fef2f2;
|
|
58
|
-
--color-error-100: #fee2e2;
|
|
59
|
-
--color-error-200: #fecaca;
|
|
60
|
-
--color-error-500: #ef4444;
|
|
61
|
-
--color-error-600: #dc2626;
|
|
62
|
-
--color-error-700: #b91c1c;
|
|
63
|
-
|
|
64
|
-
--color-info-50: #ecfeff;
|
|
65
|
-
--color-info-100: #cffafe;
|
|
66
|
-
--color-info-200: #a5f3fc;
|
|
67
|
-
--color-info-500: #06b6d4;
|
|
68
|
-
--color-info-600: #0891b2;
|
|
69
|
-
--color-info-700: #0e7490;
|
|
70
|
-
|
|
71
|
-
--color-text-primary: var(--color-neutral-900);
|
|
72
|
-
--color-text-secondary: var(--color-neutral-600);
|
|
73
|
-
--color-text-tertiary: var(--color-neutral-400);
|
|
74
|
-
--color-text-disabled: var(--color-neutral-400);
|
|
75
|
-
--color-text-inverse: var(--color-neutral-0);
|
|
76
|
-
--color-text-link: var(--color-primary-600);
|
|
77
|
-
--color-text-link-hover: var(--color-primary-800);
|
|
78
|
-
|
|
79
|
-
// Two-tier surfaces: bg-canvas is the page, bg-base is component surfaces on
|
|
80
|
-
// it (inputs, cards, accordion, popovers). In dark mode bg-base lifts above
|
|
81
|
-
// bg-canvas so surfaces don't vanish into the page.
|
|
82
|
-
--color-bg-canvas: var(--color-neutral-0);
|
|
83
|
-
--color-bg-base: var(--color-neutral-0);
|
|
84
|
-
--color-bg-subtle: var(--color-neutral-50);
|
|
85
|
-
--color-bg-stripe: var(--color-neutral-50);
|
|
86
|
-
// Zebra-stripe fill for table rows: a mid-tone between the base row and the
|
|
87
|
-
// header tint so striped rows read as lighter than the header, not identical to
|
|
88
|
-
// it. Dark mode overrides the ratio to stay equally subtle.
|
|
89
|
-
--color-bg-stripe-subtle: color-mix(
|
|
90
|
-
in srgb,
|
|
91
|
-
var(--color-bg-base) 30%,
|
|
92
|
-
var(--color-bg-stripe)
|
|
93
|
-
);
|
|
94
|
-
--color-bg-muted: var(--color-neutral-100);
|
|
95
|
-
// Soft neutral fill for placeholder surfaces (e.g. avatar initials) when no
|
|
96
|
-
// image is set; light enough to sit gently on a white page
|
|
97
|
-
--color-bg-emphasis: var(--color-neutral-100);
|
|
98
|
-
--color-bg-elevated: var(--color-neutral-0);
|
|
99
|
-
--color-bg-overlay: rgba(0, 0, 0, 0.5);
|
|
100
|
-
|
|
101
|
-
// Tooltips float over arbitrary content, so their surface is a unique tone that
|
|
102
|
-
// never matches a page or palette colour in either theme; the translucent
|
|
103
|
-
// hairline border separates it from same-tone backgrounds.
|
|
104
|
-
--color-tooltip-surface: #1a1b21;
|
|
105
|
-
--color-tooltip-border: rgba(255, 255, 255, 0.15);
|
|
106
|
-
|
|
107
|
-
// Interactive lift layers for hover and active/selected fills. Light surfaces
|
|
108
|
-
// are all near-white and never collapse onto these shades, so solid muted
|
|
109
|
-
// tones read cleanly. Dark mode swaps them for translucent washes (see the
|
|
110
|
-
// dark overrides) because its surfaces all collapse onto the same neutrals,
|
|
111
|
-
// where a solid fill would vanish into whatever it sits on.
|
|
112
|
-
--color-state-hover: var(--color-neutral-100);
|
|
113
|
-
--color-state-active: var(--color-neutral-200);
|
|
114
|
-
|
|
115
|
-
--color-border-subtle: var(--color-neutral-200);
|
|
116
|
-
--color-border-default: var(--color-neutral-200);
|
|
117
|
-
--color-border-strong: var(--color-neutral-400);
|
|
118
|
-
--color-divider: var(--color-border-subtle);
|
|
119
|
-
--color-border-focus: var(--color-primary-500);
|
|
120
|
-
|
|
121
|
-
// brand-default/-hover/-active are the brand colour as a surface (solid bg
|
|
122
|
-
// under white text); needs 4.5:1 vs white. brand-text is the brand colour as
|
|
123
|
-
// a foreground on a non-brand surface; needs 4.5:1 vs bg-base and flips
|
|
124
|
-
// lighter in dark mode.
|
|
125
|
-
--color-brand-default: var(--color-primary-600);
|
|
126
|
-
--color-brand-hover: var(--color-primary-700);
|
|
127
|
-
--color-brand-active: var(--color-primary-800);
|
|
128
|
-
--color-brand-text: var(--color-primary-700);
|
|
129
|
-
--color-brand-subtle: var(--color-primary-50);
|
|
130
|
-
--color-brand-muted: var(--color-primary-100);
|
|
131
|
-
|
|
132
|
-
--color-brand-secondary-default: var(--color-secondary-500);
|
|
133
|
-
--color-brand-secondary-hover: var(--color-secondary-600);
|
|
134
|
-
--color-brand-secondary-active: var(--color-secondary-700);
|
|
135
|
-
--color-brand-secondary-subtle: var(--color-secondary-50);
|
|
136
|
-
--color-brand-secondary-muted: var(--color-secondary-100);
|
|
137
|
-
|
|
138
|
-
// *-text is the status hue as a foreground on its own *-subtle/-muted wash
|
|
139
|
-
// (badge, tag, toast). It needs 4.5:1 vs that wash and flips lighter in dark
|
|
140
|
-
// mode, mirroring --color-brand-text.
|
|
141
|
-
--color-success-default: var(--color-success-600);
|
|
142
|
-
--color-success-subtle: var(--color-success-50);
|
|
143
|
-
--color-success-muted: var(--color-success-100);
|
|
144
|
-
--color-success-text: var(--color-success-700);
|
|
145
|
-
|
|
146
|
-
--color-warning-default: var(--color-warning-600);
|
|
147
|
-
--color-warning-subtle: var(--color-warning-50);
|
|
148
|
-
--color-warning-muted: var(--color-warning-100);
|
|
149
|
-
--color-warning-text: var(--color-warning-700);
|
|
150
|
-
|
|
151
|
-
--color-error-default: var(--color-error-600);
|
|
152
|
-
--color-error-subtle: var(--color-error-50);
|
|
153
|
-
--color-error-muted: var(--color-error-100);
|
|
154
|
-
--color-error-text: var(--color-error-700);
|
|
155
|
-
|
|
156
|
-
--color-info-default: var(--color-info-600);
|
|
157
|
-
--color-info-subtle: var(--color-info-50);
|
|
158
|
-
--color-info-muted: var(--color-info-100);
|
|
159
|
-
--color-info-text: var(--color-info-700);
|
|
160
|
-
|
|
161
|
-
// Pure RGB primaries for the picker's hue wheel and saturation/value
|
|
162
|
-
// gradient. Intrinsic to the picker, not themeable; kept here so component
|
|
163
|
-
// SCSS stays literal-free.
|
|
164
|
-
--color-picker-hue-red: #ff0000;
|
|
165
|
-
--color-picker-hue-yellow: #ffff00;
|
|
166
|
-
--color-picker-hue-green: #00ff00;
|
|
167
|
-
--color-picker-hue-cyan: #00ffff;
|
|
168
|
-
--color-picker-hue-blue: #0000ff;
|
|
169
|
-
--color-picker-hue-magenta: #ff00ff;
|
|
170
|
-
--color-picker-sv-white: #ffffff;
|
|
171
|
-
--color-picker-sv-black: #000000;
|
|
172
|
-
--color-picker-thumb-halo: rgba(0, 0, 0, 0.25);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Dark mode: applied when the OS prefers dark, unless forced light via
|
|
176
|
-
// `<html data-theme="light">`. `<html data-theme="dark">` forces dark.
|
|
177
|
-
@mixin dark-color-tokens {
|
|
178
|
-
--color-text-primary: var(--color-neutral-50);
|
|
179
|
-
--color-text-secondary: var(--color-neutral-300);
|
|
180
|
-
--color-text-tertiary: var(--color-neutral-500);
|
|
181
|
-
--color-text-disabled: var(--color-neutral-500);
|
|
182
|
-
--color-text-inverse: var(--color-neutral-900);
|
|
183
|
-
--color-text-link: var(--color-primary-300);
|
|
184
|
-
--color-text-link-hover: var(--color-primary-100);
|
|
185
|
-
|
|
186
|
-
// Canvas is the deepest page tone; bg-base and up lift component surfaces,
|
|
187
|
-
// striped rows, floating surfaces, and hover states above it.
|
|
188
|
-
--color-bg-canvas: var(--color-neutral-950);
|
|
189
|
-
--color-bg-base: var(--color-neutral-800);
|
|
190
|
-
--color-bg-subtle: var(--color-neutral-700);
|
|
191
|
-
--color-bg-stripe: var(--color-neutral-900);
|
|
192
|
-
// The dark base-to-stripe gap reads stronger than the light one, so weight the
|
|
193
|
-
// stripe mix toward the base row to keep zebra striping subtle.
|
|
194
|
-
--color-bg-stripe-subtle: color-mix(
|
|
195
|
-
in srgb,
|
|
196
|
-
var(--color-bg-base) 62.5%,
|
|
197
|
-
var(--color-bg-stripe)
|
|
198
|
-
);
|
|
199
|
-
--color-bg-elevated: var(--color-neutral-700);
|
|
200
|
-
// Opaque muted surface for static fills (disabled fields, slider/progress
|
|
201
|
-
// tracks, skeletons). Hover/active fills route through the translucent
|
|
202
|
-
// --color-state-* tokens instead, so they never collide with this shade.
|
|
203
|
-
--color-bg-muted: var(--color-neutral-700);
|
|
204
|
-
--color-bg-emphasis: var(--color-neutral-600);
|
|
205
|
-
|
|
206
|
-
// White wash so an interactive lift reads on any dark surface, including the
|
|
207
|
-
// neutral-700 tier where bg-muted/-subtle/-elevated all coincide. This is the
|
|
208
|
-
// fix that lets dropdown/menu/dialog hovers lift off their elevated surfaces.
|
|
209
|
-
--color-state-hover: rgba(255, 255, 255, 0.08);
|
|
210
|
-
--color-state-active: rgba(255, 255, 255, 0.14);
|
|
211
|
-
|
|
212
|
-
// Borders stay clear of every bg-* shade so they stay visible. subtle mixes
|
|
213
|
-
// neutral-700/-800 to sit between card and cell backgrounds; default can't go
|
|
214
|
-
// darker without colliding with bg-subtle/-elevated (both neutral-700).
|
|
215
|
-
--color-border-subtle: color-mix(
|
|
216
|
-
in srgb,
|
|
217
|
-
var(--color-neutral-700),
|
|
218
|
-
var(--color-neutral-800)
|
|
219
|
-
);
|
|
220
|
-
--color-border-default: var(--color-neutral-400);
|
|
221
|
-
--color-border-strong: var(--color-neutral-300);
|
|
222
|
-
// Dividers read as barely-there against dark surfaces at border-subtle, so
|
|
223
|
-
// they step one neutral lighter for a visible-but-quiet rule.
|
|
224
|
-
--color-divider: var(--color-neutral-600);
|
|
225
|
-
|
|
226
|
-
// Surface roles step one shade lighter than light mode so the button clears
|
|
227
|
-
// WCAG 1.4.11 (3:1) on the near-black canvas while keeping a white label
|
|
228
|
-
// above 4.5:1.
|
|
229
|
-
--color-brand-default: var(--color-primary-500);
|
|
230
|
-
--color-brand-hover: var(--color-primary-600);
|
|
231
|
-
--color-brand-active: var(--color-primary-700);
|
|
232
|
-
--color-brand-text: var(--color-primary-300);
|
|
233
|
-
--color-brand-subtle: rgba(75, 145, 195, 0.1);
|
|
234
|
-
--color-brand-muted: rgba(75, 145, 195, 0.2);
|
|
235
|
-
|
|
236
|
-
// Light pastels become unreadable behind light text in dark mode. Re-tint as
|
|
237
|
-
// a low-alpha wash of the saturated *-500 hue so the surface darkens enough
|
|
238
|
-
// for white text.
|
|
239
|
-
--color-success-subtle: rgba(34, 197, 94, 0.15);
|
|
240
|
-
--color-success-muted: rgba(34, 197, 94, 0.25);
|
|
241
|
-
--color-warning-subtle: rgba(245, 158, 11, 0.15);
|
|
242
|
-
--color-warning-muted: rgba(245, 158, 11, 0.25);
|
|
243
|
-
--color-error-subtle: rgba(239, 68, 68, 0.15);
|
|
244
|
-
--color-error-muted: rgba(239, 68, 68, 0.25);
|
|
245
|
-
--color-info-subtle: rgba(6, 182, 212, 0.15);
|
|
246
|
-
--color-info-muted: rgba(6, 182, 212, 0.25);
|
|
247
|
-
|
|
248
|
-
// The *-700 shades are unreadable on the dark translucent washes above; flip
|
|
249
|
-
// to the light *-200 pastels so status text keeps 4.5:1.
|
|
250
|
-
--color-success-text: var(--color-success-200);
|
|
251
|
-
--color-warning-text: var(--color-warning-200);
|
|
252
|
-
--color-error-text: var(--color-error-200);
|
|
253
|
-
--color-info-text: var(--color-info-200);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
@media (prefers-color-scheme: dark) {
|
|
257
|
-
:where(:root:not([data-theme='light'])) {
|
|
258
|
-
@include dark-color-tokens;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
:where(:root[data-theme='dark']) {
|
|
263
|
-
@include dark-color-tokens;
|
|
264
|
-
color-scheme: dark;
|
|
265
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
// :where() keeps these at zero specificity so consumer overrides win in every
|
|
2
|
-
// theme; see the note in _colors.scss.
|
|
3
|
-
:where(:root) {
|
|
4
|
-
--shadow-none: none;
|
|
5
|
-
--shadow-xs: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
|
6
|
-
--shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);
|
|
7
|
-
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
|
|
8
|
-
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
|
|
9
|
-
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
|
|
10
|
-
--shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
11
|
-
--shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, 0.05);
|
|
12
|
-
|
|
13
|
-
// Composable top-edge highlight appended to every dark-mode shadow so elevated
|
|
14
|
-
// surfaces catch light along their top edge; a no-op in light mode.
|
|
15
|
-
--shadow-edge-highlight: 0 0 #0000;
|
|
16
|
-
|
|
17
|
-
// Bevel: paired inset highlight (top) + shadow (bottom) for a raised look;
|
|
18
|
-
// compose with --shadow-* for an ambient drop.
|
|
19
|
-
--shadow-bevel:
|
|
20
|
-
inset 0 1px 1px rgba(255, 255, 255, 0.85), inset 0 -1px 1.5px rgba(0, 0, 0, 0.25);
|
|
21
|
-
--shadow-bevel-strong:
|
|
22
|
-
inset 0 1.5px 2px rgba(255, 255, 255, 0.9), inset 0 -2px 3px rgba(0, 0, 0, 0.3);
|
|
23
|
-
|
|
24
|
-
// Well: inverse of bevel (inset shadow top, highlight bottom) for a recessed look
|
|
25
|
-
--shadow-well:
|
|
26
|
-
inset 0 1px 1.5px rgba(0, 0, 0, 0.3), inset 0 -1px 0.5px rgba(255, 255, 255, 0.5);
|
|
27
|
-
--shadow-well-strong:
|
|
28
|
-
inset 0 2px 3px rgba(0, 0, 0, 0.4), inset 0 -1.5px 1px rgba(255, 255, 255, 0.55);
|
|
29
|
-
|
|
30
|
-
--shadow-focus-ring: 0 0 0 3px rgba(59, 130, 246, 0.45);
|
|
31
|
-
--shadow-focus-ring-error: 0 0 0 3px var(--color-error-200);
|
|
32
|
-
--shadow-focus-ring-success: 0 0 0 3px var(--color-success-200);
|
|
33
|
-
|
|
34
|
-
--z-index-base: 0;
|
|
35
|
-
--z-index-raised: 10;
|
|
36
|
-
--z-index-dropdown: 100;
|
|
37
|
-
--z-index-sticky: 200;
|
|
38
|
-
--z-index-overlay: 300;
|
|
39
|
-
--z-index-modal: 400;
|
|
40
|
-
--z-index-popover: 500;
|
|
41
|
-
--z-index-toast: 600;
|
|
42
|
-
--z-index-tooltip: 700;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Dark mode: a drop shadow is the absence of light, so it stays black (deeper
|
|
46
|
-
// than light mode); a white "shadow" reads as a glow and looks wrong. Elevation
|
|
47
|
-
// is carried instead by the lifted surface tone plus a hairline top highlight
|
|
48
|
-
// that catches light, appended to every level via --shadow-edge-highlight.
|
|
49
|
-
@mixin dark-elevation-tokens {
|
|
50
|
-
--shadow-edge-highlight: inset 0 1px 0 0 rgba(255, 255, 255, 0.06);
|
|
51
|
-
|
|
52
|
-
--shadow-xs: 0 1px 2px 0 rgba(0, 0, 0, 0.4), var(--shadow-edge-highlight);
|
|
53
|
-
--shadow-sm:
|
|
54
|
-
0 1px 3px 0 rgba(0, 0, 0, 0.5), 0 1px 2px -1px rgba(0, 0, 0, 0.4),
|
|
55
|
-
var(--shadow-edge-highlight);
|
|
56
|
-
--shadow-md:
|
|
57
|
-
0 4px 8px -2px rgba(0, 0, 0, 0.55), 0 2px 4px -2px rgba(0, 0, 0, 0.4),
|
|
58
|
-
var(--shadow-edge-highlight);
|
|
59
|
-
--shadow-lg:
|
|
60
|
-
0 12px 20px -4px rgba(0, 0, 0, 0.6), 0 4px 8px -4px rgba(0, 0, 0, 0.45),
|
|
61
|
-
var(--shadow-edge-highlight);
|
|
62
|
-
--shadow-xl:
|
|
63
|
-
0 20px 28px -6px rgba(0, 0, 0, 0.65), 0 8px 12px -6px rgba(0, 0, 0, 0.5),
|
|
64
|
-
var(--shadow-edge-highlight);
|
|
65
|
-
--shadow-2xl: 0 28px 50px -12px rgba(0, 0, 0, 0.75), var(--shadow-edge-highlight);
|
|
66
|
-
|
|
67
|
-
// On a dark surface a bright highlight reads as a halo, so drop the highlight
|
|
68
|
-
// alpha and raise the shadow alpha to keep the relief without glowing.
|
|
69
|
-
--shadow-bevel:
|
|
70
|
-
inset 0 1px 1px rgba(255, 255, 255, 0.18), inset 0 -1px 1.5px rgba(0, 0, 0, 0.6);
|
|
71
|
-
--shadow-bevel-strong:
|
|
72
|
-
inset 0 1.5px 2px rgba(255, 255, 255, 0.22), inset 0 -2px 3px rgba(0, 0, 0, 0.7);
|
|
73
|
-
--shadow-well:
|
|
74
|
-
inset 0 1px 1.5px rgba(0, 0, 0, 0.55), inset 0 -1px 0.5px rgba(255, 255, 255, 0.08);
|
|
75
|
-
--shadow-well-strong:
|
|
76
|
-
inset 0 2px 3px rgba(0, 0, 0, 0.7), inset 0 -1.5px 1px rgba(255, 255, 255, 0.12);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
@media (prefers-color-scheme: dark) {
|
|
80
|
-
:where(:root:not([data-theme='light'])) {
|
|
81
|
-
@include dark-elevation-tokens;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
:where(:root[data-theme='dark']) {
|
|
86
|
-
@include dark-elevation-tokens;
|
|
87
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// :where() keeps tokens at zero specificity so consumer overrides win; see _colors.scss.
|
|
2
|
-
:where(:root) {
|
|
3
|
-
--duration-instant: 0ms;
|
|
4
|
-
--duration-fast: 100ms;
|
|
5
|
-
--duration-normal: 200ms;
|
|
6
|
-
--duration-slow: 300ms;
|
|
7
|
-
--duration-slower: 500ms;
|
|
8
|
-
|
|
9
|
-
--ease-linear: linear;
|
|
10
|
-
--ease-in: cubic-bezier(0.4, 0, 1, 1);
|
|
11
|
-
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
|
12
|
-
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
|
13
|
-
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
14
|
-
|
|
15
|
-
--transition-colors:
|
|
16
|
-
color var(--duration-fast) var(--ease-out),
|
|
17
|
-
background-color var(--duration-fast) var(--ease-out),
|
|
18
|
-
border-color var(--duration-fast) var(--ease-out),
|
|
19
|
-
fill var(--duration-fast) var(--ease-out);
|
|
20
|
-
|
|
21
|
-
--transition-shadow: box-shadow var(--duration-fast) var(--ease-out);
|
|
22
|
-
|
|
23
|
-
--transition-transform: transform var(--duration-normal) var(--ease-spring);
|
|
24
|
-
|
|
25
|
-
--transition-opacity: opacity var(--duration-normal) var(--ease-out);
|
|
26
|
-
|
|
27
|
-
--transition-all: all var(--duration-normal) var(--ease-in-out);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
@media (prefers-reduced-motion: reduce) {
|
|
31
|
-
:where(:root) {
|
|
32
|
-
--duration-fast: 0ms;
|
|
33
|
-
--duration-normal: 0ms;
|
|
34
|
-
--duration-slow: 0ms;
|
|
35
|
-
--duration-slower: 0ms;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// :where() keeps tokens at zero specificity so consumer overrides win; see _colors.scss.
|
|
2
|
-
:where(:root) {
|
|
3
|
-
--radius-none: 0;
|
|
4
|
-
--radius-xs: 0.125rem; // 2px
|
|
5
|
-
--radius-sm: 0.25rem; // 4px
|
|
6
|
-
--radius-md: 0.375rem; // 6px
|
|
7
|
-
--radius-lg: 0.5rem; // 8px
|
|
8
|
-
--radius-xl: 0.75rem; // 12px
|
|
9
|
-
--radius-2xl: 1rem; // 16px
|
|
10
|
-
--radius-3xl: 1.5rem; // 24px
|
|
11
|
-
--radius-full: 9999px; // pill / circle
|
|
12
|
-
|
|
13
|
-
--border-width-none: 0;
|
|
14
|
-
--border-width-thin: 1px;
|
|
15
|
-
--border-width-medium: 2px;
|
|
16
|
-
--border-width-thick: 4px;
|
|
17
|
-
|
|
18
|
-
// Hit-target box for icon buttons (clear / close / dismiss / toggle). em-based
|
|
19
|
-
// so it scales with the host component's size; since all sized components share
|
|
20
|
-
// a font-size per tier, this is also consistent across components at a tier
|
|
21
|
-
// (md = 1.75 * 16px = 28px).
|
|
22
|
-
--ea-icon-button-size: 1.75em;
|
|
23
|
-
}
|