@ids-group-ltd/ids-design-system 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +32 -10
- package/fesm2022/ids-group-ltd-ids-design-system.mjs +241 -240
- package/fesm2022/ids-group-ltd-ids-design-system.mjs.map +1 -1
- package/package.json +2 -2
- package/styles/_dropdown-overlay.scss +117 -117
- package/styles/_fonts.scss +59 -59
- package/styles/_icon-base.scss +9 -9
- package/styles/_link.scss +77 -77
- package/styles/_reset.scss +17 -17
- package/styles/_scrollbar.scss +17 -17
- package/styles/_toast-overlay.scss +6 -6
- package/styles/_tokens-charts.scss +70 -70
- package/styles/_tokens.scss +614 -614
- package/styles/ds.scss +27 -27
- package/themes/README.md +96 -96
- package/themes/default/_palette.scss +159 -159
- package/themes/default/_theme.scss +274 -274
package/styles/ds.scss
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
// Public DS stylesheet entry. Consumers import once at the top of their styles.scss:
|
|
2
|
-
// @use 'styles/ds';
|
|
3
|
-
//
|
|
4
|
-
// Bundles the default palette + theme for out-of-the-box rendering. Layers:
|
|
5
|
-
// default/palette — Tier 1 concrete colours (ramps + HSL channels)
|
|
6
|
-
// default/theme — Tier 2 semantic role → palette assignments + font families
|
|
7
|
-
// tokens — Tier 3 geometry / typography scale / motion / component tokens
|
|
8
|
-
// Advanced consumers can swap the palette/theme and keep tokens — global
|
|
9
|
-
// side-effects (fonts, link) are then opt-in:
|
|
10
|
-
// @use 'themes/X/palette'; @use 'themes/X/theme'; @use 'styles/tokens';
|
|
11
|
-
// @use 'styles/fonts'; @use 'styles/link'; …
|
|
12
|
-
|
|
13
|
-
@forward '../themes/default/palette';
|
|
14
|
-
@forward '../themes/default/theme';
|
|
15
|
-
@forward 'tokens';
|
|
16
|
-
@forward 'tokens-charts';
|
|
17
|
-
@forward 'fonts';
|
|
18
|
-
@forward 'reset';
|
|
19
|
-
@forward 'typography';
|
|
20
|
-
@forward 'link';
|
|
21
|
-
@forward 'layout-utils';
|
|
22
|
-
@forward 'page-grid';
|
|
23
|
-
@forward 'scrollbar';
|
|
24
|
-
@forward 'icon-base';
|
|
25
|
-
@forward 'dropdown-overlay';
|
|
26
|
-
@forward 'toast-overlay';
|
|
27
|
-
@forward 'skeleton-shimmer';
|
|
1
|
+
// Public DS stylesheet entry. Consumers import once at the top of their styles.scss:
|
|
2
|
+
// @use 'styles/ds';
|
|
3
|
+
//
|
|
4
|
+
// Bundles the default palette + theme for out-of-the-box rendering. Layers:
|
|
5
|
+
// default/palette — Tier 1 concrete colours (ramps + HSL channels)
|
|
6
|
+
// default/theme — Tier 2 semantic role → palette assignments + font families
|
|
7
|
+
// tokens — Tier 3 geometry / typography scale / motion / component tokens
|
|
8
|
+
// Advanced consumers can swap the palette/theme and keep tokens — global
|
|
9
|
+
// side-effects (fonts, link) are then opt-in:
|
|
10
|
+
// @use 'themes/X/palette'; @use 'themes/X/theme'; @use 'styles/tokens';
|
|
11
|
+
// @use 'styles/fonts'; @use 'styles/link'; …
|
|
12
|
+
|
|
13
|
+
@forward '../themes/default/palette';
|
|
14
|
+
@forward '../themes/default/theme';
|
|
15
|
+
@forward 'tokens';
|
|
16
|
+
@forward 'tokens-charts';
|
|
17
|
+
@forward 'fonts';
|
|
18
|
+
@forward 'reset';
|
|
19
|
+
@forward 'typography';
|
|
20
|
+
@forward 'link';
|
|
21
|
+
@forward 'layout-utils';
|
|
22
|
+
@forward 'page-grid';
|
|
23
|
+
@forward 'scrollbar';
|
|
24
|
+
@forward 'icon-base';
|
|
25
|
+
@forward 'dropdown-overlay';
|
|
26
|
+
@forward 'toast-overlay';
|
|
27
|
+
@forward 'skeleton-shimmer';
|
package/themes/README.md
CHANGED
|
@@ -1,96 +1,96 @@
|
|
|
1
|
-
# Themes — palette + role assignments
|
|
2
|
-
|
|
3
|
-
Colour lives in two files here: a **palette** (defines the concrete colours) and a **theme** (assigns them to semantic roles). The geometry/component layer is separate (`../styles/_tokens.scss`).
|
|
4
|
-
|
|
5
|
-
## Architecture: three tiers
|
|
6
|
-
|
|
7
|
-
| Tier | Lives in | Examples | Consumers |
|
|
8
|
-
|---|---|---|---|
|
|
9
|
-
| **Tier 1 — Palette** (defines colours) | `themes/<name>/_palette.scss` | `--blue-600`, `--cool-gray-0`, `--brand-gray-500`, `--red-500`, `--blue-h/s/l`, `--shadow-tint-h/s/l` | Only the theme file |
|
|
10
|
-
| **Tier 2 — Theme** (sets roles) | `themes/<name>/_theme.scss` | `--primary: var(--blue-600)`, `--text-primary`, `--surface-default`, `--success`, `--focus-ring`, `--primary-h: var(--blue-h)`, font families; the `--neutral-*` family slot (cool-gray by default, brand-gray via `[data-neutrals="brand"]`) | Components |
|
|
11
|
-
| **Tier 3 — Component / scale** | `styles/_tokens.scss` and inside `*.component.scss` | `--space-*`, `--radius-*`, `--ds-button-bg`, `--duration-fast`, `--layer-modal` | Components (their own) |
|
|
12
|
-
|
|
13
|
-
**Hard rule:** components NEVER consume Tier 1 palette directly. If you write `var(--blue-600)` inside `button.component.scss`, that's a bug — introduce or reuse a Tier 2 role.
|
|
14
|
-
|
|
15
|
-
**Why split palette from theme:** the palette says *what colours exist*; the theme says *what each role is*. A dark theme ships a different palette (different ramp values) + a theme map that re-points roles. Swapping either re-skins the system without touching components.
|
|
16
|
-
|
|
17
|
-
## Available palette + theme
|
|
18
|
-
|
|
19
|
-
- **`default/_palette.scss`** — Blue + slate ramps (the concrete colours).
|
|
20
|
-
- **`default/_theme.scss`** — Light role map onto the default palette. Both are bundled into `styles/ds.scss` (palette → theme → tokens) so `@use 'styles/ds';` works out of the box.
|
|
21
|
-
|
|
22
|
-
Future (each a `themes/<name>/` folder with `_palette.scss` + `_theme.scss`):
|
|
23
|
-
- `themes/dark/` — Dark-mode flip (`--shadow-tint-l` → ~95%, neutrals inverted, etc.).
|
|
24
|
-
- `themes/high-contrast/` — A11y boost.
|
|
25
|
-
|
|
26
|
-
## How a consumer picks a theme
|
|
27
|
-
|
|
28
|
-
### Option A — out-of-the-box default
|
|
29
|
-
|
|
30
|
-
```scss
|
|
31
|
-
// Consumer styles.scss
|
|
32
|
-
@use 'styles/ds'; // bundles default palette + theme + tokens + reset + ...
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Option B — explicit theme choice
|
|
36
|
-
|
|
37
|
-
```scss
|
|
38
|
-
// Consumer styles.scss
|
|
39
|
-
@use 'themes/dark/palette'; // pick a non-default theme: palette …
|
|
40
|
-
@use 'themes/dark/theme'; // … then its role map
|
|
41
|
-
@use 'styles/tokens';
|
|
42
|
-
@use 'styles/reset';
|
|
43
|
-
@use 'styles/typography';
|
|
44
|
-
@use 'styles/scrollbar';
|
|
45
|
-
@use 'styles/icon-base';
|
|
46
|
-
@use 'styles/dropdown-overlay';
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Palette + theme must come BEFORE `tokens` so role aliases resolve.
|
|
50
|
-
|
|
51
|
-
### Option C — brand layer on top of default theme
|
|
52
|
-
|
|
53
|
-
```scss
|
|
54
|
-
// Consumer styles.scss
|
|
55
|
-
@use 'styles/ds'; // default theme + DS
|
|
56
|
-
@use './app/styles/brand-manage-my'; // overrides palette/roles via [data-brand]
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
This is the mm-broker pattern: load DS (default theme included), then overlay a brand at a more-specific selector (`[data-brand="manage-my"]`).
|
|
60
|
-
|
|
61
|
-
## Brand vs theme — what's the difference?
|
|
62
|
-
|
|
63
|
-
- **Theme** swaps the entire Tier 1 palette. Affects EVERY semantic role downstream.
|
|
64
|
-
- **Brand** is a thin overlay scoped via attribute selector (`[data-brand="X"]`). Usually overrides a smaller subset (key palette stops + maybe a few roles).
|
|
65
|
-
|
|
66
|
-
Same mechanism (CSS custom properties + cascade), different scope.
|
|
67
|
-
|
|
68
|
-
## Adding a new theme
|
|
69
|
-
|
|
70
|
-
1. Create a `themes/<name>/` folder with `_palette.scss` (ramps + HSL channels) and `_theme.scss` (role map), mirroring `themes/default/`.
|
|
71
|
-
2. Optionally add it to `styles/ds.scss` if it should be a default-bundled option.
|
|
72
|
-
3. Or let consumers `@use 'themes/<name>/palette'; @use 'themes/<name>/theme';` directly.
|
|
73
|
-
|
|
74
|
-
Components don't need any change — they consume semantic roles which automatically pick up the new palette.
|
|
75
|
-
|
|
76
|
-
## Adding a new brand override
|
|
77
|
-
|
|
78
|
-
1. Create `<consumer-app>/src/app/styles/_brand-X.scss`.
|
|
79
|
-
2. Open with `[data-brand="X"] { ... }`.
|
|
80
|
-
3. Override:
|
|
81
|
-
- **Palette HSL channels** (`--blue-h/s/l`) — for focus rings and halos that compose hsla() from channels (the theme bridges `--primary-h: var(--blue-h)`).
|
|
82
|
-
- **Blue ramp** (`--blue-50..900`) —
|
|
83
|
-
- Other roles you want to retint independently (surfaces, borders, text, success/danger ramps, secondary, etc.).
|
|
84
|
-
4. Apply via `<html data-brand="X">` on the host app.
|
|
85
|
-
|
|
86
|
-
## Rules summary
|
|
87
|
-
|
|
88
|
-
- Components NEVER reference `var(--blue-600)` / `var(--neutral-200)` / `var(--red-500)` directly. Use a Tier 2 role (`--primary`, `--text-secondary`) or a Tier 3 component token.
|
|
89
|
-
- Themes own palette. Brands overlay on top via `[data-brand]`.
|
|
90
|
-
- Theme switching = swap one `@use 'themes/X'`. No component changes.
|
|
91
|
-
- `--primary-hover`, `--primary-pressed` are auto-derived via `color-mix()`. Don't override unless brand needs non-derived hover.
|
|
92
|
-
- Audit guard (suggested pre-commit hook):
|
|
93
|
-
```bash
|
|
94
|
-
grep -nE 'var\(--(violet|neutral|red|green|yellow|blue|orange|cyan|magenta)-[0-9]+\)' \
|
|
95
|
-
prototype/ds/src/lib/components/**/*.scss && exit 1
|
|
96
|
-
```
|
|
1
|
+
# Themes — palette + role assignments
|
|
2
|
+
|
|
3
|
+
Colour lives in two files here: a **palette** (defines the concrete colours) and a **theme** (assigns them to semantic roles). The geometry/component layer is separate (`../styles/_tokens.scss`).
|
|
4
|
+
|
|
5
|
+
## Architecture: three tiers
|
|
6
|
+
|
|
7
|
+
| Tier | Lives in | Examples | Consumers |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| **Tier 1 — Palette** (defines colours) | `themes/<name>/_palette.scss` | `--blue-600`, `--cool-gray-0`, `--brand-gray-500`, `--red-500`, `--blue-h/s/l`, `--shadow-tint-h/s/l` | Only the theme file |
|
|
10
|
+
| **Tier 2 — Theme** (sets roles) | `themes/<name>/_theme.scss` | `--primary: var(--blue-600)`, `--text-primary`, `--surface-default`, `--success`, `--focus-ring`, `--primary-h: var(--blue-h)`, font families; the `--neutral-*` family slot (cool-gray by default, brand-gray via `[data-neutrals="brand"]`) | Components |
|
|
11
|
+
| **Tier 3 — Component / scale** | `styles/_tokens.scss` and inside `*.component.scss` | `--space-*`, `--radius-*`, `--ds-button-bg`, `--duration-fast`, `--layer-modal` | Components (their own) |
|
|
12
|
+
|
|
13
|
+
**Hard rule:** components NEVER consume Tier 1 palette directly. If you write `var(--blue-600)` inside `button.component.scss`, that's a bug — introduce or reuse a Tier 2 role.
|
|
14
|
+
|
|
15
|
+
**Why split palette from theme:** the palette says *what colours exist*; the theme says *what each role is*. A dark theme ships a different palette (different ramp values) + a theme map that re-points roles. Swapping either re-skins the system without touching components.
|
|
16
|
+
|
|
17
|
+
## Available palette + theme
|
|
18
|
+
|
|
19
|
+
- **`default/_palette.scss`** — Blue + slate ramps (the concrete colours).
|
|
20
|
+
- **`default/_theme.scss`** — Light role map onto the default palette. Both are bundled into `styles/ds.scss` (palette → theme → tokens) so `@use 'styles/ds';` works out of the box.
|
|
21
|
+
|
|
22
|
+
Future (each a `themes/<name>/` folder with `_palette.scss` + `_theme.scss`):
|
|
23
|
+
- `themes/dark/` — Dark-mode flip (`--shadow-tint-l` → ~95%, neutrals inverted, etc.).
|
|
24
|
+
- `themes/high-contrast/` — A11y boost.
|
|
25
|
+
|
|
26
|
+
## How a consumer picks a theme
|
|
27
|
+
|
|
28
|
+
### Option A — out-of-the-box default
|
|
29
|
+
|
|
30
|
+
```scss
|
|
31
|
+
// Consumer styles.scss
|
|
32
|
+
@use 'styles/ds'; // bundles default palette + theme + tokens + reset + ...
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Option B — explicit theme choice
|
|
36
|
+
|
|
37
|
+
```scss
|
|
38
|
+
// Consumer styles.scss
|
|
39
|
+
@use 'themes/dark/palette'; // pick a non-default theme: palette …
|
|
40
|
+
@use 'themes/dark/theme'; // … then its role map
|
|
41
|
+
@use 'styles/tokens';
|
|
42
|
+
@use 'styles/reset';
|
|
43
|
+
@use 'styles/typography';
|
|
44
|
+
@use 'styles/scrollbar';
|
|
45
|
+
@use 'styles/icon-base';
|
|
46
|
+
@use 'styles/dropdown-overlay';
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Palette + theme must come BEFORE `tokens` so role aliases resolve.
|
|
50
|
+
|
|
51
|
+
### Option C — brand layer on top of default theme
|
|
52
|
+
|
|
53
|
+
```scss
|
|
54
|
+
// Consumer styles.scss
|
|
55
|
+
@use 'styles/ds'; // default theme + DS
|
|
56
|
+
@use './app/styles/brand-manage-my'; // overrides palette/roles via [data-brand]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
This is the mm-broker pattern: load DS (default theme included), then overlay a brand at a more-specific selector (`[data-brand="manage-my"]`).
|
|
60
|
+
|
|
61
|
+
## Brand vs theme — what's the difference?
|
|
62
|
+
|
|
63
|
+
- **Theme** swaps the entire Tier 1 palette. Affects EVERY semantic role downstream.
|
|
64
|
+
- **Brand** is a thin overlay scoped via attribute selector (`[data-brand="X"]`). Usually overrides a smaller subset (key palette stops + maybe a few roles).
|
|
65
|
+
|
|
66
|
+
Same mechanism (CSS custom properties + cascade), different scope.
|
|
67
|
+
|
|
68
|
+
## Adding a new theme
|
|
69
|
+
|
|
70
|
+
1. Create a `themes/<name>/` folder with `_palette.scss` (ramps + HSL channels) and `_theme.scss` (role map), mirroring `themes/default/`.
|
|
71
|
+
2. Optionally add it to `styles/ds.scss` if it should be a default-bundled option.
|
|
72
|
+
3. Or let consumers `@use 'themes/<name>/palette'; @use 'themes/<name>/theme';` directly.
|
|
73
|
+
|
|
74
|
+
Components don't need any change — they consume semantic roles which automatically pick up the new palette.
|
|
75
|
+
|
|
76
|
+
## Adding a new brand override
|
|
77
|
+
|
|
78
|
+
1. Create `<consumer-app>/src/app/styles/_brand-X.scss`.
|
|
79
|
+
2. Open with `[data-brand="X"] { ... }`.
|
|
80
|
+
3. Override:
|
|
81
|
+
- **Palette HSL channels** (`--blue-h/s/l`) — for focus rings and halos that compose hsla() from channels (the theme bridges `--primary-h: var(--blue-h)`).
|
|
82
|
+
- **Blue ramp** (`--blue-50..900`) — the simplest re-skin lever. All brand-derived roles (`--primary`, `--primary-strong`, `--primary-subtitle`, `--primary-muted-strong`, `--text-link`, `--surface-tint`) retint automatically from it. For a fully calibrated brand you MAY also set the `--primary-*` roles directly to hand-picked hex (when ramp derivation doesn't hit the exact stop) — see `_brand-manage-my.scss`. Leave `--primary-hover`/`--primary-pressed` to the DS `color-mix()` derivation.
|
|
83
|
+
- Other roles you want to retint independently (surfaces, borders, text, success/danger ramps, secondary, etc.).
|
|
84
|
+
4. Apply via `<html data-brand="X">` on the host app.
|
|
85
|
+
|
|
86
|
+
## Rules summary
|
|
87
|
+
|
|
88
|
+
- Components NEVER reference `var(--blue-600)` / `var(--neutral-200)` / `var(--red-500)` directly. Use a Tier 2 role (`--primary`, `--text-secondary`) or a Tier 3 component token.
|
|
89
|
+
- Themes own palette. Brands overlay on top via `[data-brand]`.
|
|
90
|
+
- Theme switching = swap one `@use 'themes/X'`. No component changes.
|
|
91
|
+
- `--primary-hover`, `--primary-pressed` are auto-derived via `color-mix()`. Don't override unless brand needs non-derived hover.
|
|
92
|
+
- Audit guard (suggested pre-commit hook):
|
|
93
|
+
```bash
|
|
94
|
+
grep -nE 'var\(--(violet|neutral|red|green|yellow|blue|orange|cyan|magenta)-[0-9]+\)' \
|
|
95
|
+
prototype/ds/src/lib/components/**/*.scss && exit 1
|
|
96
|
+
```
|
|
@@ -1,159 +1,159 @@
|
|
|
1
|
-
// =========================================================================
|
|
2
|
-
// Default palette — Tier 1 concrete colour primitives.
|
|
3
|
-
//
|
|
4
|
-
// This file DEFINES the colours: raw ramps (--cool-gray-*, --brand-gray-*,
|
|
5
|
-
// --blue-*, --red-*, --green-*, --yellow-*, --sky-*, --orange-*) + the HSL
|
|
6
|
-
// channels (--blue-h/s/l, --red-h/s/l, --shadow-tint-h/s/l) they compose from.
|
|
7
|
-
// Tokens are named by the COLOUR itself — the palette does not know what a
|
|
8
|
-
// colour is "for". The --neutral-* FAMILY SLOT (which gray ramp is active)
|
|
9
|
-
// is semantic, so it lives in the theme (_theme.scss), not here.
|
|
10
|
-
//
|
|
11
|
-
// The companion theme (themes/default/_theme.scss) SETS these onto semantic
|
|
12
|
-
// roles (--primary → --blue-600, --error → --red-500, …). Components consume
|
|
13
|
-
// only those roles, never this palette directly.
|
|
14
|
-
//
|
|
15
|
-
// A sibling palette (e.g. _palette-dark.scss) ships different ramp values; pair
|
|
16
|
-
// it with a matching theme file. Default = "Blue + Slate baseline".
|
|
17
|
-
// =========================================================================
|
|
18
|
-
|
|
19
|
-
:root {
|
|
20
|
-
// -----------------------------------------------------------------------
|
|
21
|
-
// Cool gray ramp (13 stops) — hand-drawn slate-family gray. The hue drifts
|
|
22
|
-
// 210 → 227 toward the brand hue (229) as it darkens; chroma follows a
|
|
23
|
-
// designed U-curve (S 40% → 12% → 37%). Appearance name, Carbon-style.
|
|
24
|
-
// -----------------------------------------------------------------------
|
|
25
|
-
--cool-gray-0: #FFFFFF;
|
|
26
|
-
--cool-gray-50: #F8FAFC;
|
|
27
|
-
--cool-gray-100: #F1F4F9;
|
|
28
|
-
--cool-gray-150: #E8ECF2;
|
|
29
|
-
--cool-gray-200: #DCE1EA;
|
|
30
|
-
--cool-gray-300: #C2C9D6;
|
|
31
|
-
--cool-gray-400: #9BA3B4;
|
|
32
|
-
--cool-gray-500: #6B7388;
|
|
33
|
-
--cool-gray-600: #4D5468;
|
|
34
|
-
--cool-gray-700: #353B4D;
|
|
35
|
-
--cool-gray-800: #232838;
|
|
36
|
-
--cool-gray-900: #161A28;
|
|
37
|
-
--cool-gray-950: #0B0E18;
|
|
38
|
-
|
|
39
|
-
// -----------------------------------------------------------------------
|
|
40
|
-
// Brand gray ramp (13 stops) — derived, M3-style: the cool-gray S/L curve
|
|
41
|
-
// and hue drift are kept, but the hue source is --neutral-h (defaults to
|
|
42
|
-
// the brand hue). Re-skinning --primary-h re-tints these grays to match
|
|
43
|
-
// the brand automatically. With the default blue brand this ramp matches
|
|
44
|
-
// cool-gray to within rounding.
|
|
45
|
-
// -----------------------------------------------------------------------
|
|
46
|
-
--neutral-h: var(--primary-h, var(--blue-h));
|
|
47
|
-
--brand-gray-0: #FFFFFF;
|
|
48
|
-
--brand-gray-50: hsl(calc(var(--neutral-h) - 19), 40.0%, 98.0%);
|
|
49
|
-
--brand-gray-100: hsl(calc(var(--neutral-h) - 12), 40.0%, 96.1%);
|
|
50
|
-
--brand-gray-150: hsl(calc(var(--neutral-h) - 13), 27.8%, 92.9%);
|
|
51
|
-
--brand-gray-200: hsl(calc(var(--neutral-h) - 10), 25.0%, 89.0%);
|
|
52
|
-
--brand-gray-300: hsl(calc(var(--neutral-h) - 10), 19.6%, 80.0%);
|
|
53
|
-
--brand-gray-400: hsl(calc(var(--neutral-h) - 8), 14.3%, 65.7%);
|
|
54
|
-
--brand-gray-500: hsl(calc(var(--neutral-h) - 6), 11.9%, 47.6%);
|
|
55
|
-
--brand-gray-600: hsl(calc(var(--neutral-h) - 5), 14.9%, 35.5%);
|
|
56
|
-
--brand-gray-700: hsl(calc(var(--neutral-h) - 4), 18.5%, 25.5%);
|
|
57
|
-
--brand-gray-800: hsl(calc(var(--neutral-h) - 3), 23.1%, 17.8%);
|
|
58
|
-
--brand-gray-900: hsl(calc(var(--neutral-h) - 2), 29.0%, 12.2%);
|
|
59
|
-
--brand-gray-950: hsl(calc(var(--neutral-h) - 3), 37.1%, 6.9%);
|
|
60
|
-
|
|
61
|
-
// -----------------------------------------------------------------------
|
|
62
|
-
// Blue — defined as HSL channels so we can compose hsla() halos and tints
|
|
63
|
-
// from the same source. #2F54FF ≈ hsl(229, 100%, 59%). This is the ramp the
|
|
64
|
-
// default theme maps --primary onto (see styles/_tokens.scss). Naming is
|
|
65
|
-
// concrete (the colour) — the semantic --primary mapping lives in the lib.
|
|
66
|
-
// -----------------------------------------------------------------------
|
|
67
|
-
--blue-h: 229;
|
|
68
|
-
--blue-s: 100%;
|
|
69
|
-
--blue-l: 59%;
|
|
70
|
-
|
|
71
|
-
--blue-50: hsl(var(--blue-h), 100%, 97%);
|
|
72
|
-
--blue-100: hsl(var(--blue-h), 95%, 94%);
|
|
73
|
-
--blue-200: hsl(var(--blue-h), 95%, 89%);
|
|
74
|
-
--blue-300: hsl(var(--blue-h), 98%, 82%);
|
|
75
|
-
--blue-400: hsl(var(--blue-h), 100%, 75%);
|
|
76
|
-
--blue-500: hsl(var(--blue-h), 100%, 66%);
|
|
77
|
-
--blue-600: hsl(var(--blue-h), var(--blue-s), var(--blue-l));
|
|
78
|
-
--blue-700: hsl(var(--blue-h), 85%, 52%);
|
|
79
|
-
--blue-800: hsl(var(--blue-h), 79%, 40%);
|
|
80
|
-
--blue-900: hsl(var(--blue-h), 77%, 30%);
|
|
81
|
-
|
|
82
|
-
// -----------------------------------------------------------------------
|
|
83
|
-
// Orange — focus / secondary signal
|
|
84
|
-
// -----------------------------------------------------------------------
|
|
85
|
-
--orange-50: #FFF7F0;
|
|
86
|
-
--orange-100: #FFEEDF;
|
|
87
|
-
--orange-200: #FFD9B8;
|
|
88
|
-
--orange-300: #FFC59C;
|
|
89
|
-
--orange-400: #FF9755;
|
|
90
|
-
--orange-500: #FF7A2E;
|
|
91
|
-
--orange-600: #E8631A;
|
|
92
|
-
--orange-700: #B84812;
|
|
93
|
-
--orange-800: #8A340A;
|
|
94
|
-
|
|
95
|
-
// -----------------------------------------------------------------------
|
|
96
|
-
// Green — success
|
|
97
|
-
// -----------------------------------------------------------------------
|
|
98
|
-
--green-50: #ECFAEE;
|
|
99
|
-
--green-100: #D6F3DB;
|
|
100
|
-
--green-200: #BBE8C2;
|
|
101
|
-
--green-300: #8EDA9A;
|
|
102
|
-
--green-400: #4FC368;
|
|
103
|
-
--green-500: #22A33A;
|
|
104
|
-
--green-600: #1B8A2E;
|
|
105
|
-
--green-700: #156822;
|
|
106
|
-
|
|
107
|
-
// -----------------------------------------------------------------------
|
|
108
|
-
// Yellow — attention / warning
|
|
109
|
-
// -----------------------------------------------------------------------
|
|
110
|
-
--yellow-50: #FFFBEA;
|
|
111
|
-
--yellow-100: #FEF8DC;
|
|
112
|
-
--yellow-200: #FCEFA1;
|
|
113
|
-
--yellow-300: #F9E25F;
|
|
114
|
-
--yellow-400: #F4D43A;
|
|
115
|
-
--yellow-500: #E0BE00;
|
|
116
|
-
--yellow-600: #B89B00;
|
|
117
|
-
--yellow-700: #8A7400;
|
|
118
|
-
|
|
119
|
-
// -----------------------------------------------------------------------
|
|
120
|
-
// Red — HSL-channel-split for halo derivation. #D81F1F ≈ hsl(0, 75%, 49%).
|
|
121
|
-
// The default theme maps --error onto this ramp (see styles/_tokens.scss).
|
|
122
|
-
// -----------------------------------------------------------------------
|
|
123
|
-
--red-h: 0;
|
|
124
|
-
--red-s: 75%;
|
|
125
|
-
--red-l: 49%;
|
|
126
|
-
|
|
127
|
-
--red-50: hsl(var(--red-h), 86%, 97%);
|
|
128
|
-
--red-100: hsl(var(--red-h), 86%, 95%);
|
|
129
|
-
--red-200: hsl(var(--red-h), 86%, 88%);
|
|
130
|
-
--red-300: hsl(var(--red-h), 84%, 76%);
|
|
131
|
-
--red-400: hsl(var(--red-h), 87%, 57%);
|
|
132
|
-
--red-500: hsl(var(--red-h), var(--red-s), var(--red-l));
|
|
133
|
-
--red-600: hsl(var(--red-h), 78%, 41%);
|
|
134
|
-
--red-700: hsl(var(--red-h), 78%, 31%);
|
|
135
|
-
|
|
136
|
-
// -----------------------------------------------------------------------
|
|
137
|
-
// Sky — info role ramp. A brighter, cooler blue (#3B82F6) kept distinct
|
|
138
|
-
// from the primary --blue ramp (#2F54FF) so "informational" reads apart
|
|
139
|
-
// from "primary action".
|
|
140
|
-
// -----------------------------------------------------------------------
|
|
141
|
-
--sky-50: #EFF6FF;
|
|
142
|
-
--sky-100: #DBEAFE;
|
|
143
|
-
--sky-200: #BFDBFE;
|
|
144
|
-
--sky-300: #93C5FD;
|
|
145
|
-
--sky-400: #60A5FA;
|
|
146
|
-
--sky-500: #3B82F6;
|
|
147
|
-
--sky-600: #2563EB;
|
|
148
|
-
--sky-700: #1D4ED8;
|
|
149
|
-
|
|
150
|
-
// -----------------------------------------------------------------------
|
|
151
|
-
// Shadow tint — channel-split substrate. Light theme uses a cool
|
|
152
|
-
// near-black slate (225 / 39% / 7%). A dark theme would override
|
|
153
|
-
// --shadow-tint-l to ~95% so the same alphas render as soft light
|
|
154
|
-
// glows over dark surfaces.
|
|
155
|
-
// -----------------------------------------------------------------------
|
|
156
|
-
--shadow-tint-h: 225;
|
|
157
|
-
--shadow-tint-s: 39%;
|
|
158
|
-
--shadow-tint-l: 7%;
|
|
159
|
-
}
|
|
1
|
+
// =========================================================================
|
|
2
|
+
// Default palette — Tier 1 concrete colour primitives.
|
|
3
|
+
//
|
|
4
|
+
// This file DEFINES the colours: raw ramps (--cool-gray-*, --brand-gray-*,
|
|
5
|
+
// --blue-*, --red-*, --green-*, --yellow-*, --sky-*, --orange-*) + the HSL
|
|
6
|
+
// channels (--blue-h/s/l, --red-h/s/l, --shadow-tint-h/s/l) they compose from.
|
|
7
|
+
// Tokens are named by the COLOUR itself — the palette does not know what a
|
|
8
|
+
// colour is "for". The --neutral-* FAMILY SLOT (which gray ramp is active)
|
|
9
|
+
// is semantic, so it lives in the theme (_theme.scss), not here.
|
|
10
|
+
//
|
|
11
|
+
// The companion theme (themes/default/_theme.scss) SETS these onto semantic
|
|
12
|
+
// roles (--primary → --blue-600, --error → --red-500, …). Components consume
|
|
13
|
+
// only those roles, never this palette directly.
|
|
14
|
+
//
|
|
15
|
+
// A sibling palette (e.g. _palette-dark.scss) ships different ramp values; pair
|
|
16
|
+
// it with a matching theme file. Default = "Blue + Slate baseline".
|
|
17
|
+
// =========================================================================
|
|
18
|
+
|
|
19
|
+
:root {
|
|
20
|
+
// -----------------------------------------------------------------------
|
|
21
|
+
// Cool gray ramp (13 stops) — hand-drawn slate-family gray. The hue drifts
|
|
22
|
+
// 210 → 227 toward the brand hue (229) as it darkens; chroma follows a
|
|
23
|
+
// designed U-curve (S 40% → 12% → 37%). Appearance name, Carbon-style.
|
|
24
|
+
// -----------------------------------------------------------------------
|
|
25
|
+
--cool-gray-0: #FFFFFF;
|
|
26
|
+
--cool-gray-50: #F8FAFC;
|
|
27
|
+
--cool-gray-100: #F1F4F9;
|
|
28
|
+
--cool-gray-150: #E8ECF2;
|
|
29
|
+
--cool-gray-200: #DCE1EA;
|
|
30
|
+
--cool-gray-300: #C2C9D6;
|
|
31
|
+
--cool-gray-400: #9BA3B4;
|
|
32
|
+
--cool-gray-500: #6B7388;
|
|
33
|
+
--cool-gray-600: #4D5468;
|
|
34
|
+
--cool-gray-700: #353B4D;
|
|
35
|
+
--cool-gray-800: #232838;
|
|
36
|
+
--cool-gray-900: #161A28;
|
|
37
|
+
--cool-gray-950: #0B0E18;
|
|
38
|
+
|
|
39
|
+
// -----------------------------------------------------------------------
|
|
40
|
+
// Brand gray ramp (13 stops) — derived, M3-style: the cool-gray S/L curve
|
|
41
|
+
// and hue drift are kept, but the hue source is --neutral-h (defaults to
|
|
42
|
+
// the brand hue). Re-skinning --primary-h re-tints these grays to match
|
|
43
|
+
// the brand automatically. With the default blue brand this ramp matches
|
|
44
|
+
// cool-gray to within rounding.
|
|
45
|
+
// -----------------------------------------------------------------------
|
|
46
|
+
--neutral-h: var(--primary-h, var(--blue-h));
|
|
47
|
+
--brand-gray-0: #FFFFFF;
|
|
48
|
+
--brand-gray-50: hsl(calc(var(--neutral-h) - 19), 40.0%, 98.0%);
|
|
49
|
+
--brand-gray-100: hsl(calc(var(--neutral-h) - 12), 40.0%, 96.1%);
|
|
50
|
+
--brand-gray-150: hsl(calc(var(--neutral-h) - 13), 27.8%, 92.9%);
|
|
51
|
+
--brand-gray-200: hsl(calc(var(--neutral-h) - 10), 25.0%, 89.0%);
|
|
52
|
+
--brand-gray-300: hsl(calc(var(--neutral-h) - 10), 19.6%, 80.0%);
|
|
53
|
+
--brand-gray-400: hsl(calc(var(--neutral-h) - 8), 14.3%, 65.7%);
|
|
54
|
+
--brand-gray-500: hsl(calc(var(--neutral-h) - 6), 11.9%, 47.6%);
|
|
55
|
+
--brand-gray-600: hsl(calc(var(--neutral-h) - 5), 14.9%, 35.5%);
|
|
56
|
+
--brand-gray-700: hsl(calc(var(--neutral-h) - 4), 18.5%, 25.5%);
|
|
57
|
+
--brand-gray-800: hsl(calc(var(--neutral-h) - 3), 23.1%, 17.8%);
|
|
58
|
+
--brand-gray-900: hsl(calc(var(--neutral-h) - 2), 29.0%, 12.2%);
|
|
59
|
+
--brand-gray-950: hsl(calc(var(--neutral-h) - 3), 37.1%, 6.9%);
|
|
60
|
+
|
|
61
|
+
// -----------------------------------------------------------------------
|
|
62
|
+
// Blue — defined as HSL channels so we can compose hsla() halos and tints
|
|
63
|
+
// from the same source. #2F54FF ≈ hsl(229, 100%, 59%). This is the ramp the
|
|
64
|
+
// default theme maps --primary onto (see styles/_tokens.scss). Naming is
|
|
65
|
+
// concrete (the colour) — the semantic --primary mapping lives in the lib.
|
|
66
|
+
// -----------------------------------------------------------------------
|
|
67
|
+
--blue-h: 229;
|
|
68
|
+
--blue-s: 100%;
|
|
69
|
+
--blue-l: 59%;
|
|
70
|
+
|
|
71
|
+
--blue-50: hsl(var(--blue-h), 100%, 97%);
|
|
72
|
+
--blue-100: hsl(var(--blue-h), 95%, 94%);
|
|
73
|
+
--blue-200: hsl(var(--blue-h), 95%, 89%);
|
|
74
|
+
--blue-300: hsl(var(--blue-h), 98%, 82%);
|
|
75
|
+
--blue-400: hsl(var(--blue-h), 100%, 75%);
|
|
76
|
+
--blue-500: hsl(var(--blue-h), 100%, 66%);
|
|
77
|
+
--blue-600: hsl(var(--blue-h), var(--blue-s), var(--blue-l));
|
|
78
|
+
--blue-700: hsl(var(--blue-h), 85%, 52%);
|
|
79
|
+
--blue-800: hsl(var(--blue-h), 79%, 40%);
|
|
80
|
+
--blue-900: hsl(var(--blue-h), 77%, 30%);
|
|
81
|
+
|
|
82
|
+
// -----------------------------------------------------------------------
|
|
83
|
+
// Orange — focus / secondary signal
|
|
84
|
+
// -----------------------------------------------------------------------
|
|
85
|
+
--orange-50: #FFF7F0;
|
|
86
|
+
--orange-100: #FFEEDF;
|
|
87
|
+
--orange-200: #FFD9B8;
|
|
88
|
+
--orange-300: #FFC59C;
|
|
89
|
+
--orange-400: #FF9755;
|
|
90
|
+
--orange-500: #FF7A2E;
|
|
91
|
+
--orange-600: #E8631A;
|
|
92
|
+
--orange-700: #B84812;
|
|
93
|
+
--orange-800: #8A340A;
|
|
94
|
+
|
|
95
|
+
// -----------------------------------------------------------------------
|
|
96
|
+
// Green — success
|
|
97
|
+
// -----------------------------------------------------------------------
|
|
98
|
+
--green-50: #ECFAEE;
|
|
99
|
+
--green-100: #D6F3DB;
|
|
100
|
+
--green-200: #BBE8C2;
|
|
101
|
+
--green-300: #8EDA9A;
|
|
102
|
+
--green-400: #4FC368;
|
|
103
|
+
--green-500: #22A33A;
|
|
104
|
+
--green-600: #1B8A2E;
|
|
105
|
+
--green-700: #156822;
|
|
106
|
+
|
|
107
|
+
// -----------------------------------------------------------------------
|
|
108
|
+
// Yellow — attention / warning
|
|
109
|
+
// -----------------------------------------------------------------------
|
|
110
|
+
--yellow-50: #FFFBEA;
|
|
111
|
+
--yellow-100: #FEF8DC;
|
|
112
|
+
--yellow-200: #FCEFA1;
|
|
113
|
+
--yellow-300: #F9E25F;
|
|
114
|
+
--yellow-400: #F4D43A;
|
|
115
|
+
--yellow-500: #E0BE00;
|
|
116
|
+
--yellow-600: #B89B00;
|
|
117
|
+
--yellow-700: #8A7400;
|
|
118
|
+
|
|
119
|
+
// -----------------------------------------------------------------------
|
|
120
|
+
// Red — HSL-channel-split for halo derivation. #D81F1F ≈ hsl(0, 75%, 49%).
|
|
121
|
+
// The default theme maps --error onto this ramp (see styles/_tokens.scss).
|
|
122
|
+
// -----------------------------------------------------------------------
|
|
123
|
+
--red-h: 0;
|
|
124
|
+
--red-s: 75%;
|
|
125
|
+
--red-l: 49%;
|
|
126
|
+
|
|
127
|
+
--red-50: hsl(var(--red-h), 86%, 97%);
|
|
128
|
+
--red-100: hsl(var(--red-h), 86%, 95%);
|
|
129
|
+
--red-200: hsl(var(--red-h), 86%, 88%);
|
|
130
|
+
--red-300: hsl(var(--red-h), 84%, 76%);
|
|
131
|
+
--red-400: hsl(var(--red-h), 87%, 57%);
|
|
132
|
+
--red-500: hsl(var(--red-h), var(--red-s), var(--red-l));
|
|
133
|
+
--red-600: hsl(var(--red-h), 78%, 41%);
|
|
134
|
+
--red-700: hsl(var(--red-h), 78%, 31%);
|
|
135
|
+
|
|
136
|
+
// -----------------------------------------------------------------------
|
|
137
|
+
// Sky — info role ramp. A brighter, cooler blue (#3B82F6) kept distinct
|
|
138
|
+
// from the primary --blue ramp (#2F54FF) so "informational" reads apart
|
|
139
|
+
// from "primary action".
|
|
140
|
+
// -----------------------------------------------------------------------
|
|
141
|
+
--sky-50: #EFF6FF;
|
|
142
|
+
--sky-100: #DBEAFE;
|
|
143
|
+
--sky-200: #BFDBFE;
|
|
144
|
+
--sky-300: #93C5FD;
|
|
145
|
+
--sky-400: #60A5FA;
|
|
146
|
+
--sky-500: #3B82F6;
|
|
147
|
+
--sky-600: #2563EB;
|
|
148
|
+
--sky-700: #1D4ED8;
|
|
149
|
+
|
|
150
|
+
// -----------------------------------------------------------------------
|
|
151
|
+
// Shadow tint — channel-split substrate. Light theme uses a cool
|
|
152
|
+
// near-black slate (225 / 39% / 7%). A dark theme would override
|
|
153
|
+
// --shadow-tint-l to ~95% so the same alphas render as soft light
|
|
154
|
+
// glows over dark surfaces.
|
|
155
|
+
// -----------------------------------------------------------------------
|
|
156
|
+
--shadow-tint-h: 225;
|
|
157
|
+
--shadow-tint-s: 39%;
|
|
158
|
+
--shadow-tint-l: 7%;
|
|
159
|
+
}
|