@kiva/kv-tokens 3.7.5 → 4.0.0-next.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 CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  The package contains
4
4
 
5
- - A JSON file specifying the design definitions of Kiva's style guide.
5
+ - Design token definitions authored as [W3C DTCG](https://design-tokens.github.io/community-group/format/) JSON.
6
+ - A [Style Dictionary](https://styledictionary.com) build that emits JS, CSS, and SCSS artifacts from those tokens.
6
7
  - A custom Tailwind configuration set to Kiva's style guide that can be used as a preset for your Tailwind project.
7
8
 
8
9
  ## Install
@@ -17,6 +18,12 @@ import designTokens from '@kiva/kv-tokens';
17
18
  const primaryTextColor = designTokens.colors.theme.DEFAULT.text.primary;
18
19
  ```
19
20
 
21
+ You can also import the generated tokens module directly (flat named exports plus the nested default):
22
+
23
+ ```js
24
+ import tokens, { colorBrandDefault } from '@kiva/kv-tokens/tokens';
25
+ ```
26
+
20
27
  ## Using the Tailwind Preset
21
28
 
22
29
  ```js
@@ -47,6 +54,46 @@ Our Tailwind config has some differences to the standard install. Notably
47
54
  See our [Storybook](https://main--608b4cf87f686c00213841b1.chromatic.com/?path=/docs/base-styling-primitives--primitives) for possible names.
48
55
  - Our spacing scale is based on 8px rather Tailwind's default 4px.
49
56
 
57
+ ## Package Exports
58
+
59
+ | Subpath | Resolves to | Use for |
60
+ | ------------------------------ | --------------------------- | ----------------------------------------- |
61
+ | `@kiva/kv-tokens` | `index.js` | Default: tokens object + theme/tailwind helpers |
62
+ | `@kiva/kv-tokens/tokens` | `dist/js/tokens.js` | Generated JS tokens (flat + nested) |
63
+ | `@kiva/kv-tokens/tailwind` | `configs/tailwind.config.js`| Tailwind preset |
64
+ | `@kiva/kv-tokens/css` | `dist/css/tokens.css` | Themed CSS custom properties |
65
+ | `@kiva/kv-tokens/scss` | `dist/scss/tokens.scss` | SCSS `$variable` map |
66
+
67
+ ## Editing Tokens
68
+
69
+ Tokens live under [`tokens/`](tokens/) as DTCG JSON:
70
+
71
+ - [`tokens/core/`](tokens/core/) — primitive values (colors, sizes, typography, z-index, opacity).
72
+ - [`tokens/semantic/themes/`](tokens/semantic/themes/) — themed semantic tokens referencing primitives.
73
+
74
+ To update a token, edit the relevant JSON file and run:
75
+
76
+ ```sh
77
+ npm run build
78
+ ```
79
+
80
+ This invokes Style Dictionary (via [`build/style-dictionary.config.js`](build/style-dictionary.config.js)) to regenerate the `dist/js/`, `dist/css/`, and `dist/scss/` artifacts, then runs [`build/build.js`](build/build.js) to copy fonts and emit the heading-underline SVG sprite.
81
+
82
+ ### How the Build Works
83
+
84
+ Custom Style Dictionary formats and transforms live in [`build/formats/`](build/formats/) and [`build/transforms/`](build/transforms/):
85
+
86
+ - `kiva/js-tokens` — emits both flat named exports (`colorBrandDefault`) and a nested default export that matches the runtime shape used by `kivaColors.js`, `kivaTypography.js`, and `tailwind.config.js`.
87
+ - `kiva/css-themes` — emits a `:root` block for the default theme plus `[data-theme="..."]` blocks for each variant. Colors become RGB triples (`R, G, B`) so consumers can compose opacity with `rgb(var(--text-primary) / 50%)`.
88
+ - `kiva/dimension-to-number` — unwraps DTCG `{ value, unit }` dimension objects back to raw numbers for JS consumers.
89
+
90
+ ## Migrating from v3.x
91
+
92
+ - **The legacy `tw-exported-vars.scss` artifact (at `dist/kvui/tw-exported-vars.scss`) is no longer generated.** Import SCSS variables from `@kiva/kv-tokens/scss` instead.
93
+ - **SCSS variable names have changed** to Style Dictionary's kebab-case convention. For example, `$colors-brand-default` is now `$color-brand-default`. Full paths are generated from the token tree.
94
+ - **The hand-authored `primitives.js` has been removed.** The default export of `@kiva/kv-tokens` still resolves to the same nested shape (e.g. `designTokens.colors.theme.DEFAULT.text.primary`), so existing JS/Vue imports continue to work unchanged.
95
+ - **Token edits now flow through `tokens/*.json`.** If you previously patched `primitives.js` directly, move those values into the appropriate JSON file under `tokens/core/` or `tokens/semantic/themes/`.
96
+
50
97
  ## Contribution Guidelines
51
98
 
52
99
  The Kiva UI project is bound by a [Code of Conduct](https://github.com/kiva/ui/blob/master/code_of_conduct.md).
package/build/build.js ADDED
@@ -0,0 +1,23 @@
1
+ import fs from 'node:fs';
2
+ import { generateExternalSVG } from '../configs/kivaHeadingUnderline.js';
3
+
4
+ // Note: dir is relative to the root of the kv-tokens package
5
+ const dir = '../../dist/kvui';
6
+
7
+ // Create dist folder
8
+ if (!fs.existsSync(dir)) {
9
+ fs.mkdirSync(dir, { recursive: true });
10
+ }
11
+
12
+ // Copy fonts to dist folder
13
+ const fontsDir = './assets/fonts';
14
+ const fontFiles = fs.readdirSync(fontsDir).filter((file) => file.endsWith('.woff2'));
15
+ fontFiles.forEach((file) => {
16
+ const srcPath = `${fontsDir}/${file}`;
17
+ const destPath = `${dir}/${file}`;
18
+ fs.copyFileSync(srcPath, destPath);
19
+ });
20
+
21
+ // Generate Heading Underline SVG
22
+ const svg = generateExternalSVG();
23
+ fs.writeFileSync(`${dir}/heading-underline.svg`, svg);
@@ -0,0 +1,60 @@
1
+ // Emit a CSS file with :root (DEFAULT theme) plus [data-theme="..."] blocks
2
+ // for every other theme found under theme tokens.
3
+
4
+ const hexToRGB = (hex) => {
5
+ const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
6
+ const replacedHex = hex.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b);
7
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(replacedHex);
8
+ return `${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}`;
9
+ };
10
+
11
+ const CATEGORY_TO_PREFIX = {
12
+ text: 'text',
13
+ background: 'bg',
14
+ border: 'border',
15
+ 'heading-underline': 'heading-underline',
16
+ };
17
+
18
+ const blockFor = (themeTokens) => {
19
+ const lines = [];
20
+ Object.keys(themeTokens).forEach((category) => {
21
+ const prefix = CATEGORY_TO_PREFIX[category] ?? category;
22
+ const props = themeTokens[category];
23
+ Object.keys(props).forEach((prop) => {
24
+ const tokenLeaf = props[prop];
25
+ const raw = tokenLeaf.$value ?? tokenLeaf.value;
26
+ const name = `--${prefix}-${prop}`;
27
+ if (category === 'heading-underline') {
28
+ lines.push(`\t${name}: url('/kvui/heading-underline.svg${raw}');`);
29
+ } else {
30
+ lines.push(`\t${name}: ${hexToRGB(raw)};`);
31
+ }
32
+ });
33
+ });
34
+ return lines.join('\n');
35
+ };
36
+
37
+ const cssThemesFormat = {
38
+ name: 'kiva/css-themes',
39
+ format: ({ dictionary }) => {
40
+ const themes = dictionary.tokens.theme ?? {};
41
+ const out = ['/* Do not edit directly. Generated by Style Dictionary. */', ''];
42
+ const defaultTheme = themes.DEFAULT;
43
+ if (defaultTheme) {
44
+ out.push(':root {');
45
+ out.push(blockFor(defaultTheme));
46
+ out.push('}');
47
+ out.push('');
48
+ }
49
+ Object.keys(themes).forEach((name) => {
50
+ if (name === 'DEFAULT') return;
51
+ out.push(`[data-theme="${name}"] {`);
52
+ out.push(blockFor(themes[name]));
53
+ out.push('}');
54
+ out.push('');
55
+ });
56
+ return out.join('\n');
57
+ },
58
+ };
59
+
60
+ export default cssThemesFormat;
@@ -0,0 +1,91 @@
1
+ // Style Dictionary v4 custom format.
2
+ // Emits:
3
+ // 1. Flat named exports: `export const colorBrandDefault = '#2AA967';`
4
+ // 2. A nested default export matching the legacy primitives.js shape.
5
+
6
+ const DTCG_TO_LEGACY_KEY = {
7
+ color: 'colors',
8
+ 'font-family': 'fonts',
9
+ 'font-weight': 'fontWeights',
10
+ 'font-size': 'fontSizes',
11
+ 'semantic-font-size': 'semanticFontSizes',
12
+ 'line-height': 'lineHeights',
13
+ 'line-height-absolute': 'lineHeightsAbsolute',
14
+ 'letter-spacing': 'letterSpacings',
15
+ 'border-width': 'borderWidths',
16
+ breakpoint: 'breakpoints',
17
+ radius: 'radii',
18
+ 'z-index': 'zIndices',
19
+ space: 'space',
20
+ opacity: 'opacity',
21
+ theme: 'theme',
22
+ };
23
+
24
+ const restoreKey = (key) => {
25
+ if (/^n\d+_\d+$/.test(key)) return `-${key.slice(1).replace('_', '.')}`;
26
+ if (/^n\d+$/.test(key)) return `-${key.slice(1)}`;
27
+ if (/^\d+_\d+$/.test(key)) return key.replace('_', '.');
28
+ return key;
29
+ };
30
+
31
+ // camelCase that preserves underscores as digit separators so `space.1_5`
32
+ // and `space.15` don't collide. Dashes split into word boundaries.
33
+ const camelCase = (parts) => parts
34
+ .flatMap((p) => String(p).split('-').filter(Boolean))
35
+ .map((w, i) => {
36
+ const lower = w.toLowerCase();
37
+ if (i === 0) return lower;
38
+ return lower.charAt(0).toUpperCase() + lower.slice(1);
39
+ })
40
+ .join('');
41
+
42
+ const isLeaf = (node) => node && typeof node === 'object' && '$value' in node;
43
+
44
+ const buildNested = (tokens) => {
45
+ const out = {};
46
+ const walk = (node, path) => {
47
+ if (isLeaf(node)) {
48
+ const legacyPath = path.map((seg, i) => (i === 0 ? (DTCG_TO_LEGACY_KEY[seg] || seg) : restoreKey(seg)));
49
+ const finalPath = legacyPath[0] === 'theme' ? ['colors', ...legacyPath] : legacyPath;
50
+ let cursor = out;
51
+ for (let i = 0; i < finalPath.length - 1; i += 1) {
52
+ cursor[finalPath[i]] = cursor[finalPath[i]] ?? {};
53
+ cursor = cursor[finalPath[i]];
54
+ }
55
+ cursor[finalPath[finalPath.length - 1]] = node.$value;
56
+ return;
57
+ }
58
+ if (node && typeof node === 'object') {
59
+ Object.keys(node).forEach((k) => walk(node[k], [...path, k]));
60
+ }
61
+ };
62
+ walk(tokens, []);
63
+ out.colors = out.colors ?? {};
64
+ out.shadows = out.shadows ?? {};
65
+ return out;
66
+ };
67
+
68
+ const jsTokensFormat = {
69
+ name: 'kiva/js-tokens',
70
+ format: ({ dictionary }) => {
71
+ const flatLines = dictionary.allTokens.map((t) => {
72
+ const name = camelCase(t.path);
73
+ const v = t.$value;
74
+ const value = typeof v === 'number' ? v : JSON.stringify(v);
75
+ return `export const ${name} = ${value};`;
76
+ });
77
+ const nested = buildNested(dictionary.tokens);
78
+ return [
79
+ '// Do not edit directly. Generated by Style Dictionary.',
80
+ '',
81
+ ...flatLines,
82
+ '',
83
+ `const tokens = ${JSON.stringify(nested, null, '\t')};`,
84
+ '',
85
+ 'export default tokens;',
86
+ '',
87
+ ].join('\n');
88
+ },
89
+ };
90
+
91
+ export default jsTokensFormat;
@@ -0,0 +1,45 @@
1
+ import StyleDictionary from 'style-dictionary';
2
+ import jsTokensFormat from './formats/js-tokens.js';
3
+ import cssThemesFormat from './formats/css-themes.js';
4
+ import dimensionToNumberTransform from './transforms/dimension-to-number.js';
5
+
6
+ StyleDictionary.registerFormat(jsTokensFormat);
7
+ StyleDictionary.registerFormat(cssThemesFormat);
8
+ StyleDictionary.registerTransform(dimensionToNumberTransform);
9
+
10
+ export default {
11
+ source: ['tokens/**/*.json'],
12
+ platforms: {
13
+ js: {
14
+ transforms: ['attribute/cti', 'name/kebab', 'kiva/dimension-to-number'],
15
+ buildPath: 'dist/js/',
16
+ files: [
17
+ {
18
+ destination: 'tokens.js',
19
+ format: 'kiva/js-tokens',
20
+ },
21
+ ],
22
+ },
23
+ css: {
24
+ transforms: ['attribute/cti', 'name/kebab'],
25
+ buildPath: 'dist/css/',
26
+ files: [
27
+ {
28
+ destination: 'tokens.css',
29
+ format: 'kiva/css-themes',
30
+ },
31
+ ],
32
+ },
33
+ scss: {
34
+ transforms: ['attribute/cti', 'name/kebab', 'kiva/dimension-to-number'],
35
+ buildPath: 'dist/scss/',
36
+ files: [
37
+ {
38
+ destination: 'tokens.scss',
39
+ format: 'scss/variables',
40
+ options: { outputReferences: false },
41
+ },
42
+ ],
43
+ },
44
+ },
45
+ };
@@ -0,0 +1,17 @@
1
+ // Transform: dimension objects -> raw numeric value.
2
+ // DTCG encodes dimensions as { value: 16, unit: 'px' }; legacy primitives.js
3
+ // stored them as raw numbers. Strip the unit for JS output.
4
+
5
+ const dimensionToNumberTransform = {
6
+ name: 'kiva/dimension-to-number',
7
+ type: 'value',
8
+ transitive: true,
9
+ filter: (token) => token.$type === 'dimension' || token.type === 'dimension',
10
+ transform: (token) => {
11
+ const v = token.$value ?? token.value;
12
+ if (v && typeof v === 'object' && 'value' in v) return v.value;
13
+ return v;
14
+ },
15
+ };
16
+
17
+ export default dimensionToNumberTransform;
@@ -1,5 +1,5 @@
1
1
  import { hexToRGB } from './util.js';
2
- import designTokens from '../primitives.js';
2
+ import designTokens from '../dist/js/tokens.js';
3
3
 
4
4
  const {
5
5
  DEFAULT: defaultThemeTokens,
@@ -1,4 +1,4 @@
1
- import designTokens from '../primitives.js';
1
+ import designTokens from '../dist/js/tokens.js';
2
2
  import { base64 } from './util.js';
3
3
  import underlinePath from './underlinePath.js';
4
4
 
@@ -1,5 +1,5 @@
1
1
  import { rem, em } from './util.js';
2
- import designTokens from '../primitives.js';
2
+ import designTokens from '../dist/js/tokens.js';
3
3
 
4
4
  const {
5
5
  fonts,
@@ -533,7 +533,7 @@ export const textStyles = (() => {
533
533
 
534
534
  const textCaption = {
535
535
  fontFamily: fonts.sans,
536
- fontWeight: fontWeights.normal,
536
+ fontWeight: fontWeights.light,
537
537
  fontSize: rem(semanticFontSizes.small.small),
538
538
  letterSpacing: em(letterSpacings.normal, semanticFontSizes.small.small),
539
539
  lineHeight: em(lineHeightsAbsolute.caption.sm, semanticFontSizes.small.small),
@@ -7,7 +7,7 @@ import {
7
7
  webFonts,
8
8
  } from './kivaTypography.js';
9
9
  import { defaultTheme, buildColorChoices } from './kivaColors.js';
10
- import designTokens from '../primitives.js';
10
+ import designTokens from '../dist/js/tokens.js';
11
11
  import { rem } from './util.js';
12
12
 
13
13
  const {
@@ -259,6 +259,7 @@ export default {
259
259
  '.text-button-link': textStyles.textButtonLink,
260
260
  '.text-upper': textStyles.textUpper,
261
261
  '.text-caption': textStyles.textCaption,
262
+ '.text-label': textStyles.textLabel,
262
263
  }, ['responsive']);
263
264
  }),
264
265
  ],
package/configs/util.js CHANGED
@@ -19,18 +19,3 @@ export const base64 = (str) => {
19
19
  if (typeof window === 'undefined') return Buffer.from(str).toString('base64');
20
20
  return window.btoa(str);
21
21
  };
22
-
23
- export const flattenJSON = (obj, parentKey = '') => {
24
- const flattened = {};
25
-
26
- Object.keys(obj).forEach((key) => {
27
- const newKey = parentKey ? `${parentKey}-${key}` : key;
28
- if (typeof obj[key] === 'object') {
29
- Object.assign(flattened, flattenJSON(obj[key], newKey));
30
- } else {
31
- flattened[newKey] = obj[key];
32
- }
33
- });
34
-
35
- return flattened;
36
- };
@@ -0,0 +1,266 @@
1
+ /* Do not edit directly. Generated by Style Dictionary. */
2
+
3
+ :root {
4
+ --text-primary: 34, 56, 41;
5
+ --text-primary-inverse: 237, 244, 241;
6
+ --text-secondary: 117, 117, 117;
7
+ --text-tertiary: 158, 158, 158;
8
+ --text-action: 39, 106, 67;
9
+ --text-action-highlight: 34, 56, 41;
10
+ --text-caution: 89, 50, 7;
11
+ --text-caution-highlight: 153, 98, 16;
12
+ --text-danger: 92, 42, 34;
13
+ --text-danger-highlight: 162, 69, 54;
14
+ --bg-primary: 255, 255, 255;
15
+ --bg-primary-inverse: 34, 56, 41;
16
+ --bg-secondary: 237, 244, 241;
17
+ --bg-tertiary: 196, 196, 196;
18
+ --bg-action: 39, 106, 67;
19
+ --bg-action-highlight: 34, 56, 41;
20
+ --bg-caution: 248, 205, 105;
21
+ --bg-caution-highlight: 248, 242, 230;
22
+ --bg-danger: 224, 152, 141;
23
+ --bg-danger-highlight: 249, 240, 239;
24
+ --border-primary: 80, 80, 80;
25
+ --border-primary-inverse: 255, 255, 255;
26
+ --border-secondary: 117, 117, 117;
27
+ --border-tertiary: 196, 196, 196;
28
+ --border-action: 39, 106, 67;
29
+ --border-action-highlight: 34, 56, 41;
30
+ --border-caution: 248, 205, 105;
31
+ --border-caution-highlight: 248, 242, 230;
32
+ --border-danger: 224, 152, 141;
33
+ --border-danger-highlight: 249, 240, 239;
34
+ --heading-underline-primary: url('/kvui/heading-underline.svg#2AA967');
35
+ }
36
+
37
+ [data-theme="dark-green"] {
38
+ --text-primary: 245, 245, 245;
39
+ --text-primary-inverse: 33, 33, 33;
40
+ --text-secondary: 158, 158, 158;
41
+ --text-tertiary: 158, 158, 158;
42
+ --text-action: 43, 124, 95;
43
+ --text-action-highlight: 39, 112, 86;
44
+ --text-danger: 228, 42, 42;
45
+ --text-danger-highlight: 206, 38, 38;
46
+ --bg-primary: 42, 169, 103;
47
+ --bg-primary-inverse: 245, 245, 245;
48
+ --bg-secondary: 34, 135, 82;
49
+ --bg-tertiary: 224, 224, 224;
50
+ --bg-action: 43, 124, 95;
51
+ --bg-action-highlight: 39, 112, 86;
52
+ --bg-danger: 228, 42, 42;
53
+ --bg-danger-highlight: 206, 38, 38;
54
+ --bg-caution: 230, 203, 85;
55
+ --bg-caution-highlight: 217, 188, 59;
56
+ --border-primary: 33, 33, 33;
57
+ --border-action: 43, 124, 95;
58
+ --border-action-highlight: 39, 112, 86;
59
+ --border-danger: 228, 42, 42;
60
+ --border-danger-highlight: 206, 38, 38;
61
+ }
62
+
63
+ [data-theme="dark-mint"] {
64
+ --text-primary: 255, 255, 255;
65
+ --text-primary-inverse: 245, 245, 245;
66
+ --text-action: 149, 212, 179;
67
+ --text-action-highlight: 39, 112, 86;
68
+ --text-danger: 228, 42, 42;
69
+ --text-danger-highlight: 206, 38, 38;
70
+ --bg-primary: 69, 69, 69;
71
+ --bg-primary-inverse: 0, 0, 0;
72
+ --bg-secondary: 245, 245, 245;
73
+ --bg-tertiary: 224, 224, 224;
74
+ --bg-action: 43, 124, 95;
75
+ --bg-action-highlight: 39, 112, 86;
76
+ --bg-danger: 228, 42, 42;
77
+ --bg-danger-highlight: 206, 38, 38;
78
+ --bg-caution: 230, 203, 85;
79
+ --bg-caution-highlight: 217, 188, 59;
80
+ --border-primary: 33, 33, 33;
81
+ --border-action: 43, 124, 95;
82
+ --border-action-highlight: 39, 112, 86;
83
+ --border-danger: 228, 42, 42;
84
+ --border-danger-highlight: 206, 38, 38;
85
+ }
86
+
87
+ [data-theme="dark-stone"] {
88
+ --text-primary: 245, 245, 245;
89
+ --text-primary-inverse: 33, 33, 33;
90
+ --text-secondary: 158, 158, 158;
91
+ --text-tertiary: 117, 117, 117;
92
+ --text-action: 74, 182, 126;
93
+ --text-action-highlight: 106, 195, 149;
94
+ --text-danger: 228, 42, 42;
95
+ --text-danger-highlight: 206, 38, 38;
96
+ --bg-primary: 0, 0, 0;
97
+ --bg-primary-inverse: 245, 245, 245;
98
+ --bg-secondary: 46, 39, 30;
99
+ --bg-tertiary: 69, 69, 69;
100
+ --bg-action: 74, 182, 126;
101
+ --bg-action-highlight: 106, 195, 149;
102
+ --bg-danger: 228, 42, 42;
103
+ --bg-danger-highlight: 206, 38, 38;
104
+ --bg-caution: 230, 203, 85;
105
+ --bg-caution-highlight: 217, 188, 59;
106
+ --border-primary: 245, 245, 245;
107
+ --border-primary-inverse: 33, 33, 33;
108
+ --border-secondary: 158, 158, 158;
109
+ --border-tertiary: 117, 117, 117;
110
+ --border-action: 74, 182, 126;
111
+ --border-action-highlight: 106, 195, 149;
112
+ --border-danger: 228, 42, 42;
113
+ --border-danger-highlight: 206, 38, 38;
114
+ }
115
+
116
+ [data-theme="dark"] {
117
+ --text-primary: 245, 245, 245;
118
+ --text-primary-inverse: 33, 33, 33;
119
+ --text-secondary: 158, 158, 158;
120
+ --text-tertiary: 117, 117, 117;
121
+ --text-action: 74, 182, 126;
122
+ --text-action-highlight: 106, 195, 149;
123
+ --text-danger: 228, 42, 42;
124
+ --text-danger-highlight: 206, 38, 38;
125
+ --bg-primary: 0, 0, 0;
126
+ --bg-primary-inverse: 245, 245, 245;
127
+ --bg-secondary: 33, 33, 33;
128
+ --bg-tertiary: 69, 69, 69;
129
+ --bg-action: 74, 182, 126;
130
+ --bg-action-highlight: 106, 195, 149;
131
+ --bg-danger: 228, 42, 42;
132
+ --bg-danger-highlight: 206, 38, 38;
133
+ --bg-caution: 230, 203, 85;
134
+ --bg-caution-highlight: 217, 188, 59;
135
+ --border-primary: 245, 245, 245;
136
+ --border-primary-inverse: 33, 33, 33;
137
+ --border-secondary: 158, 158, 158;
138
+ --border-tertiary: 117, 117, 117;
139
+ --border-action: 74, 182, 126;
140
+ --border-action-highlight: 106, 195, 149;
141
+ --border-danger: 228, 42, 42;
142
+ --border-danger-highlight: 206, 38, 38;
143
+ }
144
+
145
+ [data-theme="green-dark"] {
146
+ --text-primary: 237, 244, 241;
147
+ --text-primary-inverse: 34, 56, 41;
148
+ --text-secondary: 196, 196, 196;
149
+ --text-tertiary: 224, 224, 224;
150
+ --text-action: 120, 199, 159;
151
+ --text-action-highlight: 237, 244, 241;
152
+ --bg-primary: 34, 56, 41;
153
+ --bg-primary-inverse: 255, 255, 255;
154
+ --bg-secondary: 39, 106, 67;
155
+ --bg-tertiary: 196, 196, 196;
156
+ --bg-action: 120, 199, 159;
157
+ --bg-action-highlight: 237, 244, 241;
158
+ --bg-caution-highlight: 248, 242, 230;
159
+ --bg-danger-highlight: 249, 240, 239;
160
+ --border-primary: 237, 244, 241;
161
+ --border-primary-inverse: 34, 56, 41;
162
+ --border-secondary: 39, 106, 67;
163
+ --border-action: 120, 199, 159;
164
+ --border-action-highlight: 237, 244, 241;
165
+ --border-caution-highlight: 248, 242, 230;
166
+ --border-danger-highlight: 249, 240, 239;
167
+ }
168
+
169
+ [data-theme="green-light"] {
170
+ --bg-primary: 237, 244, 241;
171
+ --bg-secondary: 255, 255, 255;
172
+ }
173
+
174
+ [data-theme="marigold-light"] {
175
+ --text-primary: 89, 50, 7;
176
+ --text-primary-inverse: 248, 242, 230;
177
+ --text-action: 153, 98, 16;
178
+ --text-action-highlight: 89, 50, 7;
179
+ --bg-primary: 248, 242, 230;
180
+ --bg-primary-inverse: 89, 50, 7;
181
+ --bg-secondary: 255, 255, 255;
182
+ --bg-tertiary: 196, 196, 196;
183
+ --bg-action: 153, 98, 16;
184
+ --bg-action-highlight: 89, 50, 7;
185
+ --bg-caution-highlight: 248, 242, 230;
186
+ --bg-danger-highlight: 249, 240, 239;
187
+ --border-primary: 153, 98, 16;
188
+ --border-primary-inverse: 248, 242, 230;
189
+ --border-secondary: 248, 205, 105;
190
+ --border-tertiary: 255, 255, 255;
191
+ --border-action: 153, 98, 16;
192
+ --border-action-highlight: 89, 50, 7;
193
+ --border-caution-highlight: 248, 242, 230;
194
+ --border-danger-highlight: 249, 240, 239;
195
+ --heading-underline-primary: url('/kvui/heading-underline.svg#F8CD69');
196
+ }
197
+
198
+ [data-theme="mint"] {
199
+ --text-primary: 33, 33, 33;
200
+ --text-primary-inverse: 245, 245, 245;
201
+ --text-secondary: 34, 135, 82;
202
+ --text-tertiary: 40, 160, 98;
203
+ --text-action: 43, 124, 95;
204
+ --text-action-highlight: 39, 112, 86;
205
+ --text-danger: 228, 42, 42;
206
+ --text-danger-highlight: 206, 38, 38;
207
+ --bg-primary: 149, 212, 179;
208
+ --bg-primary-inverse: 0, 0, 0;
209
+ --bg-secondary: 245, 245, 245;
210
+ --bg-tertiary: 224, 224, 224;
211
+ --bg-action: 43, 124, 95;
212
+ --bg-action-highlight: 39, 112, 86;
213
+ --bg-danger: 228, 42, 42;
214
+ --bg-danger-highlight: 206, 38, 38;
215
+ --bg-caution: 230, 203, 85;
216
+ --bg-caution-highlight: 217, 188, 59;
217
+ --border-primary: 33, 33, 33;
218
+ --border-tertiary: 74, 182, 126;
219
+ --border-action: 43, 124, 95;
220
+ --border-action-highlight: 39, 112, 86;
221
+ --border-danger: 228, 42, 42;
222
+ --border-danger-highlight: 206, 38, 38;
223
+ }
224
+
225
+ [data-theme="stone-dark"] {
226
+ --text-primary: 243, 241, 239;
227
+ --text-primary-inverse: 46, 39, 30;
228
+ --text-secondary: 196, 196, 196;
229
+ --text-tertiary: 224, 224, 224;
230
+ --text-action: 223, 208, 188;
231
+ --text-action-highlight: 243, 241, 239;
232
+ --bg-primary: 46, 39, 30;
233
+ --bg-primary-inverse: 243, 241, 239;
234
+ --bg-secondary: 99, 85, 68;
235
+ --bg-action: 223, 208, 188;
236
+ --bg-action-highlight: 243, 241, 239;
237
+ --bg-caution-highlight: 248, 242, 230;
238
+ --bg-danger-highlight: 249, 240, 239;
239
+ --border-primary: 243, 241, 239;
240
+ --border-primary-inverse: 46, 39, 30;
241
+ --border-secondary: 99, 85, 68;
242
+ --border-action: 223, 208, 188;
243
+ --border-action-highlight: 243, 241, 239;
244
+ --border-caution-highlight: 248, 242, 230;
245
+ --border-danger-highlight: 249, 240, 239;
246
+ --heading-underline-primary: url('/kvui/heading-underline.svg#AA9E8D');
247
+ }
248
+
249
+ [data-theme="stone-light"] {
250
+ --text-primary: 46, 39, 30;
251
+ --text-primary-inverse: 243, 241, 239;
252
+ --text-action: 99, 85, 68;
253
+ --text-action-highlight: 46, 39, 30;
254
+ --bg-primary: 243, 241, 239;
255
+ --bg-primary-inverse: 46, 39, 30;
256
+ --bg-secondary: 255, 255, 255;
257
+ --bg-action: 99, 85, 68;
258
+ --bg-action-highlight: 46, 39, 30;
259
+ --border-primary: 99, 85, 68;
260
+ --border-primary-inverse: 243, 241, 239;
261
+ --border-secondary: 170, 158, 141;
262
+ --border-tertiary: 255, 255, 255;
263
+ --border-action: 99, 85, 68;
264
+ --border-action-highlight: 46, 39, 30;
265
+ --heading-underline-primary: url('/kvui/heading-underline.svg#AA9E8D');
266
+ }