@ids-group-ltd/ids-design-system 0.2.1 → 0.3.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/README.md +1 -68
- package/fesm2022/ids-group-ltd-ids-design-system.mjs +795 -372
- package/fesm2022/ids-group-ltd-ids-design-system.mjs.map +1 -1
- package/package.json +4 -7
- package/schematics/collection.json +10 -0
- package/schematics/ng-add/index.js +47 -0
- package/schematics/ng-add/schema.json +13 -0
- package/styles/_dropdown-overlay.scss +3 -3
- package/styles/_fonts.scss +11 -5
- package/styles/_layout-utils.scss +2 -2
- package/styles/_link.scss +3 -2
- package/styles/_page-grid.scss +6 -3
- package/styles/_reset.scss +6 -1
- package/styles/_scrollbar.scss +1 -1
- package/styles/_tokens-charts.scss +18 -18
- package/styles/_tokens.scss +21 -9
- package/styles/_typography.scss +21 -20
- package/themes/README.md +12 -11
- package/themes/default/_palette.scss +32 -32
- package/themes/default/_theme.scss +28 -25
- package/types/ids-group-ltd-ids-design-system.d.ts +53 -9
package/package.json
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ids-group-ltd/ids-design-system",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "IDS Group Angular design system: components, tokens, themes",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"repository": {
|
|
7
|
-
"type": "git",
|
|
8
|
-
"url": "git+https://bitbucket.org/itband/ids-design-system.git"
|
|
9
|
-
},
|
|
10
6
|
"homepage": "https://ids-ds.proto.ids-group.co.uk/",
|
|
11
7
|
"keywords": [
|
|
12
8
|
"angular",
|
|
@@ -43,5 +39,6 @@
|
|
|
43
39
|
"sideEffects": false,
|
|
44
40
|
"module": "fesm2022/ids-group-ltd-ids-design-system.mjs",
|
|
45
41
|
"typings": "types/ids-group-ltd-ids-design-system.d.ts",
|
|
46
|
-
"type": "module"
|
|
47
|
-
|
|
42
|
+
"type": "module",
|
|
43
|
+
"schematics": "./schematics/collection.json"
|
|
44
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
|
|
3
|
+
"schematics": {
|
|
4
|
+
"ng-add": {
|
|
5
|
+
"description": "Wire the IDS design system's global styles into a project.",
|
|
6
|
+
"factory": "./ng-add/index#ngAdd",
|
|
7
|
+
"schema": "./ng-add/schema.json"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ngAdd = ngAdd;
|
|
4
|
+
const DS_IMPORT = "@use '@ids-group-ltd/ids-design-system/styles/ds';";
|
|
5
|
+
/**
|
|
6
|
+
* `ng add @ids-group-ltd/ids-design-system` — wires the design system's global
|
|
7
|
+
* styles (palette + theme + tokens + globals) into the target project's styles
|
|
8
|
+
* entry. Idempotent. Components are standalone — import them directly where used.
|
|
9
|
+
*/
|
|
10
|
+
function ngAdd(options) {
|
|
11
|
+
return (tree, context) => {
|
|
12
|
+
const angularJson = tree.read('angular.json');
|
|
13
|
+
if (!angularJson) {
|
|
14
|
+
context.logger.warn('ng-add: angular.json not found — skipping styles wiring.');
|
|
15
|
+
return tree;
|
|
16
|
+
}
|
|
17
|
+
const workspace = JSON.parse(angularJson.toString());
|
|
18
|
+
const projects = workspace.projects ?? {};
|
|
19
|
+
const projectName = options.project ??
|
|
20
|
+
workspace.defaultProject ??
|
|
21
|
+
Object.keys(projects).find((name) => projects[name].projectType === 'application');
|
|
22
|
+
const stylesEntry = projectName
|
|
23
|
+
? findStylesFile(projects[projectName])
|
|
24
|
+
: undefined;
|
|
25
|
+
if (!stylesEntry || !tree.exists(stylesEntry)) {
|
|
26
|
+
context.logger.info(`ng-add: add \`${DS_IMPORT}\` to your global styles file manually.`);
|
|
27
|
+
return tree;
|
|
28
|
+
}
|
|
29
|
+
const current = tree.read(stylesEntry).toString();
|
|
30
|
+
if (current.includes(DS_IMPORT)) {
|
|
31
|
+
context.logger.info('ng-add: design system already imported — nothing to do.');
|
|
32
|
+
return tree;
|
|
33
|
+
}
|
|
34
|
+
tree.overwrite(stylesEntry, `${DS_IMPORT}\n${current}`);
|
|
35
|
+
context.logger.info(`ng-add: imported the design system into ${stylesEntry}.`);
|
|
36
|
+
return tree;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function findStylesFile(project) {
|
|
40
|
+
const styles = project?.architect?.build?.options?.styles;
|
|
41
|
+
if (!styles?.length) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
const first = styles[0];
|
|
45
|
+
const path = typeof first === 'string' ? first : first.input;
|
|
46
|
+
return path && /\.s?css$/.test(path) ? path : undefined;
|
|
47
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"$id": "IdsNgAdd",
|
|
4
|
+
"title": "IDS ng-add Options",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"project": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "Project to wire the design system into (defaults to the workspace default / first application)."
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"required": []
|
|
13
|
+
}
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
.optgroup-label {
|
|
40
40
|
display: block;
|
|
41
41
|
padding: var(--space-2) var(--space-3) var(--space-1);
|
|
42
|
-
font: var(--font-weight-semibold) var(--font-size-xs)/var(--line-height-flat) var(--font-sans);
|
|
42
|
+
font: var(--font-weight-semibold) var(--font-size-xs) / var(--line-height-flat) var(--font-sans);
|
|
43
43
|
color: var(--text-tertiary);
|
|
44
44
|
text-transform: uppercase;
|
|
45
45
|
letter-spacing: var(--letter-spacing-wide);
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
padding: var(--space-2) var(--space-2-5);
|
|
68
68
|
border: 0;
|
|
69
69
|
background: transparent;
|
|
70
|
-
font: var(--font-weight-medium) var(--font-size-s)/var(--line-height-flat) var(--font-sans);
|
|
70
|
+
font: var(--font-weight-medium) var(--font-size-s) / var(--line-height-flat) var(--font-sans);
|
|
71
71
|
color: var(--text-primary);
|
|
72
72
|
cursor: pointer;
|
|
73
73
|
border-radius: var(--radius-sm);
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
|
|
99
99
|
&:focus-visible {
|
|
100
100
|
outline: none;
|
|
101
|
-
box-shadow: var(--focus-
|
|
101
|
+
box-shadow: var(--ds-control-focus-shadow);
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
&.is-selected {
|
package/styles/_fonts.scss
CHANGED
|
@@ -1,35 +1,39 @@
|
|
|
1
1
|
// Self-hosted DS default fonts (latin subset). Consumers override --font-sans / --font-mono to swap.
|
|
2
2
|
|
|
3
3
|
@font-face {
|
|
4
|
-
font-family:
|
|
4
|
+
font-family: Mulish;
|
|
5
5
|
font-style: normal;
|
|
6
6
|
font-weight: 400;
|
|
7
7
|
font-display: swap;
|
|
8
8
|
src: url('./fonts/mulish-latin-400-normal.woff2') format('woff2');
|
|
9
9
|
}
|
|
10
|
+
|
|
10
11
|
@font-face {
|
|
11
|
-
font-family:
|
|
12
|
+
font-family: Mulish;
|
|
12
13
|
font-style: normal;
|
|
13
14
|
font-weight: 500;
|
|
14
15
|
font-display: swap;
|
|
15
16
|
src: url('./fonts/mulish-latin-500-normal.woff2') format('woff2');
|
|
16
17
|
}
|
|
18
|
+
|
|
17
19
|
@font-face {
|
|
18
|
-
font-family:
|
|
20
|
+
font-family: Mulish;
|
|
19
21
|
font-style: normal;
|
|
20
22
|
font-weight: 600;
|
|
21
23
|
font-display: swap;
|
|
22
24
|
src: url('./fonts/mulish-latin-600-normal.woff2') format('woff2');
|
|
23
25
|
}
|
|
26
|
+
|
|
24
27
|
@font-face {
|
|
25
|
-
font-family:
|
|
28
|
+
font-family: Mulish;
|
|
26
29
|
font-style: normal;
|
|
27
30
|
font-weight: 700;
|
|
28
31
|
font-display: swap;
|
|
29
32
|
src: url('./fonts/mulish-latin-700-normal.woff2') format('woff2');
|
|
30
33
|
}
|
|
34
|
+
|
|
31
35
|
@font-face {
|
|
32
|
-
font-family:
|
|
36
|
+
font-family: Mulish;
|
|
33
37
|
font-style: normal;
|
|
34
38
|
font-weight: 800;
|
|
35
39
|
font-display: swap;
|
|
@@ -43,6 +47,7 @@
|
|
|
43
47
|
font-display: swap;
|
|
44
48
|
src: url('./fonts/jetbrains-mono-latin-400-normal.woff2') format('woff2');
|
|
45
49
|
}
|
|
50
|
+
|
|
46
51
|
@font-face {
|
|
47
52
|
font-family: 'JetBrains Mono';
|
|
48
53
|
font-style: normal;
|
|
@@ -50,6 +55,7 @@
|
|
|
50
55
|
font-display: swap;
|
|
51
56
|
src: url('./fonts/jetbrains-mono-latin-500-normal.woff2') format('woff2');
|
|
52
57
|
}
|
|
58
|
+
|
|
53
59
|
@font-face {
|
|
54
60
|
font-family: 'JetBrains Mono';
|
|
55
61
|
font-style: normal;
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4); }
|
|
6
6
|
.grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-4); }
|
|
7
7
|
|
|
8
|
-
@media (
|
|
8
|
+
@media (width <= 1100px) {
|
|
9
9
|
.grid-4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
@media (
|
|
12
|
+
@media (width <= 820px) {
|
|
13
13
|
.grid-3, .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
14
14
|
}
|
package/styles/_link.scss
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
&:focus-visible {
|
|
32
32
|
outline: none;
|
|
33
|
-
box-shadow: var(--focus-
|
|
33
|
+
box-shadow: var(--ds-control-focus-shadow);
|
|
34
34
|
border-radius: var(--radius-sm);
|
|
35
35
|
text-decoration-color: var(--_link-color);
|
|
36
36
|
}
|
|
@@ -43,12 +43,13 @@
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
.icon {
|
|
46
|
-
color:
|
|
46
|
+
color: currentcolor;
|
|
47
47
|
flex-shrink: 0;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
&.quiet {
|
|
51
51
|
color: var(--text-secondary);
|
|
52
|
+
|
|
52
53
|
/* Pull the underline down to match the muted text — the base rule sets
|
|
53
54
|
text-decoration-color to the link color, which would leave a bright
|
|
54
55
|
underline under grey text at rest. */
|
package/styles/_page-grid.scss
CHANGED
|
@@ -27,24 +27,27 @@
|
|
|
27
27
|
// Mobile (default, <= 640px) — 4 columns
|
|
28
28
|
--page-gutter: var(--page-gutter-mobile);
|
|
29
29
|
--page-margin: var(--page-margin-mobile);
|
|
30
|
+
|
|
30
31
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
31
32
|
|
|
32
33
|
// Tablet (641-1024px) — 8 columns
|
|
33
|
-
@media (
|
|
34
|
+
@media (width >= 641px) {
|
|
34
35
|
--page-gutter: var(--page-gutter-tablet);
|
|
35
36
|
--page-margin: var(--page-margin-tablet);
|
|
37
|
+
|
|
36
38
|
grid-template-columns: repeat(8, minmax(0, 1fr));
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
// Desktop (1025-1440px) — 12 columns, fluid width
|
|
40
|
-
@media (
|
|
42
|
+
@media (width >= 1025px) {
|
|
41
43
|
--page-gutter: var(--page-gutter-desktop);
|
|
42
44
|
--page-margin: var(--page-margin-desktop);
|
|
45
|
+
|
|
43
46
|
grid-template-columns: repeat(12, minmax(0, 1fr));
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
// Desktop wide (>= 1441px) — 12 columns, container capped at --col-cap-content
|
|
47
|
-
@media (
|
|
50
|
+
@media (width >= 1441px) {
|
|
48
51
|
--page-gutter: var(--page-gutter-wide);
|
|
49
52
|
--page-margin: var(--page-margin-wide);
|
|
50
53
|
}
|
package/styles/_reset.scss
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
// Reset — ported from CLAUDE_DESIGN_DS/tokens.css §Base.
|
|
2
2
|
|
|
3
3
|
*, *::before, *::after { box-sizing: border-box; }
|
|
4
|
+
|
|
5
|
+
/* Opt into animating to/from intrinsic sizes (height: auto, max-content).
|
|
6
|
+
Inherited, so components can transition height:0 ↔ auto natively
|
|
7
|
+
(accordion, sidenav group) without max-height magic numbers. */
|
|
8
|
+
:root { interpolate-size: allow-keywords; }
|
|
4
9
|
html, body {
|
|
5
10
|
margin: 0;
|
|
6
11
|
font-family: var(--font-sans);
|
|
7
12
|
color: var(--text-primary);
|
|
8
13
|
background: var(--surface-canvas);
|
|
9
14
|
-webkit-font-smoothing: antialiased;
|
|
10
|
-
text-rendering:
|
|
15
|
+
text-rendering: optimizelegibility;
|
|
11
16
|
}
|
|
12
17
|
button, input, select, textarea { font-family: inherit; }
|
|
13
18
|
|
package/styles/_scrollbar.scss
CHANGED
|
@@ -14,4 +14,4 @@ html { scrollbar-width: thin; scrollbar-color: var(--scrollbar-thumb) transparen
|
|
|
14
14
|
*::-webkit-scrollbar-thumb:active { background: var(--scrollbar-thumb-active); background-clip: padding-box; }
|
|
15
15
|
|
|
16
16
|
// Global text-selection — sourced from components-extras.css line 910.
|
|
17
|
-
::selection { background: var(--select-bg, color-mix(in srgb, var(--primary) 22%, transparent)); color: var(--text-primary); }
|
|
17
|
+
::selection { background-color: var(--select-bg-color, color-mix(in srgb, var(--primary) 22%, transparent)); color: var(--text-primary); }
|
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
|
|
16
16
|
:root {
|
|
17
17
|
/* CATEGORICAL (8) ----------------------------------------- */
|
|
18
|
-
--chart-cat-1: hsl(
|
|
19
|
-
--chart-cat-2: hsl(
|
|
20
|
-
--chart-cat-3: hsl(
|
|
21
|
-
--chart-cat-4: hsl(
|
|
22
|
-
--chart-cat-5: hsl(
|
|
23
|
-
--chart-cat-6: hsl(
|
|
24
|
-
--chart-cat-7: hsl(
|
|
25
|
-
--chart-cat-8: hsl(
|
|
18
|
+
--chart-cat-1: hsl(229deg 100% 59%); /* blue (primary) */
|
|
19
|
+
--chart-cat-2: hsl(165deg 72% 38%); /* teal */
|
|
20
|
+
--chart-cat-3: hsl( 24deg 95% 55%); /* orange */
|
|
21
|
+
--chart-cat-4: hsl(330deg 82% 55%); /* magenta */
|
|
22
|
+
--chart-cat-5: hsl(45deg 95% 50%); /* amber */
|
|
23
|
+
--chart-cat-6: hsl(190deg 85% 45%); /* cyan */
|
|
24
|
+
--chart-cat-7: hsl(280deg 60% 60%); /* lavender */
|
|
25
|
+
--chart-cat-8: hsl(130deg 45% 50%); /* moss */
|
|
26
26
|
|
|
27
27
|
/* SEQUENTIAL — single-hue, light → dark */
|
|
28
28
|
--chart-seq-1: var(--blue-100);
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
matches the reference one-for-one. Explicit HSL keeps the ramp
|
|
39
39
|
independent of palette retunes — re-skinning brand/red/green
|
|
40
40
|
should not shift the dataviz colour story. */
|
|
41
|
-
--chart-div--3: hsl(
|
|
42
|
-
--chart-div--2: hsl(
|
|
43
|
-
--chart-div--1: hsl(
|
|
44
|
-
--chart-div-0: hsl(
|
|
45
|
-
--chart-div-1: hsl(
|
|
46
|
-
--chart-div-2: hsl(
|
|
47
|
-
--chart-div-3: hsl(
|
|
41
|
+
--chart-div--3: hsl(0deg 70% 40%); /* large negative (worst) */
|
|
42
|
+
--chart-div--2: hsl(0deg 60% 58%);
|
|
43
|
+
--chart-div--1: hsl(0deg 50% 80%);
|
|
44
|
+
--chart-div-0: hsl(225deg 8% 92%); /* zero */
|
|
45
|
+
--chart-div-1: hsl(140deg 35% 80%);
|
|
46
|
+
--chart-div-2: hsl(140deg 45% 55%);
|
|
47
|
+
--chart-div-3: hsl(140deg 55% 35%); /* large positive (best) */
|
|
48
48
|
|
|
49
49
|
/* AXIS / GRID / LEGEND */
|
|
50
50
|
--chart-axis-line: var(--neutral-300);
|
|
@@ -56,10 +56,10 @@
|
|
|
56
56
|
--chart-axis-fs: var(--font-size-2xs);
|
|
57
57
|
|
|
58
58
|
/* HIGHLIGHT / HOVER */
|
|
59
|
-
--chart-hover-bg:
|
|
59
|
+
--chart-hover-bg-color: hsl(225deg 39% 7% / 4%);
|
|
60
60
|
--chart-cursor-line: var(--neutral-400);
|
|
61
|
-
--chart-tooltip-bg: var(--neutral-900);
|
|
62
|
-
--chart-tooltip-
|
|
61
|
+
--chart-tooltip-bg-color: var(--neutral-900);
|
|
62
|
+
--chart-tooltip-text-color: var(--neutral-0);
|
|
63
63
|
--chart-tooltip-border: var(--neutral-700);
|
|
64
64
|
|
|
65
65
|
/* DIMENSIONS */
|
package/styles/_tokens.scss
CHANGED
|
@@ -84,17 +84,18 @@
|
|
|
84
84
|
The alpha values stay constant across themes — only the
|
|
85
85
|
hue/saturation/lightness become configurable.
|
|
86
86
|
============================================================ */
|
|
87
|
+
|
|
87
88
|
/* --shadow-tint-h/s/l live in themes/default/_palette.scss — palette-level
|
|
88
89
|
so dark palettes can override --shadow-tint-l → ~95% for soft light glows. */
|
|
89
90
|
|
|
90
|
-
--shadow-1: 0 1px 2px
|
|
91
|
-
0 1px 3px
|
|
92
|
-
--shadow-2: 0 4px 8px
|
|
93
|
-
0 4px 16px
|
|
94
|
-
--shadow-3: 0 8px 16px
|
|
95
|
-
0 16px 32px
|
|
96
|
-
--shadow-4: 0 16px 32px
|
|
97
|
-
0 24px 48px
|
|
91
|
+
--shadow-1: 0 1px 2px hsl(var(--shadow-tint-h) var(--shadow-tint-s) var(--shadow-tint-l) / 6%),
|
|
92
|
+
0 1px 3px hsl(var(--shadow-tint-h) var(--shadow-tint-s) var(--shadow-tint-l) / 8%);
|
|
93
|
+
--shadow-2: 0 4px 8px hsl(var(--shadow-tint-h) var(--shadow-tint-s) var(--shadow-tint-l) / 6%),
|
|
94
|
+
0 4px 16px hsl(var(--shadow-tint-h) var(--shadow-tint-s) var(--shadow-tint-l) / 10%);
|
|
95
|
+
--shadow-3: 0 8px 16px hsl(var(--shadow-tint-h) var(--shadow-tint-s) var(--shadow-tint-l) / 8%),
|
|
96
|
+
0 16px 32px hsl(var(--shadow-tint-h) var(--shadow-tint-s) var(--shadow-tint-l) / 14%);
|
|
97
|
+
--shadow-4: 0 16px 32px hsl(var(--shadow-tint-h) var(--shadow-tint-s) var(--shadow-tint-l) / 12%),
|
|
98
|
+
0 24px 48px hsl(var(--shadow-tint-h) var(--shadow-tint-s) var(--shadow-tint-l) / 18%);
|
|
98
99
|
--shadow-popover: var(--shadow-2);
|
|
99
100
|
--shadow-modal: var(--shadow-4);
|
|
100
101
|
--shadow-toast: var(--shadow-3);
|
|
@@ -169,6 +170,7 @@
|
|
|
169
170
|
--opacity-scrim: 0.55; /* modal/drawer backdrop overlay (light theme) */
|
|
170
171
|
--opacity-state-hover: 0.08; /* hover layer over surface (overlay vs surface swap) */
|
|
171
172
|
--opacity-state-pressed: 0.16; /* active/pressed layer */
|
|
173
|
+
--opacity-state-active: 0.24; /* deepest pressed layer (e.g. tag close on :active) */
|
|
172
174
|
|
|
173
175
|
/* ============================================================
|
|
174
176
|
Breakpoints
|
|
@@ -202,7 +204,7 @@
|
|
|
202
204
|
--scrollbar-thumb: var(--neutral-300);
|
|
203
205
|
--scrollbar-thumb-hover: var(--neutral-400);
|
|
204
206
|
--scrollbar-thumb-active: var(--neutral-500);
|
|
205
|
-
--select-bg: color-mix(in srgb, var(--primary) 22%, transparent);
|
|
207
|
+
--select-bg-color: color-mix(in srgb, var(--primary) 22%, transparent);
|
|
206
208
|
--col-cap-text: 720px;
|
|
207
209
|
--col-cap-content: 1280px;
|
|
208
210
|
|
|
@@ -282,6 +284,15 @@
|
|
|
282
284
|
default their own --ds-*-pad to this, so a consumer retunes all at once. */
|
|
283
285
|
--ds-container-pad: var(--space-6);
|
|
284
286
|
|
|
287
|
+
/* Shared focus indicators — components default their own --ds-*-focus-shadow
|
|
288
|
+
to these, so a consumer retunes focus per-group at once (field vs control)
|
|
289
|
+
or per-component. Two families: fields get the soft halo, interactive
|
|
290
|
+
controls/nav get the crisp ring (see themes/default/_theme.scss). */
|
|
291
|
+
--ds-field-focus-shadow: var(--focus-field);
|
|
292
|
+
--ds-field-focus-shadow-error: var(--focus-field-error);
|
|
293
|
+
--ds-control-focus-shadow: var(--focus-ring);
|
|
294
|
+
--ds-control-focus-shadow-error: var(--focus-ring-error);
|
|
295
|
+
|
|
285
296
|
/* Table cell padding — density-aware, consumed by .tbl td/th. */
|
|
286
297
|
--table-cell-pad-x: var(--space-4);
|
|
287
298
|
--table-cell-pad-y: var(--space-3);
|
|
@@ -597,6 +608,7 @@
|
|
|
597
608
|
}
|
|
598
609
|
[data-density="cozy"] {
|
|
599
610
|
--hit-cozy: 40px;
|
|
611
|
+
|
|
600
612
|
/* defaults */
|
|
601
613
|
}
|
|
602
614
|
[data-density="comfy"] {
|
package/styles/_typography.scss
CHANGED
|
@@ -1,30 +1,31 @@
|
|
|
1
1
|
// Type utility classes — ported from CLAUDE_DESIGN_DS/tokens.css §Type utilities.
|
|
2
2
|
// These are GLOBAL by design — consumers apply them via class.
|
|
3
3
|
|
|
4
|
-
.t-display { font: var(--font-weight-extrabold) var(--font-size-display)/var(--line-height-tight) var(--font-display); letter-spacing: var(--letter-spacing-tight); }
|
|
5
|
-
.t-h1 { font: var(--font-weight-extrabold) var(--font-size-h1)/var(--line-height-tight) var(--font-heading); letter-spacing: var(--letter-spacing-tight); }
|
|
6
|
-
.t-h2 { font: var(--font-weight-extrabold) var(--font-size-h2)/var(--line-height-snug) var(--font-heading); letter-spacing: var(--letter-spacing-snug); }
|
|
7
|
-
.t-h3 { font: var(--font-weight-extrabold) var(--font-size-h3)/var(--line-height-snug) var(--font-heading); letter-spacing: var(--letter-spacing-snug); }
|
|
8
|
-
.t-h4 { font: var(--font-weight-bold) var(--font-size-h4)/var(--line-height-snug) var(--font-heading); }
|
|
9
|
-
.t-h5 { font: var(--font-weight-bold) var(--font-size-h5)/var(--line-height-snug) var(--font-heading); }
|
|
10
|
-
.t-card-title { font: var(--font-weight-bold) var(--card-title-fs)/var(--line-height-snug) var(--font-heading); margin: 0; color: var(--text-primary); }
|
|
11
|
-
.t-l { font: var(--font-weight-regular) var(--font-size-l)/var(--line-height-base) var(--font-sans); }
|
|
12
|
-
.t-l-bold { font: var(--font-weight-bold) var(--font-size-l)/var(--line-height-base) var(--font-sans); }
|
|
13
|
-
.t-m { font: var(--font-weight-regular) var(--font-size-m)/var(--line-height-base) var(--font-sans); }
|
|
14
|
-
.t-m-bold { font: var(--font-weight-bold) var(--font-size-m)/var(--line-height-base) var(--font-sans); }
|
|
15
|
-
.t-s { font: var(--font-weight-regular) var(--font-size-s)/var(--line-height-base) var(--font-sans); }
|
|
16
|
-
.t-s-bold { font: var(--font-weight-bold) var(--font-size-s)/var(--line-height-base) var(--font-sans); }
|
|
17
|
-
.t-xs { font: var(--font-weight-regular) var(--font-size-xs)/var(--line-height-base) var(--font-sans); }
|
|
18
|
-
.t-xs-bold { font: var(--font-weight-bold) var(--font-size-xs)/var(--line-height-base) var(--font-sans); }
|
|
19
|
-
.t-overline { font: var(--font-weight-bold) var(--font-size-2xs)/var(--line-height-base) var(--font-sans); letter-spacing: var(--letter-spacing-wider); text-transform: uppercase; color: var(--text-tertiary); }
|
|
20
|
-
.t-caption { font: var(--font-weight-regular) var(--font-size-xs)/var(--line-height-base) var(--font-sans); color: var(--text-tertiary); }
|
|
21
|
-
.t-mono
|
|
22
|
-
.t-mono-
|
|
4
|
+
.t-display { font: var(--font-weight-extrabold) var(--font-size-display) / var(--line-height-tight) var(--font-display); letter-spacing: var(--letter-spacing-tight); }
|
|
5
|
+
.t-h1 { font: var(--font-weight-extrabold) var(--font-size-h1) / var(--line-height-tight) var(--font-heading); letter-spacing: var(--letter-spacing-tight); }
|
|
6
|
+
.t-h2 { font: var(--font-weight-extrabold) var(--font-size-h2) / var(--line-height-snug) var(--font-heading); letter-spacing: var(--letter-spacing-snug); }
|
|
7
|
+
.t-h3 { font: var(--font-weight-extrabold) var(--font-size-h3) / var(--line-height-snug) var(--font-heading); letter-spacing: var(--letter-spacing-snug); }
|
|
8
|
+
.t-h4 { font: var(--font-weight-bold) var(--font-size-h4) / var(--line-height-snug) var(--font-heading); }
|
|
9
|
+
.t-h5 { font: var(--font-weight-bold) var(--font-size-h5) / var(--line-height-snug) var(--font-heading); }
|
|
10
|
+
.t-card-title { font: var(--font-weight-bold) var(--card-title-fs) / var(--line-height-snug) var(--font-heading); margin: 0; color: var(--text-primary); }
|
|
11
|
+
.t-l { font: var(--font-weight-regular) var(--font-size-l) / var(--line-height-base) var(--font-sans); }
|
|
12
|
+
.t-l-bold { font: var(--font-weight-bold) var(--font-size-l) / var(--line-height-base) var(--font-sans); }
|
|
13
|
+
.t-m { font: var(--font-weight-regular) var(--font-size-m) / var(--line-height-base) var(--font-sans); }
|
|
14
|
+
.t-m-bold { font: var(--font-weight-bold) var(--font-size-m) / var(--line-height-base) var(--font-sans); }
|
|
15
|
+
.t-s { font: var(--font-weight-regular) var(--font-size-s) / var(--line-height-base) var(--font-sans); }
|
|
16
|
+
.t-s-bold { font: var(--font-weight-bold) var(--font-size-s) / var(--line-height-base) var(--font-sans); }
|
|
17
|
+
.t-xs { font: var(--font-weight-regular) var(--font-size-xs) / var(--line-height-base) var(--font-sans); }
|
|
18
|
+
.t-xs-bold { font: var(--font-weight-bold) var(--font-size-xs) / var(--line-height-base) var(--font-sans); }
|
|
19
|
+
.t-overline { font: var(--font-weight-bold) var(--font-size-2xs) / var(--line-height-base) var(--font-sans); letter-spacing: var(--letter-spacing-wider); text-transform: uppercase; color: var(--text-tertiary); }
|
|
20
|
+
.t-caption { font: var(--font-weight-regular) var(--font-size-xs) / var(--line-height-base) var(--font-sans); color: var(--text-tertiary); }
|
|
21
|
+
.t-mono { font: var(--font-weight-medium) var(--font-size-mono) / var(--line-height-base) var(--font-mono); }
|
|
22
|
+
.t-mono-inline { font: var(--font-weight-regular) var(--font-size-mono) / 1 var(--font-mono); background: var(--surface-secondary); color: var(--text-primary); padding: 1px var(--space-1); border-radius: var(--radius-sm); }
|
|
23
|
+
.t-mono-block { font: var(--font-weight-regular) var(--font-size-mono) / var(--line-height-loose) var(--font-mono); background: var(--surface-secondary); border: var(--border-width-default) solid var(--border-divider); border-radius: var(--radius-md); padding: var(--space-3) var(--space-4); }
|
|
23
24
|
|
|
24
25
|
.sr-only {
|
|
25
26
|
position: absolute !important;
|
|
26
27
|
width: 1px; height: 1px;
|
|
27
28
|
padding: 0; margin: -1px;
|
|
28
|
-
overflow: hidden; clip:
|
|
29
|
+
overflow: hidden; clip-path: inset(50%);
|
|
29
30
|
white-space: nowrap; border: 0;
|
|
30
31
|
}
|
package/themes/README.md
CHANGED
|
@@ -4,15 +4,15 @@ Colour lives in two files here: a **palette** (defines the concrete colours) and
|
|
|
4
4
|
|
|
5
5
|
## Architecture: three tiers
|
|
6
6
|
|
|
7
|
-
| Tier
|
|
8
|
-
|
|
9
|
-
| **Tier 1 — Palette** (defines colours) | `themes/<name>/_palette.scss`
|
|
10
|
-
| **Tier 2 — Theme** (sets roles)
|
|
11
|
-
| **Tier 3 — Component / scale**
|
|
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-color`, `--duration-fast`, `--layer-modal` | Components (their own) |
|
|
12
12
|
|
|
13
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
14
|
|
|
15
|
-
**Why split palette from theme:** the palette says
|
|
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
16
|
|
|
17
17
|
## Available palette + theme
|
|
18
18
|
|
|
@@ -20,6 +20,7 @@ Colour lives in two files here: a **palette** (defines the concrete colours) and
|
|
|
20
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
21
|
|
|
22
22
|
Future (each a `themes/<name>/` folder with `_palette.scss` + `_theme.scss`):
|
|
23
|
+
|
|
23
24
|
- `themes/dark/` — Dark-mode flip (`--shadow-tint-l` → ~95%, neutrals inverted, etc.).
|
|
24
25
|
- `themes/high-contrast/` — A11y boost.
|
|
25
26
|
|
|
@@ -29,15 +30,15 @@ Future (each a `themes/<name>/` folder with `_palette.scss` + `_theme.scss`):
|
|
|
29
30
|
|
|
30
31
|
```scss
|
|
31
32
|
// Consumer styles.scss
|
|
32
|
-
@use 'styles/ds';
|
|
33
|
+
@use 'styles/ds'; // bundles default palette + theme + tokens + reset + ...
|
|
33
34
|
```
|
|
34
35
|
|
|
35
36
|
### Option B — explicit theme choice
|
|
36
37
|
|
|
37
38
|
```scss
|
|
38
39
|
// Consumer styles.scss
|
|
39
|
-
@use 'themes/dark/palette';
|
|
40
|
-
@use 'themes/dark/theme';
|
|
40
|
+
@use 'themes/dark/palette'; // pick a non-default theme: palette …
|
|
41
|
+
@use 'themes/dark/theme'; // … then its role map
|
|
41
42
|
@use 'styles/tokens';
|
|
42
43
|
@use 'styles/reset';
|
|
43
44
|
@use 'styles/typography';
|
|
@@ -52,8 +53,8 @@ Palette + theme must come BEFORE `tokens` so role aliases resolve.
|
|
|
52
53
|
|
|
53
54
|
```scss
|
|
54
55
|
// Consumer styles.scss
|
|
55
|
-
@use 'styles/ds';
|
|
56
|
-
@use './app/styles/brand-manage-my';
|
|
56
|
+
@use 'styles/ds'; // default theme + DS
|
|
57
|
+
@use './app/styles/brand-manage-my'; // overrides palette/roles via [data-brand]
|
|
57
58
|
```
|
|
58
59
|
|
|
59
60
|
This is the mm-broker pattern: load DS (default theme included), then overlay a brand at a more-specific selector (`[data-brand="manage-my"]`).
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
// 210 → 227 toward the brand hue (229) as it darkens; chroma follows a
|
|
23
23
|
// designed U-curve (S 40% → 12% → 37%). Appearance name, Carbon-style.
|
|
24
24
|
// -----------------------------------------------------------------------
|
|
25
|
-
--cool-gray-0: #
|
|
25
|
+
--cool-gray-0: #FFF;
|
|
26
26
|
--cool-gray-50: #F8FAFC;
|
|
27
27
|
--cool-gray-100: #F1F4F9;
|
|
28
28
|
--cool-gray-150: #E8ECF2;
|
|
@@ -44,19 +44,19 @@
|
|
|
44
44
|
// cool-gray to within rounding.
|
|
45
45
|
// -----------------------------------------------------------------------
|
|
46
46
|
--neutral-h: var(--primary-h, var(--blue-h));
|
|
47
|
-
--brand-gray-0: #
|
|
48
|
-
--brand-gray-50: hsl(calc(var(--neutral-h) - 19)
|
|
49
|
-
--brand-gray-100: hsl(calc(var(--neutral-h) - 12)
|
|
50
|
-
--brand-gray-150: hsl(calc(var(--neutral-h) - 13)
|
|
51
|
-
--brand-gray-200: hsl(calc(var(--neutral-h) - 10)
|
|
52
|
-
--brand-gray-300: hsl(calc(var(--neutral-h) - 10)
|
|
53
|
-
--brand-gray-400: hsl(calc(var(--neutral-h) - 8)
|
|
54
|
-
--brand-gray-500: hsl(calc(var(--neutral-h) - 6)
|
|
55
|
-
--brand-gray-600: hsl(calc(var(--neutral-h) - 5)
|
|
56
|
-
--brand-gray-700: hsl(calc(var(--neutral-h) - 4)
|
|
57
|
-
--brand-gray-800: hsl(calc(var(--neutral-h) - 3)
|
|
58
|
-
--brand-gray-900: hsl(calc(var(--neutral-h) - 2)
|
|
59
|
-
--brand-gray-950: hsl(calc(var(--neutral-h) - 3)
|
|
47
|
+
--brand-gray-0: #FFF;
|
|
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
60
|
|
|
61
61
|
// -----------------------------------------------------------------------
|
|
62
62
|
// Blue — defined as HSL channels so we can compose hsla() halos and tints
|
|
@@ -68,16 +68,16 @@
|
|
|
68
68
|
--blue-s: 100%;
|
|
69
69
|
--blue-l: 59%;
|
|
70
70
|
|
|
71
|
-
--blue-50: hsl(var(--blue-h)
|
|
72
|
-
--blue-100: hsl(var(--blue-h)
|
|
73
|
-
--blue-200: hsl(var(--blue-h)
|
|
74
|
-
--blue-300: hsl(var(--blue-h)
|
|
75
|
-
--blue-400: hsl(var(--blue-h)
|
|
76
|
-
--blue-500: hsl(var(--blue-h)
|
|
77
|
-
--blue-600: hsl(var(--blue-h)
|
|
78
|
-
--blue-700: hsl(var(--blue-h)
|
|
79
|
-
--blue-800: hsl(var(--blue-h)
|
|
80
|
-
--blue-900: hsl(var(--blue-h)
|
|
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
81
|
|
|
82
82
|
// -----------------------------------------------------------------------
|
|
83
83
|
// Orange — focus / secondary signal
|
|
@@ -124,14 +124,14 @@
|
|
|
124
124
|
--red-s: 75%;
|
|
125
125
|
--red-l: 49%;
|
|
126
126
|
|
|
127
|
-
--red-50: hsl(var(--red-h)
|
|
128
|
-
--red-100: hsl(var(--red-h)
|
|
129
|
-
--red-200: hsl(var(--red-h)
|
|
130
|
-
--red-300: hsl(var(--red-h)
|
|
131
|
-
--red-400: hsl(var(--red-h)
|
|
132
|
-
--red-500: hsl(var(--red-h)
|
|
133
|
-
--red-600: hsl(var(--red-h)
|
|
134
|
-
--red-700: hsl(var(--red-h)
|
|
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
135
|
|
|
136
136
|
// -----------------------------------------------------------------------
|
|
137
137
|
// Sky — info role ramp. A brighter, cooler blue (#3B82F6) kept distinct
|