From c2bee5e8e8d5450f10fd43640f19a1b0ab01051c Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Mon, 29 Jun 2026 16:24:12 +1000 Subject: [PATCH 01/25] adding semantic colors --- packages/design-tokens/src/js/index.ts | 1 + .../src/js/semanticColorTokens.ts | 126 ++++++++++++++++++ packages/design-tokens/src/js/tokens.ts | 2 + packages/design-tokens/src/types.ts | 2 + 4 files changed, 131 insertions(+) create mode 100644 packages/design-tokens/src/js/semanticColorTokens.ts diff --git a/packages/design-tokens/src/js/index.ts b/packages/design-tokens/src/js/index.ts index d0a5ea27893..e4fdfb28cb1 100644 --- a/packages/design-tokens/src/js/index.ts +++ b/packages/design-tokens/src/js/index.ts @@ -1 +1,2 @@ export * from './tokens' +export * from './semanticColorTokens' diff --git a/packages/design-tokens/src/js/semanticColorTokens.ts b/packages/design-tokens/src/js/semanticColorTokens.ts new file mode 100644 index 00000000000..89f0aed5733 --- /dev/null +++ b/packages/design-tokens/src/js/semanticColorTokens.ts @@ -0,0 +1,126 @@ +/** + * Semantic colour tokens — Untitled UI (UUI) aligned naming. + * + * Naming follows UUI verbatim (`bg-brand-solid`, `text-primary_on-brand`, + * `border-error_subtle`) so Figma and code share one vocabulary. The `_hover` / + * `_alt` / `_on-brand` suffixes use underscores intentionally — part of the UUI + * name, not separators. Grouped by the surface a token paints: `background`, + * `text`, `foreground` (icons / glyphs), `border`. When wired to CSS these emit + * as `--` variables verbatim — no prefix — so the CSS var, Tailwind + * class, and JS key are the same string (e.g. `bg-brand-solid` → + * `--bg-brand-solid`, the `bg-brand-solid` Tailwind class, and the + * `bg-brand-solid` JS key all refer to one thing). + * + * VALUES are DRAFT mappings derived from the UUI→Kaizen usage audit (dominant + * primitive per token). Most reference existing `--color-*` primitives. The + * `text-*` hierarchy was signed off by Lua Cortes (2026-06-29): it now maps to + * solid `gray-550`/`gray-600`/`gray-700` primitives instead of the old + * `purple-800` alpha hacks (chosen to land close to the future greycool OKLCH + * lightness). Caveats: + * + * - `null` = no usage data yet / no confident mapping. Left for design sign-off. + * - Tokens marked `ALPHA` in a trailing comment are used in the source at + * reduced opacity (e.g. `rgb(--color-purple-800-rgb 0.7)`). Collapsed here to + * the BASE primitive; the alpha treatment must be reapplied when wired to CSS. + * - Tokens marked `CONFLICT` had split votes — the dominant choice is used; the + * runner-up is noted for review. + * + * Mappings are not final until signed off with the designer (Lua Cortes). + */ + +/** A semantic token value: a primitive reference once mapped, `null` while unmapped. */ +export type SemanticColorTokenValue = string | null + +export type SemanticColorTokenGroup = Record + +export interface SemanticColorTokens { + background: SemanticColorTokenGroup + text: SemanticColorTokenGroup + foreground: SemanticColorTokenGroup + border: SemanticColorTokenGroup +} + +export const semanticColorTokens: SemanticColorTokens = { + background: { + 'bg-primary': 'var(--color-white)', + 'bg-primary_alt': null, + 'bg-primary_hover': null, + 'bg-secondary': 'var(--color-gray-200)', // CONFLICT: gray-100 also seen; ordering vs bg-secondary_hover (gray-200) needs review + 'bg-secondary_alt': null, + 'bg-secondary_hover': 'var(--color-gray-200)', + 'bg-tertiary': 'var(--color-gray-300)', + 'bg-quaternary': null, + 'bg-primary-solid': 'var(--color-purple-800)', // CONFLICT: purple-700 also seen + 'bg-secondary-solid': 'var(--color-gray-600)', // CONFLICT: gray-500 also seen + 'bg-overlay': 'var(--color-white)', // ALPHA: used as white at 0.1–0.65 + 'bg-brand-primary': 'var(--color-blue-100)', // CONFLICT: purple-100 also seen + 'bg-brand-primary_alt': null, + 'bg-brand-secondary': 'var(--color-blue-200)', + 'bg-brand-solid': 'var(--color-blue-500)', + 'bg-brand-solid_hover': 'var(--color-blue-700)', // CONFLICT: blue-600 also seen + 'bg-brand-section': null, + 'bg-brand-section_subtle': null, + 'bg-error-primary': 'var(--color-red-100)', + 'bg-error-secondary': 'var(--color-red-300)', + 'bg-error-solid': 'var(--color-red-400)', + 'bg-error-solid_hover': null, + 'bg-success-primary': 'var(--color-green-100)', + 'bg-success-secondary': 'var(--color-green-300)', + 'bg-success-solid': 'var(--color-green-600)', // CONFLICT: green-400/500 also seen + 'bg-warning-primary': 'var(--color-yellow-100)', + 'bg-warning-secondary': 'var(--color-yellow-400)', // NOTE: same as bg-warning-solid in source + 'bg-warning-solid': 'var(--color-yellow-400)', + }, + text: { + 'text-primary': 'var(--color-purple-800)', // Lua Cortes (2026-06-29): solid bridge, future greycool #171A1B + 'text-secondary': 'var(--color-gray-700)', // Lua Cortes (2026-06-29): solid bridge replacing purple-800 @0.7–0.8 alpha hack + 'text-secondary_hover': null, + 'text-tertiary': 'var(--color-gray-600)', // Lua Cortes (2026-06-29): solid bridge replacing purple-800 @0.7 alpha hack + 'text-tertiary_hover': null, + 'text-quaternary': 'var(--color-gray-550)', // Lua Cortes (2026-06-29): solid bridge replacing purple-800 @0.3 alpha hack + 'text-placeholder': 'var(--color-gray-550)', // Lua Cortes (2026-06-29): solid bridge replacing purple-800 @0.7 alpha hack + 'text-primary_on-brand': null, + 'text-secondary_on-brand': 'var(--color-white)', // ALPHA: used at 0.8 + 'text-tertiary_on-brand': null, + 'text-quaternary_on-brand': 'var(--color-white)', // ALPHA: used at 0.2–0.3 + 'text-brand-primary': 'var(--color-blue-500)', + 'text-brand-secondary': 'var(--color-blue-700)', + 'text-brand-secondary_hover': 'var(--color-blue-600)', + 'text-brand-tertiary': null, + 'text-brand-tertiary_alt': null, + 'text-error-primary': 'var(--color-red-600)', // CONFLICT: red-500 also seen + 'text-success-primary': 'var(--color-green-600)', // CONFLICT: green-500 also seen + 'text-warning-primary': null, // doc had no UUI yellow text token + }, + foreground: { + 'fg-primary': 'var(--color-purple-800)', + 'fg-secondary': 'var(--color-purple-800)', // ALPHA: used at 0.7; gray-600 also seen + 'fg-secondary_hover': 'var(--color-purple-800)', + 'fg-tertiary': 'var(--color-gray-500)', // CONFLICT: purple-800 @0.5 also seen + 'fg-tertiary_hover': null, + 'fg-quaternary': 'var(--color-purple-800)', // ALPHA: used at 0.3 + 'fg-quaternary_hover': null, + 'fg-white': 'var(--color-white)', + 'fg-brand-primary': 'var(--color-blue-500)', + 'fg-brand-primary_alt': null, + 'fg-brand-secondary': null, + 'fg-brand-secondary_alt': null, + 'fg-brand-secondary_hover': null, + 'fg-error-primary': 'var(--color-red-500)', + 'fg-error-secondary': null, + 'fg-success-primary': 'var(--color-green-500)', + 'fg-success-secondary': 'var(--color-green-400)', + 'fg-warning-primary': 'var(--color-yellow-700)', + 'fg-warning-secondary': null, + }, + border: { + 'border-primary': 'var(--color-gray-600)', // CONFLICT: white (dark-surface usage) tied; black also seen + 'border-secondary': 'var(--color-gray-500)', // CONFLICT: gray-400 also seen + 'border-secondary_alt': 'var(--color-gray-200)', // CONFLICT: gray-300 also seen + 'border-tertiary': 'var(--color-gray-300)', // CONFLICT: white @alpha also seen + 'border-brand': 'var(--color-blue-500)', + 'border-brand_alt': 'var(--color-blue-300)', // CONFLICT: blue-400 / purple-400 also seen + 'border-error': 'var(--color-red-500)', + 'border-error_subtle': 'var(--color-red-300)', + }, +} diff --git a/packages/design-tokens/src/js/tokens.ts b/packages/design-tokens/src/js/tokens.ts index 1ba2e29ee9b..3a5f6fa5070 100644 --- a/packages/design-tokens/src/js/tokens.ts +++ b/packages/design-tokens/src/js/tokens.ts @@ -109,7 +109,9 @@ export const tokens: TokenStructure = { 300: '#eaeaec', 400: '#cdcdd0', 500: '#878792', + 550: '#6D6674', 600: '#524e56', + 700: '#3F3C42', }, white: '#ffffff', black: '#000000', diff --git a/packages/design-tokens/src/types.ts b/packages/design-tokens/src/types.ts index 728439398e8..3bacedfb43b 100644 --- a/packages/design-tokens/src/types.ts +++ b/packages/design-tokens/src/types.ts @@ -138,7 +138,9 @@ export type TokenStructure = { '300': Hex '400': Hex '500': Hex + '550': Hex '600': Hex + '700': Hex } white: Hex black: Hex From 630605781d113be6ae20275cb0d9f9bb7879b107 Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Mon, 29 Jun 2026 16:28:41 +1000 Subject: [PATCH 02/25] exports css scss less and tw3 presets --- .../design-tokens/bin/buildSemanticTokens.ts | 55 +++++++++++++++++++ packages/design-tokens/css/semantic.css | 55 +++++++++++++++++++ packages/design-tokens/css/variables.css | 2 +- packages/design-tokens/less/color.less | 8 +++ packages/design-tokens/less/semantic.less | 53 ++++++++++++++++++ packages/design-tokens/package.json | 3 +- packages/design-tokens/sass/color.scss | 8 +++ packages/design-tokens/sass/semantic.scss | 53 ++++++++++++++++++ .../src/js/semanticColorTokens.ts | 19 +++++++ packages/design-tokens/tokens/color.json | 10 +++- packages/tailwind/src/tailwind-presets.ts | 39 ++++++++++++- 11 files changed, 300 insertions(+), 5 deletions(-) create mode 100644 packages/design-tokens/bin/buildSemanticTokens.ts create mode 100644 packages/design-tokens/css/semantic.css create mode 100644 packages/design-tokens/less/semantic.less create mode 100644 packages/design-tokens/sass/semantic.scss diff --git a/packages/design-tokens/bin/buildSemanticTokens.ts b/packages/design-tokens/bin/buildSemanticTokens.ts new file mode 100644 index 00000000000..597d4955d46 --- /dev/null +++ b/packages/design-tokens/bin/buildSemanticTokens.ts @@ -0,0 +1,55 @@ +import fs from 'fs' +import path from 'path' +import { semanticColorTokens } from '../src/js/semanticColorTokens' + +const CSS_OUTPUT_DIR = `${process.cwd()}/css` +const LESS_OUTPUT_DIR = `${process.cwd()}/less` +const SASS_OUTPUT_DIR = `${process.cwd()}/sass` + +const AUTOGENERATED_HEADER = '/** THIS IS AN AUTOGENERATED FILE **/' + +/** + * Flatten all 4 semantic colour groups into a single [key, value] list, + * dropping any entry whose value is `null` (unmapped token). + */ +const flatEntries = Object.values(semanticColorTokens) + .flatMap((group) => Object.entries(group)) + .filter((entry): entry is [string, string] => entry[1] !== null) + +const run = (): void => { + fs.mkdirSync(CSS_OUTPUT_DIR, { recursive: true }) + fs.mkdirSync(LESS_OUTPUT_DIR, { recursive: true }) + fs.mkdirSync(SASS_OUTPUT_DIR, { recursive: true }) + + // css/semantic.css — CSS custom properties on :root + const cssLines = flatEntries.map(([key, value]) => ` --${key}: ${value};`) + fs.writeFileSync( + path.resolve(CSS_OUTPUT_DIR, 'semantic.css'), + `${AUTOGENERATED_HEADER}\n\n:root {\n${cssLines.join('\n')}\n}\n`, + ) + + // less/semantic.less — LESS variables that fall back through the CSS var + const lessLines = flatEntries.map(([key, value]) => `@${key}: var(--${key}, ${value});`) + fs.writeFileSync( + path.resolve(LESS_OUTPUT_DIR, 'semantic.less'), + `${AUTOGENERATED_HEADER}\n\n${lessLines.join('\n')}\n`, + ) + + // sass/semantic.scss — SCSS variables that fall back through the CSS var + const scssLines = flatEntries.map(([key, value]) => `$${key}: var(--${key}, ${value});`) + fs.writeFileSync( + path.resolve(SASS_OUTPUT_DIR, 'semantic.scss'), + `${AUTOGENERATED_HEADER}\n\n${scssLines.join('\n')}\n`, + ) + + const totalTokens = Object.values(semanticColorTokens).flatMap((group) => + Object.values(group), + ).length + const nullCount = totalTokens - flatEntries.length + + console.log( + `Semantic tokens written: ${flatEntries.length} emitted, ${nullCount} null-skipped (${totalTokens} total).`, + ) +} + +run() diff --git a/packages/design-tokens/css/semantic.css b/packages/design-tokens/css/semantic.css new file mode 100644 index 00000000000..90ae3aff230 --- /dev/null +++ b/packages/design-tokens/css/semantic.css @@ -0,0 +1,55 @@ +/** THIS IS AN AUTOGENERATED FILE **/ + +:root { + --bg-primary: var(--color-white); + --bg-secondary: var(--color-gray-200); + --bg-secondary_hover: var(--color-gray-200); + --bg-tertiary: var(--color-gray-300); + --bg-primary-solid: var(--color-purple-800); + --bg-secondary-solid: var(--color-gray-600); + --bg-overlay: var(--color-white); + --bg-brand-primary: var(--color-blue-100); + --bg-brand-secondary: var(--color-blue-200); + --bg-brand-solid: var(--color-blue-500); + --bg-brand-solid_hover: var(--color-blue-700); + --bg-error-primary: var(--color-red-100); + --bg-error-secondary: var(--color-red-300); + --bg-error-solid: var(--color-red-400); + --bg-success-primary: var(--color-green-100); + --bg-success-secondary: var(--color-green-300); + --bg-success-solid: var(--color-green-600); + --bg-warning-primary: var(--color-yellow-100); + --bg-warning-secondary: var(--color-yellow-400); + --bg-warning-solid: var(--color-yellow-400); + --text-primary: var(--color-purple-800); + --text-secondary: var(--color-gray-700); + --text-tertiary: var(--color-gray-600); + --text-quaternary: var(--color-gray-550); + --text-placeholder: var(--color-gray-550); + --text-secondary_on-brand: var(--color-white); + --text-quaternary_on-brand: var(--color-white); + --text-brand-primary: var(--color-blue-500); + --text-brand-secondary: var(--color-blue-700); + --text-brand-secondary_hover: var(--color-blue-600); + --text-error-primary: var(--color-red-600); + --text-success-primary: var(--color-green-600); + --fg-primary: var(--color-purple-800); + --fg-secondary: var(--color-purple-800); + --fg-secondary_hover: var(--color-purple-800); + --fg-tertiary: var(--color-gray-500); + --fg-quaternary: var(--color-purple-800); + --fg-white: var(--color-white); + --fg-brand-primary: var(--color-blue-500); + --fg-error-primary: var(--color-red-500); + --fg-success-primary: var(--color-green-500); + --fg-success-secondary: var(--color-green-400); + --fg-warning-primary: var(--color-yellow-700); + --border-primary: var(--color-gray-600); + --border-secondary: var(--color-gray-500); + --border-secondary_alt: var(--color-gray-200); + --border-tertiary: var(--color-gray-300); + --border-brand: var(--color-blue-500); + --border-brand_alt: var(--color-blue-300); + --border-error: var(--color-red-500); + --border-error_subtle: var(--color-red-300); +} diff --git a/packages/design-tokens/css/variables.css b/packages/design-tokens/css/variables.css index 66327cd2138..3fcb34e1b71 100644 --- a/packages/design-tokens/css/variables.css +++ b/packages/design-tokens/css/variables.css @@ -1,5 +1,5 @@ /** THIS IS AN AUTOGENERATED FILE **/ - :root{--animation-easing-function-ease-in-out: cubic-bezier(0.455, 0.03, 0.515, 0.955); --animation-easing-function-ease-in: cubic-bezier(0.55, 0.085, 0.68, 0.53); --animation-easing-function-ease-out: cubic-bezier(0.25, 0.46, 0.45, 0.94); --animation-easing-function-linear: linear; --animation-easing-function-bounce-in: cubic-bezier(0.485, 0.155, 0.24, 1.245); --animation-easing-function-bounce-out: cubic-bezier(0.485, 0.155, 0.515, 0.845); --animation-easing-function-bounce-in-out: cubic-bezier(0.76, -0.245, 0.24, 1.245); --animation-duration-instant: 0ms; --animation-duration-immediate: 100ms; --animation-duration-rapid: 200ms; --animation-duration-fast: 300ms; --animation-duration-slow: 400ms; --animation-duration-deliberate: 700ms; --border-solid-border-width: 2px; --border-solid-border-radius: 7px; --border-solid-border-style: solid; --border-solid-border-color: #e1e2ea; --border-solid-border-color-rgb: 225, 226, 234; --border-dashed-border-width: 2px; --border-dashed-border-radius: 7px; --border-dashed-border-style: dashed; --border-borderless-border-width: 2px; --border-borderless-border-radius: 7px; --border-borderless-border-style: solid; --border-borderless-border-color: transparent; --border-borderless-border-color-rgb: 0, 0, 0; --border-focus-ring-border-width: 2px; --border-focus-ring-border-radius: 10px; --border-focus-ring-border-style: solid; --border-width-1: 1px; --color-purple-100: #f4edf8; --color-purple-100-rgb: 244, 237, 248; --color-purple-200: #dfc9ea; --color-purple-200-rgb: 223, 201, 234; --color-purple-300: #c9a5dd; --color-purple-300-rgb: 201, 165, 221; --color-purple-400: #ae67b1; --color-purple-400-rgb: 174, 103, 177; --color-purple-500: #844587; --color-purple-500-rgb: 132, 69, 135; --color-purple-600: #5f3361; --color-purple-600-rgb: 95, 51, 97; --color-purple-700: #4a234d; --color-purple-700-rgb: 74, 35, 77; --color-purple-800: #2f2438; --color-purple-800-rgb: 47, 36, 56; --color-blue-100: #e6f6ff; --color-blue-100-rgb: 230, 246, 255; --color-blue-200: #bde2f5; --color-blue-200-rgb: 189, 226, 245; --color-blue-300: #73c0e8; --color-blue-300-rgb: 115, 192, 232; --color-blue-400: #008bd6; --color-blue-400-rgb: 0, 139, 214; --color-blue-500: #0168b3; --color-blue-500-rgb: 1, 104, 179; --color-blue-600: #004970; --color-blue-600-rgb: 0, 73, 112; --color-blue-700: #003157; --color-blue-700-rgb: 0, 49, 87; --color-green-100: #e8f8f4; --color-green-100-rgb: 232, 248, 244; --color-green-200: #c4ede2; --color-green-200-rgb: 196, 237, 226; --color-green-300: #8fdbc7; --color-green-300-rgb: 143, 219, 199; --color-green-400: #5dcaad; --color-green-400-rgb: 93, 202, 173; --color-green-500: #3f9a86; --color-green-500-rgb: 63, 154, 134; --color-green-600: #2c7d67; --color-green-600-rgb: 44, 125, 103; --color-green-700: #22594a; --color-green-700-rgb: 34, 89, 74; --color-yellow-100: #fff9e4; --color-yellow-100-rgb: 255, 249, 228; --color-yellow-200: #ffeeb3; --color-yellow-200-rgb: 255, 238, 179; --color-yellow-300: #ffe36e; --color-yellow-300-rgb: 255, 227, 110; --color-yellow-400: #ffca4d; --color-yellow-400-rgb: 255, 202, 77; --color-yellow-500: #ffb600; --color-yellow-500-rgb: 255, 182, 0; --color-yellow-600: #c68600; --color-yellow-600-rgb: 198, 134, 0; --color-yellow-700: #876400; --color-yellow-700-rgb: 135, 100, 0; --color-red-100: #fdeaee; --color-red-100-rgb: 253, 234, 238; --color-red-200: #f9c2cb; --color-red-200-rgb: 249, 194, 203; --color-red-300: #f597a8; --color-red-300-rgb: 245, 151, 168; --color-red-400: #e0707d; --color-red-400-rgb: 224, 112, 125; --color-red-500: #c93b55; --color-red-500-rgb: 201, 59, 85; --color-red-600: #a82433; --color-red-600-rgb: 168, 36, 51; --color-red-700: #6c1e20; --color-red-700-rgb: 108, 30, 32; --color-orange-100: #fff0e8; --color-orange-100-rgb: 255, 240, 232; --color-orange-200: #ffd1b9; --color-orange-200-rgb: 255, 209, 185; --color-orange-300: #ffb08a; --color-orange-300-rgb: 255, 176, 138; --color-orange-400: #ff9461; --color-orange-400-rgb: 255, 148, 97; --color-orange-500: #e96c2f; --color-orange-500-rgb: 233, 108, 47; --color-orange-600: #b74302; --color-orange-600-rgb: 183, 67, 2; --color-orange-700: #903c00; --color-orange-700-rgb: 144, 60, 0; --color-gray-100: #f9f9f9; --color-gray-100-rgb: 249, 249, 249; --color-gray-200: #f4f4f5; --color-gray-200-rgb: 244, 244, 245; --color-gray-300: #eaeaec; --color-gray-300-rgb: 234, 234, 236; --color-gray-400: #cdcdd0; --color-gray-400-rgb: 205, 205, 208; --color-gray-500: #878792; --color-gray-500-rgb: 135, 135, 146; --color-gray-600: #524e56; --color-gray-600-rgb: 82, 78, 86; --color-white: #ffffff; --color-white-rgb: 255, 255, 255; --color-black: #000000; --color-black-rgb: 0, 0, 0; --data-viz-favorable: #7dd5bd; --data-viz-favorable-rgb: 125, 213, 189; --data-viz-unfavorable: #e68d97; --data-viz-unfavorable-rgb: 230, 141, 151; --layout-content-max-width: 1392px; --layout-content-max-width-with-sidebar: 1080px; --layout-content-side-margin: 72px; --layout-mobile-actions-drawer-height: 60px; --layout-navigation-bar-height: 72px; --layout-breakpoints-medium: 768px; --layout-breakpoints-large: 1080px; --shadow-small-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 3px 16px 0 rgba(0, 0, 0, 0.06); --shadow-large-box-shadow: 0 3px 9px 0 rgba(0, 0, 0, 0.1), 0 8px 40px 0 rgba(0, 0, 0, 0.08); --spacing-0: 0; --spacing-1: .0625rem; --spacing-2: .125rem; --spacing-4: .25rem; --spacing-6: .375rem; --spacing-8: .5rem; --spacing-12: .75rem; --spacing-16: 1rem; --spacing-20: 1.25rem; --spacing-24: 1.5rem; --spacing-32: 2rem; --spacing-40: 2.5rem; --spacing-48: 3rem; --spacing-56: 3.5rem; --spacing-64: 4rem; --spacing-72: 4.5rem; --spacing-80: 5rem; --spacing-96: 6rem; --spacing-112: 7rem; --spacing-128: 8rem; --spacing-160: 10rem; --spacing-200: 12.5rem; --spacing-240: 15rem; --spacing-280: 17.5rem; --spacing-320: 20rem; --spacing-xs: 0.375rem; --spacing-sm: 0.75rem; --spacing-md: 1.5rem; --spacing-lg: 2.25rem; --spacing-xl: 3rem; --spacing-xxl: 3.75rem; --spacing-xxxl: 4.5rem; --spacing-xxxxl: 5.25rem; --spacing-xxxxxl: 6rem; --typography-data-large-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-large-font-weight: 700; --typography-data-large-font-size: 5.25rem; --typography-data-large-line-height: 5.25rem; --typography-data-large-letter-spacing: normal; --typography-data-large-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-large-units-font-weight: 700; --typography-data-large-units-font-size: 2.625rem; --typography-data-large-units-line-height: 5.25rem; --typography-data-large-units-letter-spacing: normal; --typography-data-medium-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-medium-font-weight: 700; --typography-data-medium-font-size: 3rem; --typography-data-medium-line-height: 5rem; --typography-data-medium-letter-spacing: normal; --typography-data-medium-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-medium-units-font-weight: 700; --typography-data-medium-units-font-size: 1.5rem; --typography-data-medium-units-line-height: 5rem; --typography-data-medium-units-letter-spacing: normal; --typography-data-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-small-font-weight: 700; --typography-data-small-font-size: 1.5rem; --typography-data-small-line-height: 1.5rem; --typography-data-small-letter-spacing: normal; --typography-data-small-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-small-units-font-weight: 700; --typography-data-small-units-font-size: 1.125rem; --typography-data-small-units-line-height: 1.5rem; --typography-data-small-units-letter-spacing: normal; --typography-display-0-font-family: "Tiempos Headline", Georgia, serif; --typography-display-0-font-weight: 800; --typography-display-0-font-size: 4.5rem; --typography-display-0-line-height: 5.25rem; --typography-display-0-letter-spacing: 0em; --typography-heading-1-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-1-font-weight: 500; --typography-heading-1-font-size: 2.125rem; --typography-heading-1-line-height: 2.625rem; --typography-heading-1-letter-spacing: normal; --typography-heading-2-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-2-font-weight: 600; --typography-heading-2-font-size: 1.75rem; --typography-heading-2-line-height: 2.25rem; --typography-heading-2-letter-spacing: normal; --typography-heading-3-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-3-font-weight: 600; --typography-heading-3-font-size: 1.375rem; --typography-heading-3-line-height: 1.875rem; --typography-heading-3-letter-spacing: normal; --typography-heading-4-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-4-font-weight: 600; --typography-heading-4-font-size: 1.125rem; --typography-heading-4-line-height: 1.5rem; --typography-heading-4-letter-spacing: normal; --typography-heading-5-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-5-font-weight: 600; --typography-heading-5-font-size: 1rem; --typography-heading-5-line-height: 1.5rem; --typography-heading-5-letter-spacing: normal; --typography-heading-6-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-6-font-weight: 600; --typography-heading-6-font-size: 0.875rem; --typography-heading-6-line-height: 1.5rem; --typography-heading-6-letter-spacing: normal; --typography-paragraph-intro-lede-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-intro-lede-font-weight: 400; --typography-paragraph-intro-lede-font-size: 1.25rem; --typography-paragraph-intro-lede-line-height: 1.875rem; --typography-paragraph-intro-lede-letter-spacing: 0; --typography-paragraph-intro-lede-max-width: 975px; --typography-paragraph-body-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-body-font-weight: 400; --typography-paragraph-body-font-size: 1rem; --typography-paragraph-body-line-height: 1.5rem; --typography-paragraph-body-letter-spacing: normal; --typography-paragraph-body-max-width: 780px; --typography-paragraph-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-small-font-weight: 400; --typography-paragraph-small-font-size: 0.875rem; --typography-paragraph-small-line-height: 1.125rem; --typography-paragraph-small-letter-spacing: normal; --typography-paragraph-small-max-width: 680px; --typography-paragraph-extra-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-extra-small-font-weight: 400; --typography-paragraph-extra-small-font-size: 0.75rem; --typography-paragraph-extra-small-line-height: 1.125rem; --typography-paragraph-extra-small-letter-spacing: normal; --typography-paragraph-extra-small-max-width: 600px; --typography-paragraph-bold-font-weight: 600; --typography-button-primary-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-button-primary-font-weight: 500; --typography-button-primary-font-size: 1.125rem; --typography-button-primary-line-height: 1.5rem; --typography-button-primary-letter-spacing: normal; --typography-button-secondary-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-button-secondary-font-weight: 500; --typography-button-secondary-font-size: 1rem; --typography-button-secondary-line-height: 1.5rem; --typography-button-secondary-letter-spacing: normal;} + :root{--animation-easing-function-ease-in-out: cubic-bezier(0.455, 0.03, 0.515, 0.955); --animation-easing-function-ease-in: cubic-bezier(0.55, 0.085, 0.68, 0.53); --animation-easing-function-ease-out: cubic-bezier(0.25, 0.46, 0.45, 0.94); --animation-easing-function-linear: linear; --animation-easing-function-bounce-in: cubic-bezier(0.485, 0.155, 0.24, 1.245); --animation-easing-function-bounce-out: cubic-bezier(0.485, 0.155, 0.515, 0.845); --animation-easing-function-bounce-in-out: cubic-bezier(0.76, -0.245, 0.24, 1.245); --animation-duration-instant: 0ms; --animation-duration-immediate: 100ms; --animation-duration-rapid: 200ms; --animation-duration-fast: 300ms; --animation-duration-slow: 400ms; --animation-duration-deliberate: 700ms; --border-solid-border-width: 2px; --border-solid-border-radius: 7px; --border-solid-border-style: solid; --border-solid-border-color: #e1e2ea; --border-solid-border-color-rgb: 225, 226, 234; --border-dashed-border-width: 2px; --border-dashed-border-radius: 7px; --border-dashed-border-style: dashed; --border-borderless-border-width: 2px; --border-borderless-border-radius: 7px; --border-borderless-border-style: solid; --border-borderless-border-color: transparent; --border-borderless-border-color-rgb: 0, 0, 0; --border-focus-ring-border-width: 2px; --border-focus-ring-border-radius: 10px; --border-focus-ring-border-style: solid; --border-width-1: 1px; --color-purple-100: #f4edf8; --color-purple-100-rgb: 244, 237, 248; --color-purple-200: #dfc9ea; --color-purple-200-rgb: 223, 201, 234; --color-purple-300: #c9a5dd; --color-purple-300-rgb: 201, 165, 221; --color-purple-400: #ae67b1; --color-purple-400-rgb: 174, 103, 177; --color-purple-500: #844587; --color-purple-500-rgb: 132, 69, 135; --color-purple-600: #5f3361; --color-purple-600-rgb: 95, 51, 97; --color-purple-700: #4a234d; --color-purple-700-rgb: 74, 35, 77; --color-purple-800: #2f2438; --color-purple-800-rgb: 47, 36, 56; --color-blue-100: #e6f6ff; --color-blue-100-rgb: 230, 246, 255; --color-blue-200: #bde2f5; --color-blue-200-rgb: 189, 226, 245; --color-blue-300: #73c0e8; --color-blue-300-rgb: 115, 192, 232; --color-blue-400: #008bd6; --color-blue-400-rgb: 0, 139, 214; --color-blue-500: #0168b3; --color-blue-500-rgb: 1, 104, 179; --color-blue-600: #004970; --color-blue-600-rgb: 0, 73, 112; --color-blue-700: #003157; --color-blue-700-rgb: 0, 49, 87; --color-green-100: #e8f8f4; --color-green-100-rgb: 232, 248, 244; --color-green-200: #c4ede2; --color-green-200-rgb: 196, 237, 226; --color-green-300: #8fdbc7; --color-green-300-rgb: 143, 219, 199; --color-green-400: #5dcaad; --color-green-400-rgb: 93, 202, 173; --color-green-500: #3f9a86; --color-green-500-rgb: 63, 154, 134; --color-green-600: #2c7d67; --color-green-600-rgb: 44, 125, 103; --color-green-700: #22594a; --color-green-700-rgb: 34, 89, 74; --color-yellow-100: #fff9e4; --color-yellow-100-rgb: 255, 249, 228; --color-yellow-200: #ffeeb3; --color-yellow-200-rgb: 255, 238, 179; --color-yellow-300: #ffe36e; --color-yellow-300-rgb: 255, 227, 110; --color-yellow-400: #ffca4d; --color-yellow-400-rgb: 255, 202, 77; --color-yellow-500: #ffb600; --color-yellow-500-rgb: 255, 182, 0; --color-yellow-600: #c68600; --color-yellow-600-rgb: 198, 134, 0; --color-yellow-700: #876400; --color-yellow-700-rgb: 135, 100, 0; --color-red-100: #fdeaee; --color-red-100-rgb: 253, 234, 238; --color-red-200: #f9c2cb; --color-red-200-rgb: 249, 194, 203; --color-red-300: #f597a8; --color-red-300-rgb: 245, 151, 168; --color-red-400: #e0707d; --color-red-400-rgb: 224, 112, 125; --color-red-500: #c93b55; --color-red-500-rgb: 201, 59, 85; --color-red-600: #a82433; --color-red-600-rgb: 168, 36, 51; --color-red-700: #6c1e20; --color-red-700-rgb: 108, 30, 32; --color-orange-100: #fff0e8; --color-orange-100-rgb: 255, 240, 232; --color-orange-200: #ffd1b9; --color-orange-200-rgb: 255, 209, 185; --color-orange-300: #ffb08a; --color-orange-300-rgb: 255, 176, 138; --color-orange-400: #ff9461; --color-orange-400-rgb: 255, 148, 97; --color-orange-500: #e96c2f; --color-orange-500-rgb: 233, 108, 47; --color-orange-600: #b74302; --color-orange-600-rgb: 183, 67, 2; --color-orange-700: #903c00; --color-orange-700-rgb: 144, 60, 0; --color-gray-100: #f9f9f9; --color-gray-100-rgb: 249, 249, 249; --color-gray-200: #f4f4f5; --color-gray-200-rgb: 244, 244, 245; --color-gray-300: #eaeaec; --color-gray-300-rgb: 234, 234, 236; --color-gray-400: #cdcdd0; --color-gray-400-rgb: 205, 205, 208; --color-gray-500: #878792; --color-gray-500-rgb: 135, 135, 146; --color-gray-550: #6d6674; --color-gray-550-rgb: 109, 102, 116; --color-gray-600: #524e56; --color-gray-600-rgb: 82, 78, 86; --color-gray-700: #3f3c42; --color-gray-700-rgb: 63, 60, 66; --color-white: #ffffff; --color-white-rgb: 255, 255, 255; --color-black: #000000; --color-black-rgb: 0, 0, 0; --data-viz-favorable: #7dd5bd; --data-viz-favorable-rgb: 125, 213, 189; --data-viz-unfavorable: #e68d97; --data-viz-unfavorable-rgb: 230, 141, 151; --layout-content-max-width: 1392px; --layout-content-max-width-with-sidebar: 1080px; --layout-content-side-margin: 72px; --layout-mobile-actions-drawer-height: 60px; --layout-navigation-bar-height: 72px; --layout-breakpoints-medium: 768px; --layout-breakpoints-large: 1080px; --shadow-small-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 3px 16px 0 rgba(0, 0, 0, 0.06); --shadow-large-box-shadow: 0 3px 9px 0 rgba(0, 0, 0, 0.1), 0 8px 40px 0 rgba(0, 0, 0, 0.08); --spacing-0: 0; --spacing-1: .0625rem; --spacing-2: .125rem; --spacing-4: .25rem; --spacing-6: .375rem; --spacing-8: .5rem; --spacing-12: .75rem; --spacing-16: 1rem; --spacing-20: 1.25rem; --spacing-24: 1.5rem; --spacing-32: 2rem; --spacing-40: 2.5rem; --spacing-48: 3rem; --spacing-56: 3.5rem; --spacing-64: 4rem; --spacing-72: 4.5rem; --spacing-80: 5rem; --spacing-96: 6rem; --spacing-112: 7rem; --spacing-128: 8rem; --spacing-160: 10rem; --spacing-200: 12.5rem; --spacing-240: 15rem; --spacing-280: 17.5rem; --spacing-320: 20rem; --spacing-xs: 0.375rem; --spacing-sm: 0.75rem; --spacing-md: 1.5rem; --spacing-lg: 2.25rem; --spacing-xl: 3rem; --spacing-xxl: 3.75rem; --spacing-xxxl: 4.5rem; --spacing-xxxxl: 5.25rem; --spacing-xxxxxl: 6rem; --typography-data-large-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-large-font-weight: 700; --typography-data-large-font-size: 5.25rem; --typography-data-large-line-height: 5.25rem; --typography-data-large-letter-spacing: normal; --typography-data-large-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-large-units-font-weight: 700; --typography-data-large-units-font-size: 2.625rem; --typography-data-large-units-line-height: 5.25rem; --typography-data-large-units-letter-spacing: normal; --typography-data-medium-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-medium-font-weight: 700; --typography-data-medium-font-size: 3rem; --typography-data-medium-line-height: 5rem; --typography-data-medium-letter-spacing: normal; --typography-data-medium-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-medium-units-font-weight: 700; --typography-data-medium-units-font-size: 1.5rem; --typography-data-medium-units-line-height: 5rem; --typography-data-medium-units-letter-spacing: normal; --typography-data-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-small-font-weight: 700; --typography-data-small-font-size: 1.5rem; --typography-data-small-line-height: 1.5rem; --typography-data-small-letter-spacing: normal; --typography-data-small-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-small-units-font-weight: 700; --typography-data-small-units-font-size: 1.125rem; --typography-data-small-units-line-height: 1.5rem; --typography-data-small-units-letter-spacing: normal; --typography-display-0-font-family: "Tiempos Headline", Georgia, serif; --typography-display-0-font-weight: 800; --typography-display-0-font-size: 4.5rem; --typography-display-0-line-height: 5.25rem; --typography-display-0-letter-spacing: 0em; --typography-heading-1-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-1-font-weight: 500; --typography-heading-1-font-size: 2.125rem; --typography-heading-1-line-height: 2.625rem; --typography-heading-1-letter-spacing: normal; --typography-heading-2-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-2-font-weight: 600; --typography-heading-2-font-size: 1.75rem; --typography-heading-2-line-height: 2.25rem; --typography-heading-2-letter-spacing: normal; --typography-heading-3-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-3-font-weight: 600; --typography-heading-3-font-size: 1.375rem; --typography-heading-3-line-height: 1.875rem; --typography-heading-3-letter-spacing: normal; --typography-heading-4-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-4-font-weight: 600; --typography-heading-4-font-size: 1.125rem; --typography-heading-4-line-height: 1.5rem; --typography-heading-4-letter-spacing: normal; --typography-heading-5-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-5-font-weight: 600; --typography-heading-5-font-size: 1rem; --typography-heading-5-line-height: 1.5rem; --typography-heading-5-letter-spacing: normal; --typography-heading-6-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-6-font-weight: 600; --typography-heading-6-font-size: 0.875rem; --typography-heading-6-line-height: 1.5rem; --typography-heading-6-letter-spacing: normal; --typography-paragraph-intro-lede-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-intro-lede-font-weight: 400; --typography-paragraph-intro-lede-font-size: 1.25rem; --typography-paragraph-intro-lede-line-height: 1.875rem; --typography-paragraph-intro-lede-letter-spacing: 0; --typography-paragraph-intro-lede-max-width: 975px; --typography-paragraph-body-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-body-font-weight: 400; --typography-paragraph-body-font-size: 1rem; --typography-paragraph-body-line-height: 1.5rem; --typography-paragraph-body-letter-spacing: normal; --typography-paragraph-body-max-width: 780px; --typography-paragraph-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-small-font-weight: 400; --typography-paragraph-small-font-size: 0.875rem; --typography-paragraph-small-line-height: 1.125rem; --typography-paragraph-small-letter-spacing: normal; --typography-paragraph-small-max-width: 680px; --typography-paragraph-extra-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-extra-small-font-weight: 400; --typography-paragraph-extra-small-font-size: 0.75rem; --typography-paragraph-extra-small-line-height: 1.125rem; --typography-paragraph-extra-small-letter-spacing: normal; --typography-paragraph-extra-small-max-width: 600px; --typography-paragraph-bold-font-weight: 600; --typography-button-primary-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-button-primary-font-weight: 500; --typography-button-primary-font-size: 1.125rem; --typography-button-primary-line-height: 1.5rem; --typography-button-primary-letter-spacing: normal; --typography-button-secondary-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-button-secondary-font-weight: 500; --typography-button-secondary-font-size: 1rem; --typography-button-secondary-line-height: 1.5rem; --typography-button-secondary-letter-spacing: normal;} \ No newline at end of file diff --git a/packages/design-tokens/less/color.less b/packages/design-tokens/less/color.less index a64de3c516e..0137b56c626 100644 --- a/packages/design-tokens/less/color.less +++ b/packages/design-tokens/less/color.less @@ -185,7 +185,9 @@ @color-gray-300: var(--color-gray-300, #eaeaec); @color-gray-400: var(--color-gray-400, #cdcdd0); @color-gray-500: var(--color-gray-500, #878792); +@color-gray-550: var(--color-gray-550, #6d6674); @color-gray-600: var(--color-gray-600, #524e56); +@color-gray-700: var(--color-gray-700, #3f3c42); @color-gray-100-rgb: var(--color-gray-100-rgb, 249, 249, 249); @color-gray-100-rgb-id: --color-gray-100-rgb; @color-gray-100-id: --color-gray-100; @@ -201,9 +203,15 @@ @color-gray-500-rgb: var(--color-gray-500-rgb, 135, 135, 146); @color-gray-500-rgb-id: --color-gray-500-rgb; @color-gray-500-id: --color-gray-500; +@color-gray-550-rgb: var(--color-gray-550-rgb, 109, 102, 116); +@color-gray-550-rgb-id: --color-gray-550-rgb; +@color-gray-550-id: --color-gray-550; @color-gray-600-rgb: var(--color-gray-600-rgb, 82, 78, 86); @color-gray-600-rgb-id: --color-gray-600-rgb; @color-gray-600-id: --color-gray-600; +@color-gray-700-rgb: var(--color-gray-700-rgb, 63, 60, 66); +@color-gray-700-rgb-id: --color-gray-700-rgb; +@color-gray-700-id: --color-gray-700; @color-white: var(--color-white, #ffffff); @color-white-rgb: var(--color-white-rgb, 255, 255, 255); @color-white-rgb-id: --color-white-rgb; diff --git a/packages/design-tokens/less/semantic.less b/packages/design-tokens/less/semantic.less new file mode 100644 index 00000000000..346abb05014 --- /dev/null +++ b/packages/design-tokens/less/semantic.less @@ -0,0 +1,53 @@ +/** THIS IS AN AUTOGENERATED FILE **/ + +@bg-primary: var(--bg-primary, var(--color-white)); +@bg-secondary: var(--bg-secondary, var(--color-gray-200)); +@bg-secondary_hover: var(--bg-secondary_hover, var(--color-gray-200)); +@bg-tertiary: var(--bg-tertiary, var(--color-gray-300)); +@bg-primary-solid: var(--bg-primary-solid, var(--color-purple-800)); +@bg-secondary-solid: var(--bg-secondary-solid, var(--color-gray-600)); +@bg-overlay: var(--bg-overlay, var(--color-white)); +@bg-brand-primary: var(--bg-brand-primary, var(--color-blue-100)); +@bg-brand-secondary: var(--bg-brand-secondary, var(--color-blue-200)); +@bg-brand-solid: var(--bg-brand-solid, var(--color-blue-500)); +@bg-brand-solid_hover: var(--bg-brand-solid_hover, var(--color-blue-700)); +@bg-error-primary: var(--bg-error-primary, var(--color-red-100)); +@bg-error-secondary: var(--bg-error-secondary, var(--color-red-300)); +@bg-error-solid: var(--bg-error-solid, var(--color-red-400)); +@bg-success-primary: var(--bg-success-primary, var(--color-green-100)); +@bg-success-secondary: var(--bg-success-secondary, var(--color-green-300)); +@bg-success-solid: var(--bg-success-solid, var(--color-green-600)); +@bg-warning-primary: var(--bg-warning-primary, var(--color-yellow-100)); +@bg-warning-secondary: var(--bg-warning-secondary, var(--color-yellow-400)); +@bg-warning-solid: var(--bg-warning-solid, var(--color-yellow-400)); +@text-primary: var(--text-primary, var(--color-purple-800)); +@text-secondary: var(--text-secondary, var(--color-gray-700)); +@text-tertiary: var(--text-tertiary, var(--color-gray-600)); +@text-quaternary: var(--text-quaternary, var(--color-gray-550)); +@text-placeholder: var(--text-placeholder, var(--color-gray-550)); +@text-secondary_on-brand: var(--text-secondary_on-brand, var(--color-white)); +@text-quaternary_on-brand: var(--text-quaternary_on-brand, var(--color-white)); +@text-brand-primary: var(--text-brand-primary, var(--color-blue-500)); +@text-brand-secondary: var(--text-brand-secondary, var(--color-blue-700)); +@text-brand-secondary_hover: var(--text-brand-secondary_hover, var(--color-blue-600)); +@text-error-primary: var(--text-error-primary, var(--color-red-600)); +@text-success-primary: var(--text-success-primary, var(--color-green-600)); +@fg-primary: var(--fg-primary, var(--color-purple-800)); +@fg-secondary: var(--fg-secondary, var(--color-purple-800)); +@fg-secondary_hover: var(--fg-secondary_hover, var(--color-purple-800)); +@fg-tertiary: var(--fg-tertiary, var(--color-gray-500)); +@fg-quaternary: var(--fg-quaternary, var(--color-purple-800)); +@fg-white: var(--fg-white, var(--color-white)); +@fg-brand-primary: var(--fg-brand-primary, var(--color-blue-500)); +@fg-error-primary: var(--fg-error-primary, var(--color-red-500)); +@fg-success-primary: var(--fg-success-primary, var(--color-green-500)); +@fg-success-secondary: var(--fg-success-secondary, var(--color-green-400)); +@fg-warning-primary: var(--fg-warning-primary, var(--color-yellow-700)); +@border-primary: var(--border-primary, var(--color-gray-600)); +@border-secondary: var(--border-secondary, var(--color-gray-500)); +@border-secondary_alt: var(--border-secondary_alt, var(--color-gray-200)); +@border-tertiary: var(--border-tertiary, var(--color-gray-300)); +@border-brand: var(--border-brand, var(--color-blue-500)); +@border-brand_alt: var(--border-brand_alt, var(--color-blue-300)); +@border-error: var(--border-error, var(--color-red-500)); +@border-error_subtle: var(--border-error_subtle, var(--color-red-300)); diff --git a/packages/design-tokens/package.json b/packages/design-tokens/package.json index 69926d274b1..146ad72c623 100644 --- a/packages/design-tokens/package.json +++ b/packages/design-tokens/package.json @@ -26,11 +26,12 @@ "scripts": { "lint:ts": "tsc --noEmit", "test": "FORCE_COLOR=1 vitest --config ../../vite.config.ts", - "build": "pnpm clean:dist && pnpm build:json && pnpm build:less && pnpm build:sass && pnpm build:ts", + "build": "pnpm clean:dist && pnpm build:json && pnpm build:less && pnpm build:sass && pnpm build:semantic && pnpm build:ts", "build:json": "tsx ./bin/buildCssVarTokens.ts", "build:ts": "pnpm package-bundler build", "build:less": "json-to-flat-sass './tokens/*.json' 'less' --extension 'less' --caseType 'kebab' && prettier less/* --write", "build:sass": "json-to-flat-sass './tokens/*.json' 'sass' --extension 'scss' --caseType 'kebab' && prettier sass/* --write", + "build:semantic": "tsx ./bin/buildSemanticTokens.ts && prettier css/semantic.css less/semantic.less sass/semantic.scss --write", "clean": "rimraf 'dist' 'node_modules' '.turbo'", "clean:dist": "rimraf 'dist'" }, diff --git a/packages/design-tokens/sass/color.scss b/packages/design-tokens/sass/color.scss index 1a858f18440..1ca178cdeba 100644 --- a/packages/design-tokens/sass/color.scss +++ b/packages/design-tokens/sass/color.scss @@ -185,7 +185,9 @@ $color-gray-200: var(--color-gray-200, #f4f4f5); $color-gray-300: var(--color-gray-300, #eaeaec); $color-gray-400: var(--color-gray-400, #cdcdd0); $color-gray-500: var(--color-gray-500, #878792); +$color-gray-550: var(--color-gray-550, #6d6674); $color-gray-600: var(--color-gray-600, #524e56); +$color-gray-700: var(--color-gray-700, #3f3c42); $color-gray-100-rgb: var(--color-gray-100-rgb, 249, 249, 249); $color-gray-100-rgb-id: --color-gray-100-rgb; $color-gray-100-id: --color-gray-100; @@ -201,9 +203,15 @@ $color-gray-400-id: --color-gray-400; $color-gray-500-rgb: var(--color-gray-500-rgb, 135, 135, 146); $color-gray-500-rgb-id: --color-gray-500-rgb; $color-gray-500-id: --color-gray-500; +$color-gray-550-rgb: var(--color-gray-550-rgb, 109, 102, 116); +$color-gray-550-rgb-id: --color-gray-550-rgb; +$color-gray-550-id: --color-gray-550; $color-gray-600-rgb: var(--color-gray-600-rgb, 82, 78, 86); $color-gray-600-rgb-id: --color-gray-600-rgb; $color-gray-600-id: --color-gray-600; +$color-gray-700-rgb: var(--color-gray-700-rgb, 63, 60, 66); +$color-gray-700-rgb-id: --color-gray-700-rgb; +$color-gray-700-id: --color-gray-700; $color-white: var(--color-white, #ffffff); $color-white-rgb: var(--color-white-rgb, 255, 255, 255); $color-white-rgb-id: --color-white-rgb; diff --git a/packages/design-tokens/sass/semantic.scss b/packages/design-tokens/sass/semantic.scss new file mode 100644 index 00000000000..9b555789b2f --- /dev/null +++ b/packages/design-tokens/sass/semantic.scss @@ -0,0 +1,53 @@ +/** THIS IS AN AUTOGENERATED FILE **/ + +$bg-primary: var(--bg-primary, var(--color-white)); +$bg-secondary: var(--bg-secondary, var(--color-gray-200)); +$bg-secondary_hover: var(--bg-secondary_hover, var(--color-gray-200)); +$bg-tertiary: var(--bg-tertiary, var(--color-gray-300)); +$bg-primary-solid: var(--bg-primary-solid, var(--color-purple-800)); +$bg-secondary-solid: var(--bg-secondary-solid, var(--color-gray-600)); +$bg-overlay: var(--bg-overlay, var(--color-white)); +$bg-brand-primary: var(--bg-brand-primary, var(--color-blue-100)); +$bg-brand-secondary: var(--bg-brand-secondary, var(--color-blue-200)); +$bg-brand-solid: var(--bg-brand-solid, var(--color-blue-500)); +$bg-brand-solid_hover: var(--bg-brand-solid_hover, var(--color-blue-700)); +$bg-error-primary: var(--bg-error-primary, var(--color-red-100)); +$bg-error-secondary: var(--bg-error-secondary, var(--color-red-300)); +$bg-error-solid: var(--bg-error-solid, var(--color-red-400)); +$bg-success-primary: var(--bg-success-primary, var(--color-green-100)); +$bg-success-secondary: var(--bg-success-secondary, var(--color-green-300)); +$bg-success-solid: var(--bg-success-solid, var(--color-green-600)); +$bg-warning-primary: var(--bg-warning-primary, var(--color-yellow-100)); +$bg-warning-secondary: var(--bg-warning-secondary, var(--color-yellow-400)); +$bg-warning-solid: var(--bg-warning-solid, var(--color-yellow-400)); +$text-primary: var(--text-primary, var(--color-purple-800)); +$text-secondary: var(--text-secondary, var(--color-gray-700)); +$text-tertiary: var(--text-tertiary, var(--color-gray-600)); +$text-quaternary: var(--text-quaternary, var(--color-gray-550)); +$text-placeholder: var(--text-placeholder, var(--color-gray-550)); +$text-secondary_on-brand: var(--text-secondary_on-brand, var(--color-white)); +$text-quaternary_on-brand: var(--text-quaternary_on-brand, var(--color-white)); +$text-brand-primary: var(--text-brand-primary, var(--color-blue-500)); +$text-brand-secondary: var(--text-brand-secondary, var(--color-blue-700)); +$text-brand-secondary_hover: var(--text-brand-secondary_hover, var(--color-blue-600)); +$text-error-primary: var(--text-error-primary, var(--color-red-600)); +$text-success-primary: var(--text-success-primary, var(--color-green-600)); +$fg-primary: var(--fg-primary, var(--color-purple-800)); +$fg-secondary: var(--fg-secondary, var(--color-purple-800)); +$fg-secondary_hover: var(--fg-secondary_hover, var(--color-purple-800)); +$fg-tertiary: var(--fg-tertiary, var(--color-gray-500)); +$fg-quaternary: var(--fg-quaternary, var(--color-purple-800)); +$fg-white: var(--fg-white, var(--color-white)); +$fg-brand-primary: var(--fg-brand-primary, var(--color-blue-500)); +$fg-error-primary: var(--fg-error-primary, var(--color-red-500)); +$fg-success-primary: var(--fg-success-primary, var(--color-green-500)); +$fg-success-secondary: var(--fg-success-secondary, var(--color-green-400)); +$fg-warning-primary: var(--fg-warning-primary, var(--color-yellow-700)); +$border-primary: var(--border-primary, var(--color-gray-600)); +$border-secondary: var(--border-secondary, var(--color-gray-500)); +$border-secondary_alt: var(--border-secondary_alt, var(--color-gray-200)); +$border-tertiary: var(--border-tertiary, var(--color-gray-300)); +$border-brand: var(--border-brand, var(--color-blue-500)); +$border-brand_alt: var(--border-brand_alt, var(--color-blue-300)); +$border-error: var(--border-error, var(--color-red-500)); +$border-error_subtle: var(--border-error_subtle, var(--color-red-300)); diff --git a/packages/design-tokens/src/js/semanticColorTokens.ts b/packages/design-tokens/src/js/semanticColorTokens.ts index 89f0aed5733..b7eecd16384 100644 --- a/packages/design-tokens/src/js/semanticColorTokens.ts +++ b/packages/design-tokens/src/js/semanticColorTokens.ts @@ -124,3 +124,22 @@ export const semanticColorTokens: SemanticColorTokens = { 'border-error_subtle': 'var(--color-red-300)', }, } + +/** + * All four semantic colour groups merged into a single flat record. + * Useful for exhaustive iteration (e.g. the CSS-var build script) and + * for deriving the union type of all canonical token names. + * + * NOTE: keys are preserved verbatim — underscores are intentional UUI + * separators (e.g. `text-primary_on-brand`). ESLint camelcase does not + * apply because keys are quoted string literals, not identifiers. + */ +export const flatSemanticColorTokens: Record = { + ...semanticColorTokens.background, + ...semanticColorTokens.text, + ...semanticColorTokens.foreground, + ...semanticColorTokens.border, +} + +/** Union of every canonical semantic colour token name. */ +export type SemanticColorTokenName = keyof typeof flatSemanticColorTokens diff --git a/packages/design-tokens/tokens/color.json b/packages/design-tokens/tokens/color.json index 75d4d8cb777..0f4ff331e4f 100644 --- a/packages/design-tokens/tokens/color.json +++ b/packages/design-tokens/tokens/color.json @@ -200,7 +200,9 @@ "300": "var(--color-gray-300, #eaeaec)", "400": "var(--color-gray-400, #cdcdd0)", "500": "var(--color-gray-500, #878792)", + "550": "var(--color-gray-550, #6d6674)", "600": "var(--color-gray-600, #524e56)", + "700": "var(--color-gray-700, #3f3c42)", "100-rgb": "var(--color-gray-100-rgb, 249, 249, 249)", "100-rgb-id": "--color-gray-100-rgb", "100-id": "--color-gray-100", @@ -216,9 +218,15 @@ "500-rgb": "var(--color-gray-500-rgb, 135, 135, 146)", "500-rgb-id": "--color-gray-500-rgb", "500-id": "--color-gray-500", + "550-rgb": "var(--color-gray-550-rgb, 109, 102, 116)", + "550-rgb-id": "--color-gray-550-rgb", + "550-id": "--color-gray-550", "600-rgb": "var(--color-gray-600-rgb, 82, 78, 86)", "600-rgb-id": "--color-gray-600-rgb", - "600-id": "--color-gray-600" + "600-id": "--color-gray-600", + "700-rgb": "var(--color-gray-700-rgb, 63, 60, 66)", + "700-rgb-id": "--color-gray-700-rgb", + "700-id": "--color-gray-700" }, "white": "var(--color-white, #ffffff)", "white-rgb": "var(--color-white-rgb, 255, 255, 255)", diff --git a/packages/tailwind/src/tailwind-presets.ts b/packages/tailwind/src/tailwind-presets.ts index 3517d678472..e6554fa96c7 100644 --- a/packages/tailwind/src/tailwind-presets.ts +++ b/packages/tailwind/src/tailwind-presets.ts @@ -1,10 +1,37 @@ -import { type CustomThemeConfig } from 'tailwindcss/types/config' -import { tokens } from '@kaizen/design-tokens/js' +import plugin from 'tailwindcss/plugin' +import { type CustomThemeConfig, type PluginsConfig } from 'tailwindcss/types/config' +import { semanticColorTokens, tokens } from '@kaizen/design-tokens' import { kzSpacing } from './kz-spacing' +/** + * Strip a category prefix from semantic token keys and filter out null values, + * mapping each remaining key to the semantic CSS variable (not the primitive). + * + * e.g. stripAndMap(semanticColorTokens.background, 'bg-') produces: + * { 'primary': 'var(--bg-primary)', 'secondary': 'var(--bg-secondary)', ... } + * (null-valued tokens are omitted) + * + * Tailwind then re-adds the category prefix so `bg-primary` is the emitted class. + */ +function stripAndMap(group: Record, prefix: string): Record { + const result: Record = {} + for (const [key, value] of Object.entries(group)) { + if (value === null) continue + const stripped = key.startsWith(prefix) ? key.slice(prefix.length) : key + result[stripped] = `var(--${key})` + } + return result +} + +const semanticBackgroundColors = stripAndMap(semanticColorTokens.background, 'bg-') +const semanticTextColors = stripAndMap(semanticColorTokens.text, 'text-') +const semanticBorderColors = stripAndMap(semanticColorTokens.border, 'border-') +const semanticForegroundColors = stripAndMap(semanticColorTokens.foreground, 'fg-') + export type KaizenTailwindTheme = Partial export type KaizenTailwindPreset = { theme: KaizenTailwindTheme + plugins?: Partial } // Note: changing any token will require to to run `pnpm build` from the root @@ -16,6 +43,9 @@ export const kaizenTailwindTheme: KaizenTailwindTheme = { 'paragraph-sm': `${tokens.typography.paragraphSmall.maxWidth}`, 'paragraph-xs': `${tokens.typography.paragraphExtraSmall.maxWidth}`, }, + backgroundColor: semanticBackgroundColors, + textColor: semanticTextColors, + borderColor: semanticBorderColors, }, colors: { transparent: 'transparent', @@ -111,6 +141,11 @@ export const kaizenTailwindTheme: KaizenTailwindTheme = { }, } as const +const fgPlugin = plugin(({ matchUtilities }) => { + matchUtilities({ fg: (value) => ({ color: value }) }, { values: semanticForegroundColors }) +}) + export const Preset: KaizenTailwindPreset = { theme: kaizenTailwindTheme, + plugins: [fgPlugin], } From 1c3e60874f41d75312b72f23ae1302e8c3f6d905 Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Tue, 30 Jun 2026 11:31:11 +1000 Subject: [PATCH 03/25] feat(design-tokens): inline semantic colour tokens into variables.css Bundle the semantic colour tokens into the generated variables.css so any consumer of the design-tokens CSS gets them automatically, with no extra import. The semantic block is appended by build:semantic (idempotent via a marker comment) after build:json regenerates the primitives. Also drop the Less output for the semantic tokens (CSS + SCSS only). Co-Authored-By: Claude Opus 4.8 (1M context) --- .changeset/semantic-colour-tokens.md | 6 ++ .../design-tokens/bin/buildSemanticTokens.ts | 21 ++++--- packages/design-tokens/css/variables.css | 56 ++++++++++++++++++- packages/design-tokens/less/semantic.less | 53 ------------------ packages/design-tokens/package.json | 2 +- 5 files changed, 75 insertions(+), 63 deletions(-) create mode 100644 .changeset/semantic-colour-tokens.md delete mode 100644 packages/design-tokens/less/semantic.less diff --git a/.changeset/semantic-colour-tokens.md b/.changeset/semantic-colour-tokens.md new file mode 100644 index 00000000000..4ae924808e4 --- /dev/null +++ b/.changeset/semantic-colour-tokens.md @@ -0,0 +1,6 @@ +--- +'@kaizen/design-tokens': minor +'@kaizen/tailwind': minor +--- + +feat: add semantic colour tokens (background, text, foreground, border) and expand the gray primitive ramp with `gray-550` and `gray-700`. Exposes the tokens as CSS variables (inlined into `variables.css`), SCSS, JS exports, and Tailwind preset utilities. diff --git a/packages/design-tokens/bin/buildSemanticTokens.ts b/packages/design-tokens/bin/buildSemanticTokens.ts index 597d4955d46..581d0276e33 100644 --- a/packages/design-tokens/bin/buildSemanticTokens.ts +++ b/packages/design-tokens/bin/buildSemanticTokens.ts @@ -3,7 +3,6 @@ import path from 'path' import { semanticColorTokens } from '../src/js/semanticColorTokens' const CSS_OUTPUT_DIR = `${process.cwd()}/css` -const LESS_OUTPUT_DIR = `${process.cwd()}/less` const SASS_OUTPUT_DIR = `${process.cwd()}/sass` const AUTOGENERATED_HEADER = '/** THIS IS AN AUTOGENERATED FILE **/' @@ -18,7 +17,6 @@ const flatEntries = Object.values(semanticColorTokens) const run = (): void => { fs.mkdirSync(CSS_OUTPUT_DIR, { recursive: true }) - fs.mkdirSync(LESS_OUTPUT_DIR, { recursive: true }) fs.mkdirSync(SASS_OUTPUT_DIR, { recursive: true }) // css/semantic.css — CSS custom properties on :root @@ -28,12 +26,19 @@ const run = (): void => { `${AUTOGENERATED_HEADER}\n\n:root {\n${cssLines.join('\n')}\n}\n`, ) - // less/semantic.less — LESS variables that fall back through the CSS var - const lessLines = flatEntries.map(([key, value]) => `@${key}: var(--${key}, ${value});`) - fs.writeFileSync( - path.resolve(LESS_OUTPUT_DIR, 'semantic.less'), - `${AUTOGENERATED_HEADER}\n\n${lessLines.join('\n')}\n`, - ) + // Inline the same semantic vars into the primitives entrypoint (variables.css) + // so every consumer of variables.css gets them automatically — no extra import. + // Runs after build:json (which regenerates variables.css), and is idempotent + // via the marker so re-running build:semantic alone won't duplicate the block. + const VARIABLES_PATH = path.resolve(CSS_OUTPUT_DIR, 'variables.css') + const SEMANTIC_MARKER = '/* --- Semantic colour tokens (autogenerated) --- */' + if (fs.existsSync(VARIABLES_PATH)) { + const existing = fs.readFileSync(VARIABLES_PATH, 'utf8') + const markerIdx = existing.indexOf(SEMANTIC_MARKER) + const primitives = markerIdx === -1 ? existing : existing.slice(0, markerIdx) + const semanticBlock = `${SEMANTIC_MARKER}\n:root {\n${cssLines.join('\n')}\n}\n` + fs.writeFileSync(VARIABLES_PATH, `${primitives.trimEnd()}\n\n${semanticBlock}`) + } // sass/semantic.scss — SCSS variables that fall back through the CSS var const scssLines = flatEntries.map(([key, value]) => `$${key}: var(--${key}, ${value});`) diff --git a/packages/design-tokens/css/variables.css b/packages/design-tokens/css/variables.css index 3fcb34e1b71..2d25f02a79f 100644 --- a/packages/design-tokens/css/variables.css +++ b/packages/design-tokens/css/variables.css @@ -2,4 +2,58 @@ /** THIS IS AN AUTOGENERATED FILE **/ :root{--animation-easing-function-ease-in-out: cubic-bezier(0.455, 0.03, 0.515, 0.955); --animation-easing-function-ease-in: cubic-bezier(0.55, 0.085, 0.68, 0.53); --animation-easing-function-ease-out: cubic-bezier(0.25, 0.46, 0.45, 0.94); --animation-easing-function-linear: linear; --animation-easing-function-bounce-in: cubic-bezier(0.485, 0.155, 0.24, 1.245); --animation-easing-function-bounce-out: cubic-bezier(0.485, 0.155, 0.515, 0.845); --animation-easing-function-bounce-in-out: cubic-bezier(0.76, -0.245, 0.24, 1.245); --animation-duration-instant: 0ms; --animation-duration-immediate: 100ms; --animation-duration-rapid: 200ms; --animation-duration-fast: 300ms; --animation-duration-slow: 400ms; --animation-duration-deliberate: 700ms; --border-solid-border-width: 2px; --border-solid-border-radius: 7px; --border-solid-border-style: solid; --border-solid-border-color: #e1e2ea; --border-solid-border-color-rgb: 225, 226, 234; --border-dashed-border-width: 2px; --border-dashed-border-radius: 7px; --border-dashed-border-style: dashed; --border-borderless-border-width: 2px; --border-borderless-border-radius: 7px; --border-borderless-border-style: solid; --border-borderless-border-color: transparent; --border-borderless-border-color-rgb: 0, 0, 0; --border-focus-ring-border-width: 2px; --border-focus-ring-border-radius: 10px; --border-focus-ring-border-style: solid; --border-width-1: 1px; --color-purple-100: #f4edf8; --color-purple-100-rgb: 244, 237, 248; --color-purple-200: #dfc9ea; --color-purple-200-rgb: 223, 201, 234; --color-purple-300: #c9a5dd; --color-purple-300-rgb: 201, 165, 221; --color-purple-400: #ae67b1; --color-purple-400-rgb: 174, 103, 177; --color-purple-500: #844587; --color-purple-500-rgb: 132, 69, 135; --color-purple-600: #5f3361; --color-purple-600-rgb: 95, 51, 97; --color-purple-700: #4a234d; --color-purple-700-rgb: 74, 35, 77; --color-purple-800: #2f2438; --color-purple-800-rgb: 47, 36, 56; --color-blue-100: #e6f6ff; --color-blue-100-rgb: 230, 246, 255; --color-blue-200: #bde2f5; --color-blue-200-rgb: 189, 226, 245; --color-blue-300: #73c0e8; --color-blue-300-rgb: 115, 192, 232; --color-blue-400: #008bd6; --color-blue-400-rgb: 0, 139, 214; --color-blue-500: #0168b3; --color-blue-500-rgb: 1, 104, 179; --color-blue-600: #004970; --color-blue-600-rgb: 0, 73, 112; --color-blue-700: #003157; --color-blue-700-rgb: 0, 49, 87; --color-green-100: #e8f8f4; --color-green-100-rgb: 232, 248, 244; --color-green-200: #c4ede2; --color-green-200-rgb: 196, 237, 226; --color-green-300: #8fdbc7; --color-green-300-rgb: 143, 219, 199; --color-green-400: #5dcaad; --color-green-400-rgb: 93, 202, 173; --color-green-500: #3f9a86; --color-green-500-rgb: 63, 154, 134; --color-green-600: #2c7d67; --color-green-600-rgb: 44, 125, 103; --color-green-700: #22594a; --color-green-700-rgb: 34, 89, 74; --color-yellow-100: #fff9e4; --color-yellow-100-rgb: 255, 249, 228; --color-yellow-200: #ffeeb3; --color-yellow-200-rgb: 255, 238, 179; --color-yellow-300: #ffe36e; --color-yellow-300-rgb: 255, 227, 110; --color-yellow-400: #ffca4d; --color-yellow-400-rgb: 255, 202, 77; --color-yellow-500: #ffb600; --color-yellow-500-rgb: 255, 182, 0; --color-yellow-600: #c68600; --color-yellow-600-rgb: 198, 134, 0; --color-yellow-700: #876400; --color-yellow-700-rgb: 135, 100, 0; --color-red-100: #fdeaee; --color-red-100-rgb: 253, 234, 238; --color-red-200: #f9c2cb; --color-red-200-rgb: 249, 194, 203; --color-red-300: #f597a8; --color-red-300-rgb: 245, 151, 168; --color-red-400: #e0707d; --color-red-400-rgb: 224, 112, 125; --color-red-500: #c93b55; --color-red-500-rgb: 201, 59, 85; --color-red-600: #a82433; --color-red-600-rgb: 168, 36, 51; --color-red-700: #6c1e20; --color-red-700-rgb: 108, 30, 32; --color-orange-100: #fff0e8; --color-orange-100-rgb: 255, 240, 232; --color-orange-200: #ffd1b9; --color-orange-200-rgb: 255, 209, 185; --color-orange-300: #ffb08a; --color-orange-300-rgb: 255, 176, 138; --color-orange-400: #ff9461; --color-orange-400-rgb: 255, 148, 97; --color-orange-500: #e96c2f; --color-orange-500-rgb: 233, 108, 47; --color-orange-600: #b74302; --color-orange-600-rgb: 183, 67, 2; --color-orange-700: #903c00; --color-orange-700-rgb: 144, 60, 0; --color-gray-100: #f9f9f9; --color-gray-100-rgb: 249, 249, 249; --color-gray-200: #f4f4f5; --color-gray-200-rgb: 244, 244, 245; --color-gray-300: #eaeaec; --color-gray-300-rgb: 234, 234, 236; --color-gray-400: #cdcdd0; --color-gray-400-rgb: 205, 205, 208; --color-gray-500: #878792; --color-gray-500-rgb: 135, 135, 146; --color-gray-550: #6d6674; --color-gray-550-rgb: 109, 102, 116; --color-gray-600: #524e56; --color-gray-600-rgb: 82, 78, 86; --color-gray-700: #3f3c42; --color-gray-700-rgb: 63, 60, 66; --color-white: #ffffff; --color-white-rgb: 255, 255, 255; --color-black: #000000; --color-black-rgb: 0, 0, 0; --data-viz-favorable: #7dd5bd; --data-viz-favorable-rgb: 125, 213, 189; --data-viz-unfavorable: #e68d97; --data-viz-unfavorable-rgb: 230, 141, 151; --layout-content-max-width: 1392px; --layout-content-max-width-with-sidebar: 1080px; --layout-content-side-margin: 72px; --layout-mobile-actions-drawer-height: 60px; --layout-navigation-bar-height: 72px; --layout-breakpoints-medium: 768px; --layout-breakpoints-large: 1080px; --shadow-small-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 3px 16px 0 rgba(0, 0, 0, 0.06); --shadow-large-box-shadow: 0 3px 9px 0 rgba(0, 0, 0, 0.1), 0 8px 40px 0 rgba(0, 0, 0, 0.08); --spacing-0: 0; --spacing-1: .0625rem; --spacing-2: .125rem; --spacing-4: .25rem; --spacing-6: .375rem; --spacing-8: .5rem; --spacing-12: .75rem; --spacing-16: 1rem; --spacing-20: 1.25rem; --spacing-24: 1.5rem; --spacing-32: 2rem; --spacing-40: 2.5rem; --spacing-48: 3rem; --spacing-56: 3.5rem; --spacing-64: 4rem; --spacing-72: 4.5rem; --spacing-80: 5rem; --spacing-96: 6rem; --spacing-112: 7rem; --spacing-128: 8rem; --spacing-160: 10rem; --spacing-200: 12.5rem; --spacing-240: 15rem; --spacing-280: 17.5rem; --spacing-320: 20rem; --spacing-xs: 0.375rem; --spacing-sm: 0.75rem; --spacing-md: 1.5rem; --spacing-lg: 2.25rem; --spacing-xl: 3rem; --spacing-xxl: 3.75rem; --spacing-xxxl: 4.5rem; --spacing-xxxxl: 5.25rem; --spacing-xxxxxl: 6rem; --typography-data-large-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-large-font-weight: 700; --typography-data-large-font-size: 5.25rem; --typography-data-large-line-height: 5.25rem; --typography-data-large-letter-spacing: normal; --typography-data-large-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-large-units-font-weight: 700; --typography-data-large-units-font-size: 2.625rem; --typography-data-large-units-line-height: 5.25rem; --typography-data-large-units-letter-spacing: normal; --typography-data-medium-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-medium-font-weight: 700; --typography-data-medium-font-size: 3rem; --typography-data-medium-line-height: 5rem; --typography-data-medium-letter-spacing: normal; --typography-data-medium-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-medium-units-font-weight: 700; --typography-data-medium-units-font-size: 1.5rem; --typography-data-medium-units-line-height: 5rem; --typography-data-medium-units-letter-spacing: normal; --typography-data-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-small-font-weight: 700; --typography-data-small-font-size: 1.5rem; --typography-data-small-line-height: 1.5rem; --typography-data-small-letter-spacing: normal; --typography-data-small-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-small-units-font-weight: 700; --typography-data-small-units-font-size: 1.125rem; --typography-data-small-units-line-height: 1.5rem; --typography-data-small-units-letter-spacing: normal; --typography-display-0-font-family: "Tiempos Headline", Georgia, serif; --typography-display-0-font-weight: 800; --typography-display-0-font-size: 4.5rem; --typography-display-0-line-height: 5.25rem; --typography-display-0-letter-spacing: 0em; --typography-heading-1-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-1-font-weight: 500; --typography-heading-1-font-size: 2.125rem; --typography-heading-1-line-height: 2.625rem; --typography-heading-1-letter-spacing: normal; --typography-heading-2-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-2-font-weight: 600; --typography-heading-2-font-size: 1.75rem; --typography-heading-2-line-height: 2.25rem; --typography-heading-2-letter-spacing: normal; --typography-heading-3-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-3-font-weight: 600; --typography-heading-3-font-size: 1.375rem; --typography-heading-3-line-height: 1.875rem; --typography-heading-3-letter-spacing: normal; --typography-heading-4-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-4-font-weight: 600; --typography-heading-4-font-size: 1.125rem; --typography-heading-4-line-height: 1.5rem; --typography-heading-4-letter-spacing: normal; --typography-heading-5-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-5-font-weight: 600; --typography-heading-5-font-size: 1rem; --typography-heading-5-line-height: 1.5rem; --typography-heading-5-letter-spacing: normal; --typography-heading-6-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-6-font-weight: 600; --typography-heading-6-font-size: 0.875rem; --typography-heading-6-line-height: 1.5rem; --typography-heading-6-letter-spacing: normal; --typography-paragraph-intro-lede-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-intro-lede-font-weight: 400; --typography-paragraph-intro-lede-font-size: 1.25rem; --typography-paragraph-intro-lede-line-height: 1.875rem; --typography-paragraph-intro-lede-letter-spacing: 0; --typography-paragraph-intro-lede-max-width: 975px; --typography-paragraph-body-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-body-font-weight: 400; --typography-paragraph-body-font-size: 1rem; --typography-paragraph-body-line-height: 1.5rem; --typography-paragraph-body-letter-spacing: normal; --typography-paragraph-body-max-width: 780px; --typography-paragraph-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-small-font-weight: 400; --typography-paragraph-small-font-size: 0.875rem; --typography-paragraph-small-line-height: 1.125rem; --typography-paragraph-small-letter-spacing: normal; --typography-paragraph-small-max-width: 680px; --typography-paragraph-extra-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-extra-small-font-weight: 400; --typography-paragraph-extra-small-font-size: 0.75rem; --typography-paragraph-extra-small-line-height: 1.125rem; --typography-paragraph-extra-small-letter-spacing: normal; --typography-paragraph-extra-small-max-width: 600px; --typography-paragraph-bold-font-weight: 600; --typography-button-primary-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-button-primary-font-weight: 500; --typography-button-primary-font-size: 1.125rem; --typography-button-primary-line-height: 1.5rem; --typography-button-primary-letter-spacing: normal; --typography-button-secondary-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-button-secondary-font-weight: 500; --typography-button-secondary-font-size: 1rem; --typography-button-secondary-line-height: 1.5rem; --typography-button-secondary-letter-spacing: normal;} - \ No newline at end of file + +/* --- Semantic colour tokens (autogenerated) --- */ +:root { + --bg-primary: var(--color-white); + --bg-secondary: var(--color-gray-200); + --bg-secondary_hover: var(--color-gray-200); + --bg-tertiary: var(--color-gray-300); + --bg-primary-solid: var(--color-purple-800); + --bg-secondary-solid: var(--color-gray-600); + --bg-overlay: var(--color-white); + --bg-brand-primary: var(--color-blue-100); + --bg-brand-secondary: var(--color-blue-200); + --bg-brand-solid: var(--color-blue-500); + --bg-brand-solid_hover: var(--color-blue-700); + --bg-error-primary: var(--color-red-100); + --bg-error-secondary: var(--color-red-300); + --bg-error-solid: var(--color-red-400); + --bg-success-primary: var(--color-green-100); + --bg-success-secondary: var(--color-green-300); + --bg-success-solid: var(--color-green-600); + --bg-warning-primary: var(--color-yellow-100); + --bg-warning-secondary: var(--color-yellow-400); + --bg-warning-solid: var(--color-yellow-400); + --text-primary: var(--color-purple-800); + --text-secondary: var(--color-gray-700); + --text-tertiary: var(--color-gray-600); + --text-quaternary: var(--color-gray-550); + --text-placeholder: var(--color-gray-550); + --text-secondary_on-brand: var(--color-white); + --text-quaternary_on-brand: var(--color-white); + --text-brand-primary: var(--color-blue-500); + --text-brand-secondary: var(--color-blue-700); + --text-brand-secondary_hover: var(--color-blue-600); + --text-error-primary: var(--color-red-600); + --text-success-primary: var(--color-green-600); + --fg-primary: var(--color-purple-800); + --fg-secondary: var(--color-purple-800); + --fg-secondary_hover: var(--color-purple-800); + --fg-tertiary: var(--color-gray-500); + --fg-quaternary: var(--color-purple-800); + --fg-white: var(--color-white); + --fg-brand-primary: var(--color-blue-500); + --fg-error-primary: var(--color-red-500); + --fg-success-primary: var(--color-green-500); + --fg-success-secondary: var(--color-green-400); + --fg-warning-primary: var(--color-yellow-700); + --border-primary: var(--color-gray-600); + --border-secondary: var(--color-gray-500); + --border-secondary_alt: var(--color-gray-200); + --border-tertiary: var(--color-gray-300); + --border-brand: var(--color-blue-500); + --border-brand_alt: var(--color-blue-300); + --border-error: var(--color-red-500); + --border-error_subtle: var(--color-red-300); +} diff --git a/packages/design-tokens/less/semantic.less b/packages/design-tokens/less/semantic.less deleted file mode 100644 index 346abb05014..00000000000 --- a/packages/design-tokens/less/semantic.less +++ /dev/null @@ -1,53 +0,0 @@ -/** THIS IS AN AUTOGENERATED FILE **/ - -@bg-primary: var(--bg-primary, var(--color-white)); -@bg-secondary: var(--bg-secondary, var(--color-gray-200)); -@bg-secondary_hover: var(--bg-secondary_hover, var(--color-gray-200)); -@bg-tertiary: var(--bg-tertiary, var(--color-gray-300)); -@bg-primary-solid: var(--bg-primary-solid, var(--color-purple-800)); -@bg-secondary-solid: var(--bg-secondary-solid, var(--color-gray-600)); -@bg-overlay: var(--bg-overlay, var(--color-white)); -@bg-brand-primary: var(--bg-brand-primary, var(--color-blue-100)); -@bg-brand-secondary: var(--bg-brand-secondary, var(--color-blue-200)); -@bg-brand-solid: var(--bg-brand-solid, var(--color-blue-500)); -@bg-brand-solid_hover: var(--bg-brand-solid_hover, var(--color-blue-700)); -@bg-error-primary: var(--bg-error-primary, var(--color-red-100)); -@bg-error-secondary: var(--bg-error-secondary, var(--color-red-300)); -@bg-error-solid: var(--bg-error-solid, var(--color-red-400)); -@bg-success-primary: var(--bg-success-primary, var(--color-green-100)); -@bg-success-secondary: var(--bg-success-secondary, var(--color-green-300)); -@bg-success-solid: var(--bg-success-solid, var(--color-green-600)); -@bg-warning-primary: var(--bg-warning-primary, var(--color-yellow-100)); -@bg-warning-secondary: var(--bg-warning-secondary, var(--color-yellow-400)); -@bg-warning-solid: var(--bg-warning-solid, var(--color-yellow-400)); -@text-primary: var(--text-primary, var(--color-purple-800)); -@text-secondary: var(--text-secondary, var(--color-gray-700)); -@text-tertiary: var(--text-tertiary, var(--color-gray-600)); -@text-quaternary: var(--text-quaternary, var(--color-gray-550)); -@text-placeholder: var(--text-placeholder, var(--color-gray-550)); -@text-secondary_on-brand: var(--text-secondary_on-brand, var(--color-white)); -@text-quaternary_on-brand: var(--text-quaternary_on-brand, var(--color-white)); -@text-brand-primary: var(--text-brand-primary, var(--color-blue-500)); -@text-brand-secondary: var(--text-brand-secondary, var(--color-blue-700)); -@text-brand-secondary_hover: var(--text-brand-secondary_hover, var(--color-blue-600)); -@text-error-primary: var(--text-error-primary, var(--color-red-600)); -@text-success-primary: var(--text-success-primary, var(--color-green-600)); -@fg-primary: var(--fg-primary, var(--color-purple-800)); -@fg-secondary: var(--fg-secondary, var(--color-purple-800)); -@fg-secondary_hover: var(--fg-secondary_hover, var(--color-purple-800)); -@fg-tertiary: var(--fg-tertiary, var(--color-gray-500)); -@fg-quaternary: var(--fg-quaternary, var(--color-purple-800)); -@fg-white: var(--fg-white, var(--color-white)); -@fg-brand-primary: var(--fg-brand-primary, var(--color-blue-500)); -@fg-error-primary: var(--fg-error-primary, var(--color-red-500)); -@fg-success-primary: var(--fg-success-primary, var(--color-green-500)); -@fg-success-secondary: var(--fg-success-secondary, var(--color-green-400)); -@fg-warning-primary: var(--fg-warning-primary, var(--color-yellow-700)); -@border-primary: var(--border-primary, var(--color-gray-600)); -@border-secondary: var(--border-secondary, var(--color-gray-500)); -@border-secondary_alt: var(--border-secondary_alt, var(--color-gray-200)); -@border-tertiary: var(--border-tertiary, var(--color-gray-300)); -@border-brand: var(--border-brand, var(--color-blue-500)); -@border-brand_alt: var(--border-brand_alt, var(--color-blue-300)); -@border-error: var(--border-error, var(--color-red-500)); -@border-error_subtle: var(--border-error_subtle, var(--color-red-300)); diff --git a/packages/design-tokens/package.json b/packages/design-tokens/package.json index 146ad72c623..833129e91d5 100644 --- a/packages/design-tokens/package.json +++ b/packages/design-tokens/package.json @@ -31,7 +31,7 @@ "build:ts": "pnpm package-bundler build", "build:less": "json-to-flat-sass './tokens/*.json' 'less' --extension 'less' --caseType 'kebab' && prettier less/* --write", "build:sass": "json-to-flat-sass './tokens/*.json' 'sass' --extension 'scss' --caseType 'kebab' && prettier sass/* --write", - "build:semantic": "tsx ./bin/buildSemanticTokens.ts && prettier css/semantic.css less/semantic.less sass/semantic.scss --write", + "build:semantic": "tsx ./bin/buildSemanticTokens.ts && prettier css/semantic.css sass/semantic.scss --write", "clean": "rimraf 'dist' 'node_modules' '.turbo'", "clean:dist": "rimraf 'dist'" }, From 69b6d1eacf178bf600f2a088231b7e93f3d1b1ce Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Tue, 30 Jun 2026 11:45:43 +1000 Subject: [PATCH 04/25] ignore console.log eslint error --- packages/design-tokens/bin/buildSemanticTokens.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/design-tokens/bin/buildSemanticTokens.ts b/packages/design-tokens/bin/buildSemanticTokens.ts index 581d0276e33..061bea33465 100644 --- a/packages/design-tokens/bin/buildSemanticTokens.ts +++ b/packages/design-tokens/bin/buildSemanticTokens.ts @@ -52,6 +52,7 @@ const run = (): void => { ).length const nullCount = totalTokens - flatEntries.length + // eslint-disable-next-line no-console -- intentional build-script progress output console.log( `Semantic tokens written: ${flatEntries.length} emitted, ${nullCount} null-skipped (${totalTokens} total).`, ) From 13a92a667876b4291ec7be52a8213490da72fcf7 Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Tue, 30 Jun 2026 12:23:06 +1000 Subject: [PATCH 05/25] adds design-tokens as peer dep --- packages/tailwind/package.json | 5 +-- pnpm-lock.yaml | 71 ++++++++++++---------------------- 2 files changed, 27 insertions(+), 49 deletions(-) diff --git a/packages/tailwind/package.json b/packages/tailwind/package.json index f259f55f52d..2d6dc121f3a 100644 --- a/packages/tailwind/package.json +++ b/packages/tailwind/package.json @@ -27,11 +27,9 @@ "author": "", "private": false, "license": "MIT", - "dependencies": { - "@kaizen/design-tokens": "workspace:*" - }, "devDependencies": { "@cultureamp/package-bundler": "^4.0.1", + "@kaizen/design-tokens": "workspace:*", "@tailwindcss/container-queries": "^0.1.1", "classnames": "^2.5.1", "react": "^19.2.7", @@ -41,6 +39,7 @@ "tslib": "^2.8.1" }, "peerDependencies": { + "@kaizen/design-tokens": "workspace:^", "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0", "tailwindcss": ">=3.4.7" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c8ac0ccfada..4a5626b9996 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -202,7 +202,7 @@ importers: version: 8.6.17(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(storybook@8.6.17(prettier@3.8.4)) '@storybook/builder-vite': specifier: 8.6.17 - version: 8.6.17(storybook@8.6.17(prettier@3.8.4))(vite@7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4)) + version: 8.6.17(storybook@8.6.17(prettier@3.8.4))(vite@7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4)) '@storybook/manager-api': specifier: 8.6.17 version: 8.6.17(storybook@8.6.17(prettier@3.8.4)) @@ -211,7 +211,7 @@ importers: version: 8.6.17(@storybook/test@8.6.17(storybook@8.6.17(prettier@3.8.4)))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(storybook@8.6.17(prettier@3.8.4))(typescript@5.9.3) '@storybook/react-vite': specifier: 8.6.17 - version: 8.6.17(@storybook/test@8.6.17(storybook@8.6.17(prettier@3.8.4)))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(rollup@4.61.1)(storybook@8.6.17(prettier@3.8.4))(typescript@5.9.3)(vite@7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4)) + version: 8.6.17(@storybook/test@8.6.17(storybook@8.6.17(prettier@3.8.4)))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(rollup@4.61.1)(storybook@8.6.17(prettier@3.8.4))(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4)) '@storybook/test-runner': specifier: ^0.24.4 version: 0.24.4(@swc/helpers@0.5.15)(@types/node@22.19.21)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.25.12))(storybook@8.6.17(prettier@3.8.4))(ts-node@10.9.2(@swc/core@1.7.10(@swc/helpers@0.5.15))(@types/node@22.19.21)(typescript@5.9.3)) @@ -226,7 +226,7 @@ importers: version: 0.12.8 '@vitejs/plugin-react': specifier: ^6.0.2 - version: 6.0.2(vite@7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4)) + version: 6.0.2(vite@7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4)) axe-playwright: specifier: ^2.2.2 version: 2.2.2(playwright@1.60.0) @@ -259,7 +259,7 @@ importers: version: 3.4.19(tsx@4.22.4) vite-plugin-node-polyfills: specifier: ^0.28.0 - version: 0.28.0(rollup@4.61.1)(vite@7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4)) + version: 0.28.0(rollup@4.61.1)(vite@7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4)) packages/components: dependencies: @@ -578,14 +578,13 @@ importers: version: 4.22.4 packages/tailwind: - dependencies: - '@kaizen/design-tokens': - specifier: workspace:* - version: link:../design-tokens devDependencies: '@cultureamp/package-bundler': specifier: ^4.0.1 version: 4.0.1(@babel/core@7.29.7)(@types/babel__core@7.20.5)(postcss-preset-env@11.3.0(postcss@8.5.15))(postcss@8.5.15)(rollup@4.61.1)(tslib@2.8.1)(typescript@5.9.3) + '@kaizen/design-tokens': + specifier: workspace:* + version: link:../design-tokens '@tailwindcss/container-queries': specifier: ^0.1.1 version: 0.1.1(tailwindcss@3.4.19(tsx@4.22.4)) @@ -1314,11 +1313,6 @@ packages: '@cultureamp/next-head-hook': '>=1 || ~0.0.0' next: '>=13.5.0' react: '>=16.14.0' - peerDependenciesMeta: - '@cultureamp/next-head-hook': - optional: true - next: - optional: true '@cultureamp/frontend-env@2.1.6': resolution: {integrity: sha512-6FYwQ08fTns6zMjRC74M2wSah8bMBSVsMxRBYmq7KWQOyYT/Jb7/BPpcrFjPaBzvnoKBLQ06TrbykCcZOkGRSA==, tarball: https://npm.pkg.github.com/download/@cultureamp/frontend-env/2.1.6/e7375ab88fbc9f9770f2094896a6dc5185094165} @@ -1334,11 +1328,6 @@ packages: eslint: ^9.39.4 next: '>=13.5.0' react: ^18.3.1 || ^19.0.0 - peerDependenciesMeta: - eslint: - optional: true - next: - optional: true '@cultureamp/next-head-hook@1.1.11': resolution: {integrity: sha512-FyaCA3oKHnxZ+pPHcPTCDoRCG4/1y0W16U1O5eyTgSxjuJfWTui3vz65MNvNxlJ20+DZ8BXmV3M0y93t/Fubog==, tarball: https://npm.pkg.github.com/download/@cultureamp/next-head-hook/1.1.11/5444465f7d6ce0d79ba33d60180245ed245956ad} @@ -11599,6 +11588,7 @@ snapshots: '@cultureamp/frontend-apis@13.3.0(@cultureamp/next-head-hook@1.1.11(next@15.2.5(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(sass@1.79.6)))(next@15.2.5(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(sass@1.79.6))(react@19.2.7)(typescript@5.9.3)': dependencies: '@cultureamp/frontend-env': 2.1.6 + '@cultureamp/next-head-hook': 1.1.11(next@15.2.5(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(sass@1.79.6)) '@cultureamp/redirect-to-login': 2.0.3 '@readme/openapi-parser': 2.7.0(openapi-types@12.1.3) '@tanstack/react-query': 5.76.2(react@19.2.7) @@ -11613,6 +11603,7 @@ snapshots: js-yaml: 4.1.1 jsrsasign: 11.1.0 msw: 2.2.14(typescript@5.9.3) + next: 15.2.5(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(sass@1.79.6) openapi-types: 12.1.3 openapi-typescript: 6.7.6 react: 19.2.7 @@ -11621,9 +11612,6 @@ snapshots: url-parse: 1.5.10 uuid: 9.0.1 yargs: 17.7.2 - optionalDependencies: - '@cultureamp/next-head-hook': 1.1.11(next@15.2.5(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(sass@1.79.6)) - next: 15.2.5(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(sass@1.79.6) transitivePeerDependencies: - '@chromatic-com/cypress' - '@chromatic-com/playwright' @@ -11652,6 +11640,7 @@ snapshots: '@formatjs/cli-lib': 6.6.6(ts-jest@29.2.4(@babel/core@7.29.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.29.7))(esbuild@0.28.0)(jest@30.2.0(@types/node@22.19.21)(esbuild-register@3.6.0(esbuild@0.28.0))(ts-node@10.9.2(@swc/core@1.7.10(@swc/helpers@0.5.15))(@types/node@22.19.21)(typescript@5.9.3)))(typescript@5.9.3)) babel-plugin-formatjs: 10.5.41(ts-jest@29.2.4(@babel/core@7.29.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.29.7))(esbuild@0.28.0)(jest@30.2.0(@types/node@22.19.21)(esbuild-register@3.6.0(esbuild@0.28.0))(ts-node@10.9.2(@swc/core@1.7.10(@swc/helpers@0.5.15))(@types/node@22.19.21)(typescript@5.9.3)))(typescript@5.9.3)) date-fns: 3.6.0 + eslint: 9.39.4(jiti@1.21.7) eslint-plugin-formatjs: 6.4.15(eslint@9.39.4(jiti@1.21.7))(ts-jest@29.2.4(@babel/core@7.29.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.29.7))(esbuild@0.28.0)(jest@30.2.0(@types/node@22.19.21)(esbuild-register@3.6.0(esbuild@0.28.0))(ts-node@10.9.2(@swc/core@1.7.10(@swc/helpers@0.5.15))(@types/node@22.19.21)(typescript@5.9.3)))(typescript@5.9.3)) fast-glob: 3.3.3 form-data: 4.0.5 @@ -11659,13 +11648,11 @@ snapshots: isomorphic-resolve: 1.0.0 json-stable-stringify: 1.3.0 limiter-es6-compat: 2.1.2 + next: 15.2.5(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(sass@1.79.6) react: 19.2.7 react-intl: 7.1.14(react@19.2.7)(typescript@5.9.3) smartling-api-sdk-nodejs: 2.35.0(encoding@0.1.13) yargs: 17.7.2 - optionalDependencies: - eslint: 9.39.4(jiti@1.21.7) - next: 15.2.5(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(sass@1.79.6) transitivePeerDependencies: - '@chromatic-com/cypress' - '@chromatic-com/playwright' @@ -11686,7 +11673,6 @@ snapshots: dependencies: next: 15.2.5(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(sass@1.79.6) react: 18.3.1 - optional: true '@cultureamp/package-bundler@4.0.1(@babel/core@7.29.7)(@types/babel__core@7.20.5)(postcss-preset-env@11.3.0(postcss@8.5.15))(postcss@8.5.15)(rollup@4.61.1)(tslib@2.8.1)(typescript@5.9.3)': dependencies: @@ -12792,12 +12778,12 @@ snapshots: '@types/yargs': 17.0.33 chalk: 4.1.2 - '@joshwooding/vite-plugin-react-docgen-typescript@0.5.0(typescript@5.9.3)(vite@7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4))': + '@joshwooding/vite-plugin-react-docgen-typescript@0.5.0(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4))': dependencies: glob: 10.5.0 magic-string: 0.27.0 react-docgen-typescript: 2.2.2(typescript@5.9.3) - vite: 7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4) + vite: 7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4) optionalDependencies: typescript: 5.9.3 @@ -12887,8 +12873,7 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@next/env@15.2.5': - optional: true + '@next/env@15.2.5': {} '@next/swc-darwin-arm64@15.2.5': optional: true @@ -14514,13 +14499,13 @@ snapshots: react: 19.2.7 react-dom: 19.2.7(react@19.2.7) - '@storybook/builder-vite@8.6.17(storybook@8.6.17(prettier@3.8.4))(vite@7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4))': + '@storybook/builder-vite@8.6.17(storybook@8.6.17(prettier@3.8.4))(vite@7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4))': dependencies: '@storybook/csf-plugin': 8.6.17(storybook@8.6.17(prettier@3.8.4)) browser-assert: 1.2.1 storybook: 8.6.17(prettier@3.8.4) ts-dedent: 2.2.0 - vite: 7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4) + vite: 7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4) '@storybook/components@8.6.17(storybook@8.6.17(prettier@3.8.4))': dependencies: @@ -14587,11 +14572,11 @@ snapshots: react-dom: 19.2.7(react@19.2.7) storybook: 8.6.17(prettier@3.8.4) - '@storybook/react-vite@8.6.17(@storybook/test@8.6.17(storybook@8.6.17(prettier@3.8.4)))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(rollup@4.61.1)(storybook@8.6.17(prettier@3.8.4))(typescript@5.9.3)(vite@7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4))': + '@storybook/react-vite@8.6.17(@storybook/test@8.6.17(storybook@8.6.17(prettier@3.8.4)))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(rollup@4.61.1)(storybook@8.6.17(prettier@3.8.4))(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4))': dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.5.0(typescript@5.9.3)(vite@7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4)) + '@joshwooding/vite-plugin-react-docgen-typescript': 0.5.0(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4)) '@rollup/pluginutils': 5.1.4(rollup@4.61.1) - '@storybook/builder-vite': 8.6.17(storybook@8.6.17(prettier@3.8.4))(vite@7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4)) + '@storybook/builder-vite': 8.6.17(storybook@8.6.17(prettier@3.8.4))(vite@7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4)) '@storybook/react': 8.6.17(@storybook/test@8.6.17(storybook@8.6.17(prettier@3.8.4)))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(storybook@8.6.17(prettier@3.8.4))(typescript@5.9.3) find-up: 5.0.0 magic-string: 0.30.21 @@ -14601,7 +14586,7 @@ snapshots: resolve: 1.22.12 storybook: 8.6.17(prettier@3.8.4) tsconfig-paths: 4.2.0 - vite: 7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4) + vite: 7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4) optionalDependencies: '@storybook/test': 8.6.17(storybook@8.6.17(prettier@3.8.4)) transitivePeerDependencies: @@ -15353,10 +15338,10 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true - '@vitejs/plugin-react@6.0.2(vite@7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4))': + '@vitejs/plugin-react@6.0.2(vite@7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4))': dependencies: '@rolldown/pluginutils': 1.0.1 - vite: 7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4) + vite: 7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4) '@vitest/eslint-plugin@1.6.20(@typescript-eslint/eslint-plugin@8.61.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.4(jiti@1.21.7))(typescript@5.9.3)(vitest@3.2.6(@types/debug@4.1.13)(@types/node@22.19.21)(jiti@1.21.7)(jsdom@20.0.3)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4))': dependencies: @@ -15968,7 +15953,6 @@ snapshots: busboy@1.6.0: dependencies: streamsearch: 1.1.0 - optional: true cac@6.7.14: {} @@ -19549,7 +19533,6 @@ snapshots: transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - optional: true no-case@3.0.4: dependencies: @@ -20560,7 +20543,6 @@ snapshots: nanoid: 3.3.12 picocolors: 1.1.1 source-map-js: 1.2.1 - optional: true postcss@8.5.15: dependencies: @@ -21035,7 +21017,6 @@ snapshots: react@18.3.1: dependencies: loose-envify: 1.4.0 - optional: true react@19.2.7: {} @@ -21635,8 +21616,7 @@ snapshots: readable-stream: 3.6.2 xtend: 4.0.2 - streamsearch@1.1.0: - optional: true + streamsearch@1.1.0: {} strict-event-emitter@0.5.1: {} @@ -21781,7 +21761,6 @@ snapshots: react: 19.2.7 optionalDependencies: '@babel/core': 7.29.7 - optional: true stylehacks@7.0.11(postcss@8.5.15): dependencies: @@ -22554,11 +22533,11 @@ snapshots: - tsx - yaml - vite-plugin-node-polyfills@0.28.0(rollup@4.61.1)(vite@7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4)): + vite-plugin-node-polyfills@0.28.0(rollup@4.61.1)(vite@7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4)): dependencies: '@rollup/plugin-inject': 5.0.5(rollup@4.61.1) node-stdlib-browser: 1.3.1 - vite: 7.3.5(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4) + vite: 7.3.1(@types/node@22.19.21)(jiti@1.21.7)(less@4.2.0)(sass@1.79.6)(stylus@0.62.0)(terser@5.31.5)(tsx@4.22.4)(yaml@2.8.4) transitivePeerDependencies: - rollup From d74c7ca65b0b5ff47418c549f9adcfe60d76e2cf Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Tue, 30 Jun 2026 12:23:20 +1000 Subject: [PATCH 06/25] fix graphql fetch --- .github/actions/setup/action.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index db4f3f22fd1..970f976c722 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -16,7 +16,13 @@ runs: - name: Cache pnpm store uses: actions/setup-node@v4 with: - node-version-file: package.json + # Pin to .nvmrc (single version) instead of the package.json `engines` + # range. A range lets setup-node float to the latest available Node, + # which after the 2026-06-18 security batch is a poisoned release + # (24.17.0 / 26.3.1) that makes node-fetch@2 throw a false + # ERR_STREAM_PREMATURE_CLOSE — breaking `changeset version`'s GitHub + # GraphQL changelog fetch. See nodejs/node#63989. + node-version-file: .nvmrc registry-url: https://npm.pkg.github.com/ cache: 'pnpm' From abf58b0a5415433ab262b772e82787896a0c477b Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Tue, 30 Jun 2026 14:46:27 +1000 Subject: [PATCH 07/25] changeset --- .changeset/semantic-colour-tokens.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.changeset/semantic-colour-tokens.md b/.changeset/semantic-colour-tokens.md index 4ae924808e4..36e412a2ccd 100644 --- a/.changeset/semantic-colour-tokens.md +++ b/.changeset/semantic-colour-tokens.md @@ -1,6 +1,9 @@ --- '@kaizen/design-tokens': minor '@kaizen/tailwind': minor +'@kaizen/components': patch --- feat: add semantic colour tokens (background, text, foreground, border) and expand the gray primitive ramp with `gray-550` and `gray-700`. Exposes the tokens as CSS variables (inlined into `variables.css`), SCSS, JS exports, and Tailwind preset utilities. + +`@kaizen/tailwind` now declares `@kaizen/design-tokens` as a peer dependency: the semantic Tailwind utilities emit `var(--)` references whose definitions live in `@kaizen/design-tokens`, so the two must be upgraded together. A mismatched/old `@kaizen/design-tokens` now surfaces a peer-dependency warning at install instead of silently rendering the wrong colours. From 6ea449b3531c8fd04c5ffb87452cac031c3ad235 Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Wed, 1 Jul 2026 10:37:42 +1000 Subject: [PATCH 08/25] feat(design-tokens): expose semantic colour tokens on the JS tokens export Spread the semantic colour tokens into `tokens.color`, keyed both by their verbatim kebab name (`tokens.color['bg-brand-solid']`) and a camelCase alias (`tokens.color.bgBrandSolid`). Preserve literal keys via `satisfies` so the name unions stay type-safe, and add a `KebabToCamel` type + derived `semanticColorTokensCamel` map. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/js/semanticColorTokens.ts | 33 ++++++++++++++++--- packages/design-tokens/src/js/tokens.ts | 6 ++++ packages/design-tokens/src/types.ts | 7 +++- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/packages/design-tokens/src/js/semanticColorTokens.ts b/packages/design-tokens/src/js/semanticColorTokens.ts index b7eecd16384..cc8fff12893 100644 --- a/packages/design-tokens/src/js/semanticColorTokens.ts +++ b/packages/design-tokens/src/js/semanticColorTokens.ts @@ -40,7 +40,7 @@ export interface SemanticColorTokens { border: SemanticColorTokenGroup } -export const semanticColorTokens: SemanticColorTokens = { +export const semanticColorTokens = { background: { 'bg-primary': 'var(--color-white)', 'bg-primary_alt': null, @@ -123,7 +123,7 @@ export const semanticColorTokens: SemanticColorTokens = { 'border-error': 'var(--color-red-500)', 'border-error_subtle': 'var(--color-red-300)', }, -} +} satisfies SemanticColorTokens /** * All four semantic colour groups merged into a single flat record. @@ -134,12 +134,37 @@ export const semanticColorTokens: SemanticColorTokens = { * separators (e.g. `text-primary_on-brand`). ESLint camelcase does not * apply because keys are quoted string literals, not identifiers. */ -export const flatSemanticColorTokens: Record = { +export const flatSemanticColorTokens = { ...semanticColorTokens.background, ...semanticColorTokens.text, ...semanticColorTokens.foreground, ...semanticColorTokens.border, -} +} satisfies Record /** Union of every canonical semantic colour token name. */ export type SemanticColorTokenName = keyof typeof flatSemanticColorTokens + +/** + * Convert a canonical kebab/underscore token name to a camelCase JS key. + * `bg-brand-solid` → `bgBrandSolid`, `text-primary_on-brand` → `textPrimaryOnBrand`. + */ +type KebabToCamel = S extends `${infer Head}${'-' | '_'}${infer Tail}` + ? `${Head}${Capitalize>}` + : S + +/** camelCase variant of every semantic colour token name. */ +export type SemanticColorTokenCamelName = KebabToCamel + +const toCamelCase = (name: string): string => + name.replace(/[-_]([a-z])/g, (_match, char: string) => char.toUpperCase()) + +/** + * Semantic colour tokens keyed by camelCase JS identifier, for ergonomic dot + * access (e.g. `bgBrandSolid`). Derived from {@link flatSemanticColorTokens} so + * the kebab name stays the single source of truth — this is only a JS-friendly + * alias. Use the kebab names (the `--bg-brand-solid` CSS var, the Tailwind + * class, the Figma variable) when you need cross-platform string identity. + */ +export const semanticColorTokensCamel = Object.fromEntries( + Object.entries(flatSemanticColorTokens).map(([name, value]) => [toCamelCase(name), value]), +) as Record diff --git a/packages/design-tokens/src/js/tokens.ts b/packages/design-tokens/src/js/tokens.ts index 3a5f6fa5070..1c492301b38 100644 --- a/packages/design-tokens/src/js/tokens.ts +++ b/packages/design-tokens/src/js/tokens.ts @@ -1,4 +1,5 @@ import { type TokenStructure } from '../types' +import { flatSemanticColorTokens, semanticColorTokensCamel } from './semanticColorTokens' export const tokens: TokenStructure = { animation: { @@ -115,6 +116,11 @@ export const tokens: TokenStructure = { }, white: '#ffffff', black: '#000000', + // Semantic colour tokens, exposed under both their verbatim kebab name + // (`tokens.color['bg-brand-solid']`) and a camelCase alias + // (`tokens.color.bgBrandSolid`). See semanticColorTokens.ts. + ...flatSemanticColorTokens, + ...semanticColorTokensCamel, }, dataViz: { favorable: '#7dd5bd', diff --git a/packages/design-tokens/src/types.ts b/packages/design-tokens/src/types.ts index 3bacedfb43b..9ac47fd5e25 100644 --- a/packages/design-tokens/src/types.ts +++ b/packages/design-tokens/src/types.ts @@ -1,4 +1,9 @@ import type { CSSProperties as ReactCSSProperties } from 'react' +import type { + SemanticColorTokenCamelName, + SemanticColorTokenName, + SemanticColorTokenValue, +} from './js/semanticColorTokens' /** * Use a custom type for CSS properties becauase we should eventually write a more strongly typed version using template literal types. @@ -144,7 +149,7 @@ export type TokenStructure = { } white: Hex black: Hex - } + } & Record dataViz: { favorable: Hex unfavorable: Hex From b290e9c1877c7a410cb6a3e4831f0f426ca9180a Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Wed, 1 Jul 2026 10:38:03 +1000 Subject: [PATCH 09/25] refactor(design-tokens): rename semantic token output to semantic-color Category-scope the generated semantic files so future token categories can sit alongside them (e.g. semantic-typography): sass/semantic.scss -> sass/ semantic-color.scss and css/semantic.css -> css/semantic-color.css. Updates the generator output paths and the build:semantic prettier target. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/design-tokens/bin/buildSemanticTokens.ts | 8 ++++---- .../css/{semantic.css => semantic-color.css} | 0 packages/design-tokens/package.json | 2 +- .../sass/{semantic.scss => semantic-color.scss} | 0 4 files changed, 5 insertions(+), 5 deletions(-) rename packages/design-tokens/css/{semantic.css => semantic-color.css} (100%) rename packages/design-tokens/sass/{semantic.scss => semantic-color.scss} (100%) diff --git a/packages/design-tokens/bin/buildSemanticTokens.ts b/packages/design-tokens/bin/buildSemanticTokens.ts index 061bea33465..89a0ef5c687 100644 --- a/packages/design-tokens/bin/buildSemanticTokens.ts +++ b/packages/design-tokens/bin/buildSemanticTokens.ts @@ -19,10 +19,10 @@ const run = (): void => { fs.mkdirSync(CSS_OUTPUT_DIR, { recursive: true }) fs.mkdirSync(SASS_OUTPUT_DIR, { recursive: true }) - // css/semantic.css — CSS custom properties on :root + // css/semantic-color.css — CSS custom properties on :root const cssLines = flatEntries.map(([key, value]) => ` --${key}: ${value};`) fs.writeFileSync( - path.resolve(CSS_OUTPUT_DIR, 'semantic.css'), + path.resolve(CSS_OUTPUT_DIR, 'semantic-color.css'), `${AUTOGENERATED_HEADER}\n\n:root {\n${cssLines.join('\n')}\n}\n`, ) @@ -40,10 +40,10 @@ const run = (): void => { fs.writeFileSync(VARIABLES_PATH, `${primitives.trimEnd()}\n\n${semanticBlock}`) } - // sass/semantic.scss — SCSS variables that fall back through the CSS var + // sass/semantic-color.scss — SCSS variables that fall back through the CSS var const scssLines = flatEntries.map(([key, value]) => `$${key}: var(--${key}, ${value});`) fs.writeFileSync( - path.resolve(SASS_OUTPUT_DIR, 'semantic.scss'), + path.resolve(SASS_OUTPUT_DIR, 'semantic-color.scss'), `${AUTOGENERATED_HEADER}\n\n${scssLines.join('\n')}\n`, ) diff --git a/packages/design-tokens/css/semantic.css b/packages/design-tokens/css/semantic-color.css similarity index 100% rename from packages/design-tokens/css/semantic.css rename to packages/design-tokens/css/semantic-color.css diff --git a/packages/design-tokens/package.json b/packages/design-tokens/package.json index 833129e91d5..709ca3ad01c 100644 --- a/packages/design-tokens/package.json +++ b/packages/design-tokens/package.json @@ -31,7 +31,7 @@ "build:ts": "pnpm package-bundler build", "build:less": "json-to-flat-sass './tokens/*.json' 'less' --extension 'less' --caseType 'kebab' && prettier less/* --write", "build:sass": "json-to-flat-sass './tokens/*.json' 'sass' --extension 'scss' --caseType 'kebab' && prettier sass/* --write", - "build:semantic": "tsx ./bin/buildSemanticTokens.ts && prettier css/semantic.css sass/semantic.scss --write", + "build:semantic": "tsx ./bin/buildSemanticTokens.ts && prettier css/semantic-color.css sass/semantic-color.scss --write", "clean": "rimraf 'dist' 'node_modules' '.turbo'", "clean:dist": "rimraf 'dist'" }, diff --git a/packages/design-tokens/sass/semantic.scss b/packages/design-tokens/sass/semantic-color.scss similarity index 100% rename from packages/design-tokens/sass/semantic.scss rename to packages/design-tokens/sass/semantic-color.scss From 774d0a7b7772325a3bc8103a1fdfa60b83aa2687 Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Wed, 1 Jul 2026 10:38:31 +1000 Subject: [PATCH 10/25] docs(design-tokens): update token guides for semantic tokens - JS guide: use semantic colour tokens instead of old primitives. - SASS guide: use semantic tokens in examples; caution against manipulating colour opacity (accessibility + semantic tokens are solid); add an import-map table clarifying each category is a separate scoped entrypoint. - example.scss: import sass/semantic-color and use a semantic token. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../_docs/pages/examples/example.scss | 4 +- .../_docs/pages/how-to-use-in-js.mdx | 8 +- .../_docs/pages/how-to-use-with-sass.mdx | 106 +++++++++++++++--- 3 files changed, 98 insertions(+), 20 deletions(-) diff --git a/packages/design-tokens/_docs/pages/examples/example.scss b/packages/design-tokens/_docs/pages/examples/example.scss index 5d0097345b0..fee9dea0498 100644 --- a/packages/design-tokens/_docs/pages/examples/example.scss +++ b/packages/design-tokens/_docs/pages/examples/example.scss @@ -1,7 +1,7 @@ @import '~@kaizen/design-tokens/sass/typography'; -@import '~@kaizen/design-tokens/sass/color'; +@import '~@kaizen/design-tokens/sass/semantic-color'; .myClass { - background-color: $color-gray-100; + background-color: $bg-secondary; font-family: $typography-data-large-font-family; } diff --git a/packages/design-tokens/_docs/pages/how-to-use-in-js.mdx b/packages/design-tokens/_docs/pages/how-to-use-in-js.mdx index 09cecceaffb..a2e83ce5484 100644 --- a/packages/design-tokens/_docs/pages/how-to-use-in-js.mdx +++ b/packages/design-tokens/_docs/pages/how-to-use-in-js.mdx @@ -21,7 +21,7 @@ For example: const Component = () => (
Custom Kaizen theme component @@ -37,7 +37,11 @@ You can access the tokens directly: import { tokens } from '@kaizen/design-tokens/js' const myAmazingFunction = () => { - const mainColor = data ? tokens.colors.purple[500] : tokens.colors.purple[300] + // Semantic tokens are available via a camelCase alias… + const mainColor = data ? tokens.color.bgBrandSolid : tokens.color.bgSecondary + + // …or by their verbatim name, matching the CSS variable / Tailwind class: + // tokens.color['bg-brand-solid'] return mainColor } diff --git a/packages/design-tokens/_docs/pages/how-to-use-with-sass.mdx b/packages/design-tokens/_docs/pages/how-to-use-with-sass.mdx index eafab3bae2e..0f85aa218c5 100644 --- a/packages/design-tokens/_docs/pages/how-to-use-with-sass.mdx +++ b/packages/design-tokens/_docs/pages/how-to-use-with-sass.mdx @@ -22,14 +22,83 @@ There are 2 different ways you can utilise the tokens: ```scss .myCustomClassName { - background-color: vars(--color-gray-100); + background-color: var(--bg-secondary); } ``` ### Importing SCSS vars - Import the CSS variable versions of the tokens -- Use these tokens in your CSS. They will be compiled to CSS variables (e.g. `$color-purple-800` will become `var(--color-purple-800)`) +- Use these tokens in your CSS. They will be compiled to CSS variables (e.g. `$bg-primary` will become `var(--bg-primary)`) + +Tokens are split across category-scoped entrypoints — import only the ones you need. There is no single "everything" SCSS import; each category is a separate file: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ImportTokensExample var
+ ~@kaizen/design-tokens/sass/semantic-color + Semantic colour tokens (recommended) + $bg-secondary, $text-primary +
+ ~@kaizen/design-tokens/sass/color + Colour primitives + $color-purple-500 +
+ ~@kaizen/design-tokens/sass/typography + Typography + $typography-data-large-font-family +
+ ~@kaizen/design-tokens/sass/border + Border radius / width / style + $border-solid-border-radius +
+ ~@kaizen/design-tokens/sass/spacing + Spacing + $spacing-16 +
+ ~@kaizen/design-tokens/sass/shadow, .../sass/animation,{' '} + .../sass/layout + Shadow, animation, layout
+ +> **Note:** `semantic-color` is colour-only. `$border-*` **in it** are border _colours_ (e.g. `$border-primary`); border _radius/width_ live in `sass/border`. As semantic tokens expand to other categories they'll get their own scoped entrypoints (e.g. `sass/semantic-typography`). Example: @@ -46,19 +115,30 @@ See API for all available tokens. -Because the exposed SASS variables contain values such as `var(--color-purple-800)`, the SASS compiler won't be able to calculate anything that relies on concrete values such as HEX strings. +Because the exposed SASS variables contain values such as `var(--text-primary)`, the SASS compiler won't be able to calculate anything that relies on concrete values such as HEX strings. -Usually when we've used functions like `mix` or `shade` it has been to lighten or darken a token by a certain amount. We recommend you find the nearest plain value. In the example above, you could simply use `$color-purple-200`. +Usually when we've used functions like `mix` or `shade` it has been to lighten or darken a token by a certain amount. We recommend you find the nearest token that already has the tone you need — pick the semantic token for that purpose (e.g. `$text-secondary`) rather than computing one. -## 4. When you need to add opacity to a colour, use `rgba()` and the `-rgb-params` variables +## 4. Avoid adding opacity to colour tokens -**Use `rgba($color-purple-800-rgb, 0.5)` instead of `rgba($color-purple-800, 0.5)` to add alpha to a color.** +> **⚠️ Don't manipulate the opacity of a colour token.** Reach for a solid token +> that already has the value you want instead. -We have exposed extra sibling variables for every color, as seen in SASS Variables, which allow you to manipulate opacity of CSS variable colors: +Applying alpha to a colour (e.g. `rgba($color-purple-800-rgb, 0.5)`) is discouraged: + +- **Accessibility.** A translucent colour composites with whatever sits behind it, so its effective contrast depends on the background and is no longer predictable. This breaks contrast guarantees and is a common cause of WCAG failures. +- **Semantic tokens are solid.** Our semantic tokens (`text-secondary`, `text-tertiary`, etc.) deliberately map to **solid** primitives — they replace the old `purple-800` alpha hacks. Using `rgba()` on a token side-steps that system and reintroduces the problem we removed. + +**Instead, pick the nearest solid token.** If you previously dimmed a colour with opacity, choose the semantic token that lands at the tone you need — e.g. use `$text-tertiary` rather than applying alpha to `$text-primary`. + +
+If you genuinely still need alpha (rare) + +Only **primitive** colours expose a `-rgb` sibling variable — semantic tokens do not — so this escape hatch necessarily drops down to a primitive. Plain `rgba($color-gray-200, 0.5)` won't work either: neither SASS nor the browser can resolve `rgba(var(--color-gray-200), 0.5)`. The `-rgb` sibling points at a comma-separated channel list (`246, 246, 246`) for use inside `rgba()`: -For similar reasons to the previous section, a statement like `rgba($color-gray-200, 0.5)`, will not work because neither SASS or your browser can understand the expanded value: `rgba(var(--color-gray-200), 0.5)`. - -Every color variable such as `$color-gray-200` will have a matching sibling variable with the `-rgb` suffix. And `$color-gray-200-rgb` points to a CSS variable that contains a list of numbers, `246, 246, 246`, which browsers can then use in inside the `rgba()` function. - -For example `rgba($color-gray-200-rgb, 0.5)`, compiles to `rgba(var(--color-gray-200-rgb), 0.5)`, which the browser then resolves to `rgba(246, 246, 246, 0.5)`. - -## Migrating from compile time SASS functions like add-tint, darken, or mix +`rgba($color-gray-200-rgb, 0.5)` compiles to `rgba(var(--color-gray-200-rgb), 0.5)`, which the browser resolves to `rgba(246, 246, 246, 0.5)`. Treat this as a last resort, not the default. -A utility to help with this is coming soon. You will need to replace any function calls like these with design tokens, as these are both not computable using CSS variables, and have been deprecated for a while. +
From fc1c64f425f424f0483244ab9c5d5261af80eb0e Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Wed, 1 Jul 2026 10:38:46 +1000 Subject: [PATCH 11/25] docs(design-tokens): single colour-token page mapping primitives to semantic Collapse the colour docs into one docs-only page that maps every semantic token to the primitive it resolves to, with name + hex on both sides. Tokens with no mapping yet are flagged. Converts the CSF story to a plain component rendered inline in the MDX so there is a single sidebar entry instead of a story + docs. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../_docs/pages/color-tokens.mdx | 12 +- .../_docs/pages/color-tokens.stories.tsx | 184 ------------------ .../_docs/pages/color-tokens.tsx | 129 ++++++++++++ 3 files changed, 135 insertions(+), 190 deletions(-) delete mode 100644 packages/design-tokens/_docs/pages/color-tokens.stories.tsx create mode 100644 packages/design-tokens/_docs/pages/color-tokens.tsx diff --git a/packages/design-tokens/_docs/pages/color-tokens.mdx b/packages/design-tokens/_docs/pages/color-tokens.mdx index 84860ccc40c..421d0627f62 100644 --- a/packages/design-tokens/_docs/pages/color-tokens.mdx +++ b/packages/design-tokens/_docs/pages/color-tokens.mdx @@ -1,12 +1,12 @@ -import { Meta, Story } from '@storybook/blocks' -import * as ColorTokensStories from './color-tokens.stories' +import { Meta } from '@storybook/blocks' +import { ColorTokensDemo } from './color-tokens' - + # Color Tokens -Import the color tokens into your SCSS with `@import "~@kaizen/design-tokens/sass/color`. +Every semantic colour token mapped to the primitive it resolves to — with the token name and hex value on both sides. Use this to see which primitive backs a semantic token, and to find the semantic replacement for a raw primitive. -## Colors +Tokens are grouped by the surface they paint (`background`, `text`, `foreground`, `border`). Tokens with **no mapping yet** are flagged with a dashed red outline — these are awaiting design sign-off. - + diff --git a/packages/design-tokens/_docs/pages/color-tokens.stories.tsx b/packages/design-tokens/_docs/pages/color-tokens.stories.tsx deleted file mode 100644 index a0fffb04f10..00000000000 --- a/packages/design-tokens/_docs/pages/color-tokens.stories.tsx +++ /dev/null @@ -1,184 +0,0 @@ -import React, { type HTMLAttributes } from 'react' -import { type Meta, type StoryFn } from '@storybook/react' -import colorString from 'color-string' -import { Heading } from '~components/Heading' -import { tokens } from '~design-tokens/js' - -export default { - title: 'Guides/Tokens/Color Tokens', - parameters: { - chromatic: { - disable: false, - diffThreshold: 0, - }, - docsLayout: 'fullPage', - }, -} satisfies Meta - -/** - * Use this for showing a simple horizontal or vertical stack of elements, with the support of padding/gaps between each of them. - */ -const Stack = ({ - children, - gapSize, - horizontal, - style, - ...divAttributes -}: HTMLAttributes & { - horizontal?: boolean - gapSize?: keyof typeof tokens.spacing -}): JSX.Element => ( -
- {children} -
-) - -/** - * A component to show a simple color block with a name - */ -const ColorDemo = ({ color, name }: { color: string; name?: string }): JSX.Element | null => { - const parsedColor = colorString.get(color) - - if (!parsedColor) return null - - return ( -
-

{name}

- -
- - - {colorString.to.hex(...(parsedColor.value as Parameters))} - - - - - {colorString.to.rgb(...(parsedColor.value as Parameters))} - - -
-
- ) -} - -/** - * A section of components, displayed as a column, with some styles such as a top and left border, a heading/title, and `contain: content` to ensure nothing bleeds out of it such as fixed or absolute positioned elements. - */ -const ComponentsSection = ({ children }: { children: React.ReactNode }): JSX.Element => ( -
- {children} -
-) - -export const ColorTokens: StoryFn = () => ( -
- - - - Purple - - - - - - - - - - - Blue - - - - - - - - - - Red - - - - - - - - - - Orange - - - - - - - - - - Green - - - - - - - - - - Yellow - - - - - - - - - - Gray - - - - - - - - - White - - - - black - - - - -
-) diff --git a/packages/design-tokens/_docs/pages/color-tokens.tsx b/packages/design-tokens/_docs/pages/color-tokens.tsx new file mode 100644 index 00000000000..1b81b770d37 --- /dev/null +++ b/packages/design-tokens/_docs/pages/color-tokens.tsx @@ -0,0 +1,129 @@ +import React from 'react' +import { Heading } from '~components/Heading' +import { tokens, semanticColorTokens } from '~design-tokens/js' + +/** Pull the primitive name out of a semantic value, e.g. `var(--color-blue-500)` → `color-blue-500`. */ +const primitiveFromValue = (value: string): string | null => + value.match(/var\(--(.+?)\)/)?.[1] ?? null + +/** Resolve a primitive CSS-var name (`color-blue-500`, `color-white`) to its hex value. */ +const primitiveHex = (primitiveName: string): string | null => { + const path = primitiveName.replace(/^color-/, '').split('-') + const colors = tokens.color as Record + + if (path.length === 1) { + const value = colors[path[0]] + return typeof value === 'string' ? value : null + } + + const [hue, shade] = path + const ramp = colors[hue] as Record | undefined + return ramp?.[shade] ?? null +} + +/** A colour swatch; renders a hatched placeholder when there's no value. */ +const Swatch = ({ hex }: { hex: string | null }): JSX.Element => ( +
+) + +/** A swatch paired with a token name and its resolved hex value. */ +const Cell = ({ name, hex }: { name: string; hex: string | null }): JSX.Element => ( +
+ +
+ {name} + + {hex ?? 'No mapping yet'} + +
+
+) + +/** + * One mapping row: the primitive on the left, the semantic token it backs on + * the right. Both swatches resolve to the same hex — that's the mapping. Tokens + * with no mapping yet (`null`) are flagged with a dashed red outline. + */ +const MappingRow = ({ + semanticName, + value, +}: { + semanticName: string + value: string | null +}): JSX.Element => { + const isUnmapped = value === null + const primitiveName = value ? primitiveFromValue(value) : null + const hex = primitiveName ? primitiveHex(primitiveName) : null + + return ( +
+ + + → + + +
+ ) +} + +const GROUP_TITLES: Record = { + background: 'Background', + text: 'Text', + foreground: 'Foreground', + border: 'Border', +} + +/** + * The single source-of-truth colour reference: every semantic token mapped to + * the primitive it resolves to, with names and hex values on both sides. + */ +export const ColorTokensDemo = (): JSX.Element => ( +
+ {(Object.keys(semanticColorTokens) as Array).map((group) => ( +
+ + {GROUP_TITLES[group]} + + {Object.entries(semanticColorTokens[group]).map(([name, value]) => ( + + ))} +
+ ))} +
+) From 8664898c3ef977e8cbe9d4957b3b3b935f84b1b9 Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Wed, 1 Jul 2026 10:39:00 +1000 Subject: [PATCH 12/25] docs(design-tokens): Tailwind-first README and rename docs page to Overview Document the tokens' many output forms (JS, CSS vars, SCSS, deprecated Less), present Tailwind (@kaizen/tailwind preset) as the recommended way to consume them, and note semantic tokens are not emitted as Less. Rename the docs README page title from "README" to "Overview". Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/design-tokens/README.md | 57 ++++++++++++++++--- packages/design-tokens/_docs/pages/README.mdx | 2 +- 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/packages/design-tokens/README.md b/packages/design-tokens/README.md index bfbf9c83bbd..6264790430f 100644 --- a/packages/design-tokens/README.md +++ b/packages/design-tokens/README.md @@ -6,9 +6,18 @@ Design tokens for all platforms. Design tokens are named and stored visual design traits, including colors, typography, and animation timings. Design Tokens are the heart of every Design System. -The tokens represented here are platform-agnostic (JS object), as this will help us contribute to & facilitate the maintenance of living style guides. This package defines all the option tokens in Kaizen. +The canonical source of truth is a platform-agnostic JS object, which we transform into several consumable forms. This helps us contribute to & facilitate the maintenance of living style guides. This package defines all the option tokens in Kaizen. -In its current state this package supports Sass and Less variables, generated from a JS tokens file. +The tokens are exported in multiple forms: + +- **JavaScript / TypeScript** — `@kaizen/design-tokens/js` (the source object, including semantic colour tokens). +- **CSS custom properties** — `css/variables.css` (primitives with the semantic colour tokens inlined) and `css/semantic-color.css` (semantic colour tokens only). +- **SCSS variables** — `sass/*`, one entrypoint per category (e.g. `sass/color`, `sass/semantic-color`, `sass/typography`). +- **Less variables** — `less/*` — **deprecated, see [Less](#less-deprecated) below.** + +Most consumers should not reach for these forms directly — the **recommended** way to consume tokens is via the [`@kaizen/tailwind`](#tailwind-recommended) preset, which is built on top of them. + +> **Note:** the new semantic colour tokens are only published as **CSS custom properties**, **SCSS**, and **JS** — they are **not** emitted as Less variables. Note that as we employ [CSS Variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties), when consuming tokens in SASS/LESS you should assume they will contain values such as `var(--color-...)`, rather than concrete values such as `1.5rem` or `#fff`. @@ -20,28 +29,62 @@ pnpm add @kaizen/design-tokens ## Usage +**Tailwind is the recommended way to consume tokens** — see [Tailwind](#tailwind-recommended) below. The other forms (CSS variables, SCSS, JS) remain available for cases Tailwind doesn't cover. + Much of this assumes that consuming repos have setup the `KaizenProvider` - refer to the [App Starter guide](/docs/guides-app-starter--docs) for more. +### Tailwind (recommended) + +Most Kaizen apps consume tokens through Tailwind, and this is the preferred approach. Add the [`@kaizen/tailwind`](https://github.com/cultureamp/kaizen-design-system/tree/main/packages/tailwind) preset to your Tailwind config: + +```js +// tailwind.config.mjs +import { Preset } from '@kaizen/tailwind' + +export default { + content: ['./src/**/*.{ts,tsx}'], + presets: [Preset], +} +``` + +Then use the semantic token utility classes directly — `bg-*`, `text-*`, `border-*`, and `fg-*` (foreground / icons): + +```jsx +
+``` + +`@kaizen/tailwind` bundles `@kaizen/design-tokens` as a runtime dependency, so you don't need to install it separately for Tailwind. You only need to load its CSS variables once at runtime — `KaizenProvider` handles this, or import it directly: + +```js +import '@kaizen/design-tokens/css/variables.css' +``` + ### SCSS +Import a category entrypoint — one file per category, there is no single "everything" import: + ```scss -@import '~@kaizen/design-tokens/sass/[color/depth/layout/spacing/typography]'; +@import '~@kaizen/design-tokens/sass/semantic-color'; // semantic colour tokens ($bg-*, $text-*) +@import '~@kaizen/design-tokens/sass/color'; // colour primitives ($color-purple-500) +// also: typography, border, spacing, shadow, animation, layout ``` Or use the CSS variables directly (Recommended). ```scss .myCustomClassName { - background-color: vars(--color-gray-100); + background-color: var(--bg-secondary); } ``` -Read more in [How to use design tokens in SAAS](/docs/guides-tokens-how-to-use-design-tokens-in-sass--docs) +Read more in [How to use design tokens in SASS](/docs/guides-tokens-how-to-use-design-tokens-in-sass--docs) + +### Less (deprecated) -### Less +> ⚠️ **Less support is being wound down.** The new semantic colour tokens are **not** published as Less variables. New code should use CSS custom properties (recommended) or SCSS. Existing Less imports still resolve for primitive tokens but will not gain semantic tokens. ```less -@import '~@kaizen/design-tokens/less/[color/depth/layout/spacing/typography]'; +@import '~@kaizen/design-tokens/less/[color/layout/spacing/typography]'; ``` ### JavaScript diff --git a/packages/design-tokens/_docs/pages/README.mdx b/packages/design-tokens/_docs/pages/README.mdx index 4d18e4fe2b4..684374ed999 100644 --- a/packages/design-tokens/_docs/pages/README.mdx +++ b/packages/design-tokens/_docs/pages/README.mdx @@ -1,6 +1,6 @@ import { Meta, Markdown } from '@storybook/blocks' import ReadMe from '../../README.md?raw' - + {ReadMe} From d9810c27f9cb826178c55feda235a042e61ba825 Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Wed, 1 Jul 2026 10:39:08 +1000 Subject: [PATCH 13/25] chore(tailwind): move design-tokens back to a runtime dependency Revert @kaizen/design-tokens from a peer dependency to a regular runtime dependency of @kaizen/tailwind, so Tailwind consumers get it transitively and don't need to install it themselves. Update the changeset wording accordingly. Co-Authored-By: Claude Opus 4.8 (1M context) --- .changeset/semantic-colour-tokens.md | 2 +- packages/tailwind/package.json | 5 +++-- pnpm-lock.yaml | 7 ++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.changeset/semantic-colour-tokens.md b/.changeset/semantic-colour-tokens.md index 36e412a2ccd..c4fbf38d258 100644 --- a/.changeset/semantic-colour-tokens.md +++ b/.changeset/semantic-colour-tokens.md @@ -6,4 +6,4 @@ feat: add semantic colour tokens (background, text, foreground, border) and expand the gray primitive ramp with `gray-550` and `gray-700`. Exposes the tokens as CSS variables (inlined into `variables.css`), SCSS, JS exports, and Tailwind preset utilities. -`@kaizen/tailwind` now declares `@kaizen/design-tokens` as a peer dependency: the semantic Tailwind utilities emit `var(--)` references whose definitions live in `@kaizen/design-tokens`, so the two must be upgraded together. A mismatched/old `@kaizen/design-tokens` now surfaces a peer-dependency warning at install instead of silently rendering the wrong colours. +`@kaizen/tailwind` depends on `@kaizen/design-tokens` (a regular runtime dependency, installed transitively): the semantic Tailwind utilities emit `var(--)` references whose definitions live in `@kaizen/design-tokens`. Consumers using the Tailwind preset do not need to install `@kaizen/design-tokens` themselves — they only need to load its CSS variables once at runtime (handled by `KaizenProvider`). diff --git a/packages/tailwind/package.json b/packages/tailwind/package.json index 2d6dc121f3a..f259f55f52d 100644 --- a/packages/tailwind/package.json +++ b/packages/tailwind/package.json @@ -27,9 +27,11 @@ "author": "", "private": false, "license": "MIT", + "dependencies": { + "@kaizen/design-tokens": "workspace:*" + }, "devDependencies": { "@cultureamp/package-bundler": "^4.0.1", - "@kaizen/design-tokens": "workspace:*", "@tailwindcss/container-queries": "^0.1.1", "classnames": "^2.5.1", "react": "^19.2.7", @@ -39,7 +41,6 @@ "tslib": "^2.8.1" }, "peerDependencies": { - "@kaizen/design-tokens": "workspace:^", "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0", "tailwindcss": ">=3.4.7" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4a5626b9996..13637259a29 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -578,13 +578,14 @@ importers: version: 4.22.4 packages/tailwind: + dependencies: + '@kaizen/design-tokens': + specifier: workspace:* + version: link:../design-tokens devDependencies: '@cultureamp/package-bundler': specifier: ^4.0.1 version: 4.0.1(@babel/core@7.29.7)(@types/babel__core@7.20.5)(postcss-preset-env@11.3.0(postcss@8.5.15))(postcss@8.5.15)(rollup@4.61.1)(tslib@2.8.1)(typescript@5.9.3) - '@kaizen/design-tokens': - specifier: workspace:* - version: link:../design-tokens '@tailwindcss/container-queries': specifier: ^0.1.1 version: 0.1.1(tailwindcss@3.4.19(tsx@4.22.4)) From 195262918e7d2fa9cfbf8c5e062044a6b03872ed Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Wed, 1 Jul 2026 10:40:23 +1000 Subject: [PATCH 14/25] removes unnecessary docs --- packages/design-tokens/_docs/pages/api.mdx | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 packages/design-tokens/_docs/pages/api.mdx diff --git a/packages/design-tokens/_docs/pages/api.mdx b/packages/design-tokens/_docs/pages/api.mdx deleted file mode 100644 index 643b34aebf9..00000000000 --- a/packages/design-tokens/_docs/pages/api.mdx +++ /dev/null @@ -1,18 +0,0 @@ -import { Meta } from '@storybook/blocks' -import { ThemesCodeBlocks, SassVariablesCodeBlocks } from '../DocsComponents' - - - -# API - -## Themes - -The following code blocks depict the structure of Kaizen's Theme type, and some of the variables that are available for you. - - - -## SASS Variables - -The following code blocks contain the source files for each SASS variable in design tokens. - - From 75d31662de418b87eb668e0c2579e59451fd1250 Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Wed, 1 Jul 2026 11:29:43 +1000 Subject: [PATCH 15/25] fix(tailwind): strip null semantic tokens from preset; use semantic colours in docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The preset spread `tokens.color` (which now merges flat semantic colour tokens) into `colors` and `borderColor`. Unmapped semantic tokens are `null`, which Tailwind's colour config rejects — breaking `@kaizen/tailwind` build for the whole branch. Add `stripNulls` to drop null-valued entries before spreading. Also update Tailwind guide docs to use the new semantic colour classes: - utility-class-helpers-overview: border-brand / bg-brand-primary / text-brand-secondary - overview: fix gray-400 -> blue-400 typo to match anatomy diagram Co-Authored-By: Claude Opus 4.8 (1M context) --- .../tailwind/src/_docs/pages/overview.mdx | 2 +- .../pages/utility-class-helpers-overview.mdx | 8 +++---- packages/tailwind/src/tailwind-presets.ts | 22 +++++++++++++++++-- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/packages/tailwind/src/_docs/pages/overview.mdx b/packages/tailwind/src/_docs/pages/overview.mdx index 38b9b56edea..3442e3b6d55 100644 --- a/packages/tailwind/src/_docs/pages/overview.mdx +++ b/packages/tailwind/src/_docs/pages/overview.mdx @@ -11,7 +11,7 @@ import AnatomyDiagram from '../assets/tw-anatomy.png' The `@kaizen/tailwind` package is essentially a custom Tailwind preset. For more information about Tailwind presets, see their docs [here](https://tailwindcss.com/docs/presets). This package does not change how Tailwind works; it only defines the suffixes that can be applied when constructing utility classes. To see a list of utilities generated by our preset, see our [Utility Class Reference Docs](/docs/guides-tailwind-utility-class-references-overview--docs). -The following diagram shows the construction of a utility class that adds a background of `blue-400` on hover. The modifier `hover:` and the prefix `bg-` are part of Tailwind by default. The suffix `gray-400` is defined by our preset, and represents one of our color design tokens. +The following diagram shows the construction of a utility class that adds a background of `blue-400` on hover. The modifier `hover:` and the prefix `bg-` are part of Tailwind by default. The suffix `blue-400` is defined by our preset, and represents one of our color design tokens. Tailwind utility class anatomy diff --git a/packages/tailwind/src/_docs/pages/utility-class-helpers-overview.mdx b/packages/tailwind/src/_docs/pages/utility-class-helpers-overview.mdx index 2e6aeba4581..ca8b8793da9 100644 --- a/packages/tailwind/src/_docs/pages/utility-class-helpers-overview.mdx +++ b/packages/tailwind/src/_docs/pages/utility-class-helpers-overview.mdx @@ -56,8 +56,8 @@ A visual representation of the CSS generated by the utility class. You can inspe **Goal:** Add our default border radius (`7px`) to the following component. ```html -
-

Example

+
+

Example

``` @@ -90,7 +90,7 @@ A visual representation of the CSS generated by the utility class. You can inspe ``` ```html -
-

Example

+
+

Example

``` diff --git a/packages/tailwind/src/tailwind-presets.ts b/packages/tailwind/src/tailwind-presets.ts index e6554fa96c7..b34c1cb268d 100644 --- a/packages/tailwind/src/tailwind-presets.ts +++ b/packages/tailwind/src/tailwind-presets.ts @@ -23,6 +23,24 @@ function stripAndMap(group: Record, prefix: string): Reco return result } +/** + * `tokens.color` merges in the flat semantic colour tokens, some of which are + * `null` (no confident mapping yet). Tailwind's colour config rejects `null`, + * so strip those entries before spreading into `colors` / `borderColor`. + */ +function stripNulls>( + group: T +): { [K in keyof T]: Exclude } { + const result: Record = {} + for (const [key, value] of Object.entries(group)) { + if (value === null) continue + result[key] = value + } + return result as { [K in keyof T]: Exclude } +} + +const nonNullColors = stripNulls(tokens.color) + const semanticBackgroundColors = stripAndMap(semanticColorTokens.background, 'bg-') const semanticTextColors = stripAndMap(semanticColorTokens.text, 'text-') const semanticBorderColors = stripAndMap(semanticColorTokens.border, 'border-') @@ -51,7 +69,7 @@ export const kaizenTailwindTheme: KaizenTailwindTheme = { transparent: 'transparent', current: 'currentColor', inherit: 'inherit', - ...tokens.color, + ...nonNullColors, ...tokens.dataViz, }, spacing: kzSpacing, @@ -78,7 +96,7 @@ export const kaizenTailwindTheme: KaizenTailwindTheme = { 'default-color': `${tokens.border.solid.borderColor}`, 'transparent': `${tokens.border.borderless.borderColor}`, 'focus-ring': tokens.color.blue[600], - ...tokens.color, + ...nonNullColors, }, fontFamily: { 'family-paragraph': [`${tokens.typography.paragraphBody.fontFamily}`], From 39c1d68e67055978db79b81db96d0a17eecf64ca Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Wed, 1 Jul 2026 11:35:38 +1000 Subject: [PATCH 16/25] fix(design-tokens): skip null semantic tokens in CSS var generation Unmapped semantic colour tokens are `null` (no confident mapping yet). Both CSS-var generators interpolated them into output, emitting literal `null` values like `--color-bg-primary-alt: null` in variables.css / color.json / color.less / color.scss. Add a null-value guard to both makeCSSVariableTheme (color.json/less/scss) and makeCssVariableDefinitionsMap (variables.css) so null tokens emit nothing. Regenerate the affected token outputs. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/design-tokens/css/variables.css | 58 +---- packages/design-tokens/less/color.less | 204 +++++++++++++++++ packages/design-tokens/sass/color.scss | 204 +++++++++++++++++ .../src/lib/makeCssVariableDefinitionsMap.ts | 3 + .../src/lib/makeCssVariableTheme.ts | 3 + packages/design-tokens/tokens/color.json | 206 +++++++++++++++++- 6 files changed, 621 insertions(+), 57 deletions(-) diff --git a/packages/design-tokens/css/variables.css b/packages/design-tokens/css/variables.css index 2d25f02a79f..f448d41bc95 100644 --- a/packages/design-tokens/css/variables.css +++ b/packages/design-tokens/css/variables.css @@ -1,59 +1,5 @@ /** THIS IS AN AUTOGENERATED FILE **/ - :root{--animation-easing-function-ease-in-out: cubic-bezier(0.455, 0.03, 0.515, 0.955); --animation-easing-function-ease-in: cubic-bezier(0.55, 0.085, 0.68, 0.53); --animation-easing-function-ease-out: cubic-bezier(0.25, 0.46, 0.45, 0.94); --animation-easing-function-linear: linear; --animation-easing-function-bounce-in: cubic-bezier(0.485, 0.155, 0.24, 1.245); --animation-easing-function-bounce-out: cubic-bezier(0.485, 0.155, 0.515, 0.845); --animation-easing-function-bounce-in-out: cubic-bezier(0.76, -0.245, 0.24, 1.245); --animation-duration-instant: 0ms; --animation-duration-immediate: 100ms; --animation-duration-rapid: 200ms; --animation-duration-fast: 300ms; --animation-duration-slow: 400ms; --animation-duration-deliberate: 700ms; --border-solid-border-width: 2px; --border-solid-border-radius: 7px; --border-solid-border-style: solid; --border-solid-border-color: #e1e2ea; --border-solid-border-color-rgb: 225, 226, 234; --border-dashed-border-width: 2px; --border-dashed-border-radius: 7px; --border-dashed-border-style: dashed; --border-borderless-border-width: 2px; --border-borderless-border-radius: 7px; --border-borderless-border-style: solid; --border-borderless-border-color: transparent; --border-borderless-border-color-rgb: 0, 0, 0; --border-focus-ring-border-width: 2px; --border-focus-ring-border-radius: 10px; --border-focus-ring-border-style: solid; --border-width-1: 1px; --color-purple-100: #f4edf8; --color-purple-100-rgb: 244, 237, 248; --color-purple-200: #dfc9ea; --color-purple-200-rgb: 223, 201, 234; --color-purple-300: #c9a5dd; --color-purple-300-rgb: 201, 165, 221; --color-purple-400: #ae67b1; --color-purple-400-rgb: 174, 103, 177; --color-purple-500: #844587; --color-purple-500-rgb: 132, 69, 135; --color-purple-600: #5f3361; --color-purple-600-rgb: 95, 51, 97; --color-purple-700: #4a234d; --color-purple-700-rgb: 74, 35, 77; --color-purple-800: #2f2438; --color-purple-800-rgb: 47, 36, 56; --color-blue-100: #e6f6ff; --color-blue-100-rgb: 230, 246, 255; --color-blue-200: #bde2f5; --color-blue-200-rgb: 189, 226, 245; --color-blue-300: #73c0e8; --color-blue-300-rgb: 115, 192, 232; --color-blue-400: #008bd6; --color-blue-400-rgb: 0, 139, 214; --color-blue-500: #0168b3; --color-blue-500-rgb: 1, 104, 179; --color-blue-600: #004970; --color-blue-600-rgb: 0, 73, 112; --color-blue-700: #003157; --color-blue-700-rgb: 0, 49, 87; --color-green-100: #e8f8f4; --color-green-100-rgb: 232, 248, 244; --color-green-200: #c4ede2; --color-green-200-rgb: 196, 237, 226; --color-green-300: #8fdbc7; --color-green-300-rgb: 143, 219, 199; --color-green-400: #5dcaad; --color-green-400-rgb: 93, 202, 173; --color-green-500: #3f9a86; --color-green-500-rgb: 63, 154, 134; --color-green-600: #2c7d67; --color-green-600-rgb: 44, 125, 103; --color-green-700: #22594a; --color-green-700-rgb: 34, 89, 74; --color-yellow-100: #fff9e4; --color-yellow-100-rgb: 255, 249, 228; --color-yellow-200: #ffeeb3; --color-yellow-200-rgb: 255, 238, 179; --color-yellow-300: #ffe36e; --color-yellow-300-rgb: 255, 227, 110; --color-yellow-400: #ffca4d; --color-yellow-400-rgb: 255, 202, 77; --color-yellow-500: #ffb600; --color-yellow-500-rgb: 255, 182, 0; --color-yellow-600: #c68600; --color-yellow-600-rgb: 198, 134, 0; --color-yellow-700: #876400; --color-yellow-700-rgb: 135, 100, 0; --color-red-100: #fdeaee; --color-red-100-rgb: 253, 234, 238; --color-red-200: #f9c2cb; --color-red-200-rgb: 249, 194, 203; --color-red-300: #f597a8; --color-red-300-rgb: 245, 151, 168; --color-red-400: #e0707d; --color-red-400-rgb: 224, 112, 125; --color-red-500: #c93b55; --color-red-500-rgb: 201, 59, 85; --color-red-600: #a82433; --color-red-600-rgb: 168, 36, 51; --color-red-700: #6c1e20; --color-red-700-rgb: 108, 30, 32; --color-orange-100: #fff0e8; --color-orange-100-rgb: 255, 240, 232; --color-orange-200: #ffd1b9; --color-orange-200-rgb: 255, 209, 185; --color-orange-300: #ffb08a; --color-orange-300-rgb: 255, 176, 138; --color-orange-400: #ff9461; --color-orange-400-rgb: 255, 148, 97; --color-orange-500: #e96c2f; --color-orange-500-rgb: 233, 108, 47; --color-orange-600: #b74302; --color-orange-600-rgb: 183, 67, 2; --color-orange-700: #903c00; --color-orange-700-rgb: 144, 60, 0; --color-gray-100: #f9f9f9; --color-gray-100-rgb: 249, 249, 249; --color-gray-200: #f4f4f5; --color-gray-200-rgb: 244, 244, 245; --color-gray-300: #eaeaec; --color-gray-300-rgb: 234, 234, 236; --color-gray-400: #cdcdd0; --color-gray-400-rgb: 205, 205, 208; --color-gray-500: #878792; --color-gray-500-rgb: 135, 135, 146; --color-gray-550: #6d6674; --color-gray-550-rgb: 109, 102, 116; --color-gray-600: #524e56; --color-gray-600-rgb: 82, 78, 86; --color-gray-700: #3f3c42; --color-gray-700-rgb: 63, 60, 66; --color-white: #ffffff; --color-white-rgb: 255, 255, 255; --color-black: #000000; --color-black-rgb: 0, 0, 0; --data-viz-favorable: #7dd5bd; --data-viz-favorable-rgb: 125, 213, 189; --data-viz-unfavorable: #e68d97; --data-viz-unfavorable-rgb: 230, 141, 151; --layout-content-max-width: 1392px; --layout-content-max-width-with-sidebar: 1080px; --layout-content-side-margin: 72px; --layout-mobile-actions-drawer-height: 60px; --layout-navigation-bar-height: 72px; --layout-breakpoints-medium: 768px; --layout-breakpoints-large: 1080px; --shadow-small-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 3px 16px 0 rgba(0, 0, 0, 0.06); --shadow-large-box-shadow: 0 3px 9px 0 rgba(0, 0, 0, 0.1), 0 8px 40px 0 rgba(0, 0, 0, 0.08); --spacing-0: 0; --spacing-1: .0625rem; --spacing-2: .125rem; --spacing-4: .25rem; --spacing-6: .375rem; --spacing-8: .5rem; --spacing-12: .75rem; --spacing-16: 1rem; --spacing-20: 1.25rem; --spacing-24: 1.5rem; --spacing-32: 2rem; --spacing-40: 2.5rem; --spacing-48: 3rem; --spacing-56: 3.5rem; --spacing-64: 4rem; --spacing-72: 4.5rem; --spacing-80: 5rem; --spacing-96: 6rem; --spacing-112: 7rem; --spacing-128: 8rem; --spacing-160: 10rem; --spacing-200: 12.5rem; --spacing-240: 15rem; --spacing-280: 17.5rem; --spacing-320: 20rem; --spacing-xs: 0.375rem; --spacing-sm: 0.75rem; --spacing-md: 1.5rem; --spacing-lg: 2.25rem; --spacing-xl: 3rem; --spacing-xxl: 3.75rem; --spacing-xxxl: 4.5rem; --spacing-xxxxl: 5.25rem; --spacing-xxxxxl: 6rem; --typography-data-large-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-large-font-weight: 700; --typography-data-large-font-size: 5.25rem; --typography-data-large-line-height: 5.25rem; --typography-data-large-letter-spacing: normal; --typography-data-large-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-large-units-font-weight: 700; --typography-data-large-units-font-size: 2.625rem; --typography-data-large-units-line-height: 5.25rem; --typography-data-large-units-letter-spacing: normal; --typography-data-medium-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-medium-font-weight: 700; --typography-data-medium-font-size: 3rem; --typography-data-medium-line-height: 5rem; --typography-data-medium-letter-spacing: normal; --typography-data-medium-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-medium-units-font-weight: 700; --typography-data-medium-units-font-size: 1.5rem; --typography-data-medium-units-line-height: 5rem; --typography-data-medium-units-letter-spacing: normal; --typography-data-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-small-font-weight: 700; --typography-data-small-font-size: 1.5rem; --typography-data-small-line-height: 1.5rem; --typography-data-small-letter-spacing: normal; --typography-data-small-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-small-units-font-weight: 700; --typography-data-small-units-font-size: 1.125rem; --typography-data-small-units-line-height: 1.5rem; --typography-data-small-units-letter-spacing: normal; --typography-display-0-font-family: "Tiempos Headline", Georgia, serif; --typography-display-0-font-weight: 800; --typography-display-0-font-size: 4.5rem; --typography-display-0-line-height: 5.25rem; --typography-display-0-letter-spacing: 0em; --typography-heading-1-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-1-font-weight: 500; --typography-heading-1-font-size: 2.125rem; --typography-heading-1-line-height: 2.625rem; --typography-heading-1-letter-spacing: normal; --typography-heading-2-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-2-font-weight: 600; --typography-heading-2-font-size: 1.75rem; --typography-heading-2-line-height: 2.25rem; --typography-heading-2-letter-spacing: normal; --typography-heading-3-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-3-font-weight: 600; --typography-heading-3-font-size: 1.375rem; --typography-heading-3-line-height: 1.875rem; --typography-heading-3-letter-spacing: normal; --typography-heading-4-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-4-font-weight: 600; --typography-heading-4-font-size: 1.125rem; --typography-heading-4-line-height: 1.5rem; --typography-heading-4-letter-spacing: normal; --typography-heading-5-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-5-font-weight: 600; --typography-heading-5-font-size: 1rem; --typography-heading-5-line-height: 1.5rem; --typography-heading-5-letter-spacing: normal; --typography-heading-6-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-6-font-weight: 600; --typography-heading-6-font-size: 0.875rem; --typography-heading-6-line-height: 1.5rem; --typography-heading-6-letter-spacing: normal; --typography-paragraph-intro-lede-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-intro-lede-font-weight: 400; --typography-paragraph-intro-lede-font-size: 1.25rem; --typography-paragraph-intro-lede-line-height: 1.875rem; --typography-paragraph-intro-lede-letter-spacing: 0; --typography-paragraph-intro-lede-max-width: 975px; --typography-paragraph-body-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-body-font-weight: 400; --typography-paragraph-body-font-size: 1rem; --typography-paragraph-body-line-height: 1.5rem; --typography-paragraph-body-letter-spacing: normal; --typography-paragraph-body-max-width: 780px; --typography-paragraph-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-small-font-weight: 400; --typography-paragraph-small-font-size: 0.875rem; --typography-paragraph-small-line-height: 1.125rem; --typography-paragraph-small-letter-spacing: normal; --typography-paragraph-small-max-width: 680px; --typography-paragraph-extra-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-extra-small-font-weight: 400; --typography-paragraph-extra-small-font-size: 0.75rem; --typography-paragraph-extra-small-line-height: 1.125rem; --typography-paragraph-extra-small-letter-spacing: normal; --typography-paragraph-extra-small-max-width: 600px; --typography-paragraph-bold-font-weight: 600; --typography-button-primary-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-button-primary-font-weight: 500; --typography-button-primary-font-size: 1.125rem; --typography-button-primary-line-height: 1.5rem; --typography-button-primary-letter-spacing: normal; --typography-button-secondary-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-button-secondary-font-weight: 500; --typography-button-secondary-font-size: 1rem; --typography-button-secondary-line-height: 1.5rem; --typography-button-secondary-letter-spacing: normal;} - -/* --- Semantic colour tokens (autogenerated) --- */ -:root { - --bg-primary: var(--color-white); - --bg-secondary: var(--color-gray-200); - --bg-secondary_hover: var(--color-gray-200); - --bg-tertiary: var(--color-gray-300); - --bg-primary-solid: var(--color-purple-800); - --bg-secondary-solid: var(--color-gray-600); - --bg-overlay: var(--color-white); - --bg-brand-primary: var(--color-blue-100); - --bg-brand-secondary: var(--color-blue-200); - --bg-brand-solid: var(--color-blue-500); - --bg-brand-solid_hover: var(--color-blue-700); - --bg-error-primary: var(--color-red-100); - --bg-error-secondary: var(--color-red-300); - --bg-error-solid: var(--color-red-400); - --bg-success-primary: var(--color-green-100); - --bg-success-secondary: var(--color-green-300); - --bg-success-solid: var(--color-green-600); - --bg-warning-primary: var(--color-yellow-100); - --bg-warning-secondary: var(--color-yellow-400); - --bg-warning-solid: var(--color-yellow-400); - --text-primary: var(--color-purple-800); - --text-secondary: var(--color-gray-700); - --text-tertiary: var(--color-gray-600); - --text-quaternary: var(--color-gray-550); - --text-placeholder: var(--color-gray-550); - --text-secondary_on-brand: var(--color-white); - --text-quaternary_on-brand: var(--color-white); - --text-brand-primary: var(--color-blue-500); - --text-brand-secondary: var(--color-blue-700); - --text-brand-secondary_hover: var(--color-blue-600); - --text-error-primary: var(--color-red-600); - --text-success-primary: var(--color-green-600); - --fg-primary: var(--color-purple-800); - --fg-secondary: var(--color-purple-800); - --fg-secondary_hover: var(--color-purple-800); - --fg-tertiary: var(--color-gray-500); - --fg-quaternary: var(--color-purple-800); - --fg-white: var(--color-white); - --fg-brand-primary: var(--color-blue-500); - --fg-error-primary: var(--color-red-500); - --fg-success-primary: var(--color-green-500); - --fg-success-secondary: var(--color-green-400); - --fg-warning-primary: var(--color-yellow-700); - --border-primary: var(--color-gray-600); - --border-secondary: var(--color-gray-500); - --border-secondary_alt: var(--color-gray-200); - --border-tertiary: var(--color-gray-300); - --border-brand: var(--color-blue-500); - --border-brand_alt: var(--color-blue-300); - --border-error: var(--color-red-500); - --border-error_subtle: var(--color-red-300); -} + :root{--animation-easing-function-ease-in-out: cubic-bezier(0.455, 0.03, 0.515, 0.955); --animation-easing-function-ease-in: cubic-bezier(0.55, 0.085, 0.68, 0.53); --animation-easing-function-ease-out: cubic-bezier(0.25, 0.46, 0.45, 0.94); --animation-easing-function-linear: linear; --animation-easing-function-bounce-in: cubic-bezier(0.485, 0.155, 0.24, 1.245); --animation-easing-function-bounce-out: cubic-bezier(0.485, 0.155, 0.515, 0.845); --animation-easing-function-bounce-in-out: cubic-bezier(0.76, -0.245, 0.24, 1.245); --animation-duration-instant: 0ms; --animation-duration-immediate: 100ms; --animation-duration-rapid: 200ms; --animation-duration-fast: 300ms; --animation-duration-slow: 400ms; --animation-duration-deliberate: 700ms; --border-solid-border-width: 2px; --border-solid-border-radius: 7px; --border-solid-border-style: solid; --border-solid-border-color: #e1e2ea; --border-solid-border-color-rgb: 225, 226, 234; --border-dashed-border-width: 2px; --border-dashed-border-radius: 7px; --border-dashed-border-style: dashed; --border-borderless-border-width: 2px; --border-borderless-border-radius: 7px; --border-borderless-border-style: solid; --border-borderless-border-color: transparent; --border-borderless-border-color-rgb: 0, 0, 0; --border-focus-ring-border-width: 2px; --border-focus-ring-border-radius: 10px; --border-focus-ring-border-style: solid; --border-width-1: 1px; --color-purple-100: #f4edf8; --color-purple-100-rgb: 244, 237, 248; --color-purple-200: #dfc9ea; --color-purple-200-rgb: 223, 201, 234; --color-purple-300: #c9a5dd; --color-purple-300-rgb: 201, 165, 221; --color-purple-400: #ae67b1; --color-purple-400-rgb: 174, 103, 177; --color-purple-500: #844587; --color-purple-500-rgb: 132, 69, 135; --color-purple-600: #5f3361; --color-purple-600-rgb: 95, 51, 97; --color-purple-700: #4a234d; --color-purple-700-rgb: 74, 35, 77; --color-purple-800: #2f2438; --color-purple-800-rgb: 47, 36, 56; --color-blue-100: #e6f6ff; --color-blue-100-rgb: 230, 246, 255; --color-blue-200: #bde2f5; --color-blue-200-rgb: 189, 226, 245; --color-blue-300: #73c0e8; --color-blue-300-rgb: 115, 192, 232; --color-blue-400: #008bd6; --color-blue-400-rgb: 0, 139, 214; --color-blue-500: #0168b3; --color-blue-500-rgb: 1, 104, 179; --color-blue-600: #004970; --color-blue-600-rgb: 0, 73, 112; --color-blue-700: #003157; --color-blue-700-rgb: 0, 49, 87; --color-green-100: #e8f8f4; --color-green-100-rgb: 232, 248, 244; --color-green-200: #c4ede2; --color-green-200-rgb: 196, 237, 226; --color-green-300: #8fdbc7; --color-green-300-rgb: 143, 219, 199; --color-green-400: #5dcaad; --color-green-400-rgb: 93, 202, 173; --color-green-500: #3f9a86; --color-green-500-rgb: 63, 154, 134; --color-green-600: #2c7d67; --color-green-600-rgb: 44, 125, 103; --color-green-700: #22594a; --color-green-700-rgb: 34, 89, 74; --color-yellow-100: #fff9e4; --color-yellow-100-rgb: 255, 249, 228; --color-yellow-200: #ffeeb3; --color-yellow-200-rgb: 255, 238, 179; --color-yellow-300: #ffe36e; --color-yellow-300-rgb: 255, 227, 110; --color-yellow-400: #ffca4d; --color-yellow-400-rgb: 255, 202, 77; --color-yellow-500: #ffb600; --color-yellow-500-rgb: 255, 182, 0; --color-yellow-600: #c68600; --color-yellow-600-rgb: 198, 134, 0; --color-yellow-700: #876400; --color-yellow-700-rgb: 135, 100, 0; --color-red-100: #fdeaee; --color-red-100-rgb: 253, 234, 238; --color-red-200: #f9c2cb; --color-red-200-rgb: 249, 194, 203; --color-red-300: #f597a8; --color-red-300-rgb: 245, 151, 168; --color-red-400: #e0707d; --color-red-400-rgb: 224, 112, 125; --color-red-500: #c93b55; --color-red-500-rgb: 201, 59, 85; --color-red-600: #a82433; --color-red-600-rgb: 168, 36, 51; --color-red-700: #6c1e20; --color-red-700-rgb: 108, 30, 32; --color-orange-100: #fff0e8; --color-orange-100-rgb: 255, 240, 232; --color-orange-200: #ffd1b9; --color-orange-200-rgb: 255, 209, 185; --color-orange-300: #ffb08a; --color-orange-300-rgb: 255, 176, 138; --color-orange-400: #ff9461; --color-orange-400-rgb: 255, 148, 97; --color-orange-500: #e96c2f; --color-orange-500-rgb: 233, 108, 47; --color-orange-600: #b74302; --color-orange-600-rgb: 183, 67, 2; --color-orange-700: #903c00; --color-orange-700-rgb: 144, 60, 0; --color-gray-100: #f9f9f9; --color-gray-100-rgb: 249, 249, 249; --color-gray-200: #f4f4f5; --color-gray-200-rgb: 244, 244, 245; --color-gray-300: #eaeaec; --color-gray-300-rgb: 234, 234, 236; --color-gray-400: #cdcdd0; --color-gray-400-rgb: 205, 205, 208; --color-gray-500: #878792; --color-gray-500-rgb: 135, 135, 146; --color-gray-550: #6d6674; --color-gray-550-rgb: 109, 102, 116; --color-gray-600: #524e56; --color-gray-600-rgb: 82, 78, 86; --color-gray-700: #3f3c42; --color-gray-700-rgb: 63, 60, 66; --color-white: #ffffff; --color-white-rgb: 255, 255, 255; --color-black: #000000; --color-black-rgb: 0, 0, 0; --color-bg-primary: var(--color-white); --color-bg-secondary: var(--color-gray-200); --color-bg-secondary-hover: var(--color-gray-200); --color-bg-tertiary: var(--color-gray-300); --color-bg-primary-solid: var(--color-purple-800); --color-bg-secondary-solid: var(--color-gray-600); --color-bg-overlay: var(--color-white); --color-bg-brand-primary: var(--color-blue-100); --color-bg-brand-secondary: var(--color-blue-200); --color-bg-brand-solid: var(--color-blue-500); --color-bg-brand-solid-hover: var(--color-blue-700); --color-bg-error-primary: var(--color-red-100); --color-bg-error-secondary: var(--color-red-300); --color-bg-error-solid: var(--color-red-400); --color-bg-success-primary: var(--color-green-100); --color-bg-success-secondary: var(--color-green-300); --color-bg-success-solid: var(--color-green-600); --color-bg-warning-primary: var(--color-yellow-100); --color-bg-warning-secondary: var(--color-yellow-400); --color-bg-warning-solid: var(--color-yellow-400); --color-text-primary: var(--color-purple-800); --color-text-secondary: var(--color-gray-700); --color-text-tertiary: var(--color-gray-600); --color-text-quaternary: var(--color-gray-550); --color-text-placeholder: var(--color-gray-550); --color-text-secondary-on-brand: var(--color-white); --color-text-quaternary-on-brand: var(--color-white); --color-text-brand-primary: var(--color-blue-500); --color-text-brand-secondary: var(--color-blue-700); --color-text-brand-secondary-hover: var(--color-blue-600); --color-text-error-primary: var(--color-red-600); --color-text-success-primary: var(--color-green-600); --color-fg-primary: var(--color-purple-800); --color-fg-secondary: var(--color-purple-800); --color-fg-secondary-hover: var(--color-purple-800); --color-fg-tertiary: var(--color-gray-500); --color-fg-quaternary: var(--color-purple-800); --color-fg-white: var(--color-white); --color-fg-brand-primary: var(--color-blue-500); --color-fg-error-primary: var(--color-red-500); --color-fg-success-primary: var(--color-green-500); --color-fg-success-secondary: var(--color-green-400); --color-fg-warning-primary: var(--color-yellow-700); --color-border-primary: var(--color-gray-600); --color-border-secondary: var(--color-gray-500); --color-border-secondary-alt: var(--color-gray-200); --color-border-tertiary: var(--color-gray-300); --color-border-brand: var(--color-blue-500); --color-border-brand-alt: var(--color-blue-300); --color-border-error: var(--color-red-500); --color-border-error-subtle: var(--color-red-300); --data-viz-favorable: #7dd5bd; --data-viz-favorable-rgb: 125, 213, 189; --data-viz-unfavorable: #e68d97; --data-viz-unfavorable-rgb: 230, 141, 151; --layout-content-max-width: 1392px; --layout-content-max-width-with-sidebar: 1080px; --layout-content-side-margin: 72px; --layout-mobile-actions-drawer-height: 60px; --layout-navigation-bar-height: 72px; --layout-breakpoints-medium: 768px; --layout-breakpoints-large: 1080px; --shadow-small-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 3px 16px 0 rgba(0, 0, 0, 0.06); --shadow-large-box-shadow: 0 3px 9px 0 rgba(0, 0, 0, 0.1), 0 8px 40px 0 rgba(0, 0, 0, 0.08); --spacing-0: 0; --spacing-1: .0625rem; --spacing-2: .125rem; --spacing-4: .25rem; --spacing-6: .375rem; --spacing-8: .5rem; --spacing-12: .75rem; --spacing-16: 1rem; --spacing-20: 1.25rem; --spacing-24: 1.5rem; --spacing-32: 2rem; --spacing-40: 2.5rem; --spacing-48: 3rem; --spacing-56: 3.5rem; --spacing-64: 4rem; --spacing-72: 4.5rem; --spacing-80: 5rem; --spacing-96: 6rem; --spacing-112: 7rem; --spacing-128: 8rem; --spacing-160: 10rem; --spacing-200: 12.5rem; --spacing-240: 15rem; --spacing-280: 17.5rem; --spacing-320: 20rem; --spacing-xs: 0.375rem; --spacing-sm: 0.75rem; --spacing-md: 1.5rem; --spacing-lg: 2.25rem; --spacing-xl: 3rem; --spacing-xxl: 3.75rem; --spacing-xxxl: 4.5rem; --spacing-xxxxl: 5.25rem; --spacing-xxxxxl: 6rem; --typography-data-large-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-large-font-weight: 700; --typography-data-large-font-size: 5.25rem; --typography-data-large-line-height: 5.25rem; --typography-data-large-letter-spacing: normal; --typography-data-large-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-large-units-font-weight: 700; --typography-data-large-units-font-size: 2.625rem; --typography-data-large-units-line-height: 5.25rem; --typography-data-large-units-letter-spacing: normal; --typography-data-medium-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-medium-font-weight: 700; --typography-data-medium-font-size: 3rem; --typography-data-medium-line-height: 5rem; --typography-data-medium-letter-spacing: normal; --typography-data-medium-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-medium-units-font-weight: 700; --typography-data-medium-units-font-size: 1.5rem; --typography-data-medium-units-line-height: 5rem; --typography-data-medium-units-letter-spacing: normal; --typography-data-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-small-font-weight: 700; --typography-data-small-font-size: 1.5rem; --typography-data-small-line-height: 1.5rem; --typography-data-small-letter-spacing: normal; --typography-data-small-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-small-units-font-weight: 700; --typography-data-small-units-font-size: 1.125rem; --typography-data-small-units-line-height: 1.5rem; --typography-data-small-units-letter-spacing: normal; --typography-display-0-font-family: "Tiempos Headline", Georgia, serif; --typography-display-0-font-weight: 800; --typography-display-0-font-size: 4.5rem; --typography-display-0-line-height: 5.25rem; --typography-display-0-letter-spacing: 0em; --typography-heading-1-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-1-font-weight: 500; --typography-heading-1-font-size: 2.125rem; --typography-heading-1-line-height: 2.625rem; --typography-heading-1-letter-spacing: normal; --typography-heading-2-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-2-font-weight: 600; --typography-heading-2-font-size: 1.75rem; --typography-heading-2-line-height: 2.25rem; --typography-heading-2-letter-spacing: normal; --typography-heading-3-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-3-font-weight: 600; --typography-heading-3-font-size: 1.375rem; --typography-heading-3-line-height: 1.875rem; --typography-heading-3-letter-spacing: normal; --typography-heading-4-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-4-font-weight: 600; --typography-heading-4-font-size: 1.125rem; --typography-heading-4-line-height: 1.5rem; --typography-heading-4-letter-spacing: normal; --typography-heading-5-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-5-font-weight: 600; --typography-heading-5-font-size: 1rem; --typography-heading-5-line-height: 1.5rem; --typography-heading-5-letter-spacing: normal; --typography-heading-6-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-6-font-weight: 600; --typography-heading-6-font-size: 0.875rem; --typography-heading-6-line-height: 1.5rem; --typography-heading-6-letter-spacing: normal; --typography-paragraph-intro-lede-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-intro-lede-font-weight: 400; --typography-paragraph-intro-lede-font-size: 1.25rem; --typography-paragraph-intro-lede-line-height: 1.875rem; --typography-paragraph-intro-lede-letter-spacing: 0; --typography-paragraph-intro-lede-max-width: 975px; --typography-paragraph-body-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-body-font-weight: 400; --typography-paragraph-body-font-size: 1rem; --typography-paragraph-body-line-height: 1.5rem; --typography-paragraph-body-letter-spacing: normal; --typography-paragraph-body-max-width: 780px; --typography-paragraph-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-small-font-weight: 400; --typography-paragraph-small-font-size: 0.875rem; --typography-paragraph-small-line-height: 1.125rem; --typography-paragraph-small-letter-spacing: normal; --typography-paragraph-small-max-width: 680px; --typography-paragraph-extra-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-extra-small-font-weight: 400; --typography-paragraph-extra-small-font-size: 0.75rem; --typography-paragraph-extra-small-line-height: 1.125rem; --typography-paragraph-extra-small-letter-spacing: normal; --typography-paragraph-extra-small-max-width: 600px; --typography-paragraph-bold-font-weight: 600; --typography-button-primary-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-button-primary-font-weight: 500; --typography-button-primary-font-size: 1.125rem; --typography-button-primary-line-height: 1.5rem; --typography-button-primary-letter-spacing: normal; --typography-button-secondary-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-button-secondary-font-weight: 500; --typography-button-secondary-font-size: 1rem; --typography-button-secondary-line-height: 1.5rem; --typography-button-secondary-letter-spacing: normal;} + \ No newline at end of file diff --git a/packages/design-tokens/less/color.less b/packages/design-tokens/less/color.less index 0137b56c626..0a0a1c52809 100644 --- a/packages/design-tokens/less/color.less +++ b/packages/design-tokens/less/color.less @@ -220,3 +220,207 @@ @color-black-rgb: var(--color-black-rgb, 0, 0, 0); @color-black-rgb-id: --color-black-rgb; @color-black-id: --color-black; +@color-bg-primary: var(--color-bg-primary, var(--color-white)); +@color-bg-primary-id: --color-bg-primary; +@color-bg-secondary: var(--color-bg-secondary, var(--color-gray-200)); +@color-bg-secondary-id: --color-bg-secondary; +@color-bg-secondary-hover: var(--color-bg-secondary-hover, var(--color-gray-200)); +@color-bg-secondary-hover-id: --color-bg-secondary-hover; +@color-bg-tertiary: var(--color-bg-tertiary, var(--color-gray-300)); +@color-bg-tertiary-id: --color-bg-tertiary; +@color-bg-primary-solid: var(--color-bg-primary-solid, var(--color-purple-800)); +@color-bg-primary-solid-id: --color-bg-primary-solid; +@color-bg-secondary-solid: var(--color-bg-secondary-solid, var(--color-gray-600)); +@color-bg-secondary-solid-id: --color-bg-secondary-solid; +@color-bg-overlay: var(--color-bg-overlay, var(--color-white)); +@color-bg-overlay-id: --color-bg-overlay; +@color-bg-brand-primary: var(--color-bg-brand-primary, var(--color-blue-100)); +@color-bg-brand-primary-id: --color-bg-brand-primary; +@color-bg-brand-secondary: var(--color-bg-brand-secondary, var(--color-blue-200)); +@color-bg-brand-secondary-id: --color-bg-brand-secondary; +@color-bg-brand-solid: var(--color-bg-brand-solid, var(--color-blue-500)); +@color-bg-brand-solid-id: --color-bg-brand-solid; +@color-bg-brand-solid-hover: var(--color-bg-brand-solid-hover, var(--color-blue-700)); +@color-bg-brand-solid-hover-id: --color-bg-brand-solid-hover; +@color-bg-error-primary: var(--color-bg-error-primary, var(--color-red-100)); +@color-bg-error-primary-id: --color-bg-error-primary; +@color-bg-error-secondary: var(--color-bg-error-secondary, var(--color-red-300)); +@color-bg-error-secondary-id: --color-bg-error-secondary; +@color-bg-error-solid: var(--color-bg-error-solid, var(--color-red-400)); +@color-bg-error-solid-id: --color-bg-error-solid; +@color-bg-success-primary: var(--color-bg-success-primary, var(--color-green-100)); +@color-bg-success-primary-id: --color-bg-success-primary; +@color-bg-success-secondary: var(--color-bg-success-secondary, var(--color-green-300)); +@color-bg-success-secondary-id: --color-bg-success-secondary; +@color-bg-success-solid: var(--color-bg-success-solid, var(--color-green-600)); +@color-bg-success-solid-id: --color-bg-success-solid; +@color-bg-warning-primary: var(--color-bg-warning-primary, var(--color-yellow-100)); +@color-bg-warning-primary-id: --color-bg-warning-primary; +@color-bg-warning-secondary: var(--color-bg-warning-secondary, var(--color-yellow-400)); +@color-bg-warning-secondary-id: --color-bg-warning-secondary; +@color-bg-warning-solid: var(--color-bg-warning-solid, var(--color-yellow-400)); +@color-bg-warning-solid-id: --color-bg-warning-solid; +@color-text-primary: var(--color-text-primary, var(--color-purple-800)); +@color-text-primary-id: --color-text-primary; +@color-text-secondary: var(--color-text-secondary, var(--color-gray-700)); +@color-text-secondary-id: --color-text-secondary; +@color-text-tertiary: var(--color-text-tertiary, var(--color-gray-600)); +@color-text-tertiary-id: --color-text-tertiary; +@color-text-quaternary: var(--color-text-quaternary, var(--color-gray-550)); +@color-text-quaternary-id: --color-text-quaternary; +@color-text-placeholder: var(--color-text-placeholder, var(--color-gray-550)); +@color-text-placeholder-id: --color-text-placeholder; +@color-text-secondary-on-brand: var(--color-text-secondary-on-brand, var(--color-white)); +@color-text-secondary-on-brand-id: --color-text-secondary-on-brand; +@color-text-quaternary-on-brand: var(--color-text-quaternary-on-brand, var(--color-white)); +@color-text-quaternary-on-brand-id: --color-text-quaternary-on-brand; +@color-text-brand-primary: var(--color-text-brand-primary, var(--color-blue-500)); +@color-text-brand-primary-id: --color-text-brand-primary; +@color-text-brand-secondary: var(--color-text-brand-secondary, var(--color-blue-700)); +@color-text-brand-secondary-id: --color-text-brand-secondary; +@color-text-brand-secondary-hover: var(--color-text-brand-secondary-hover, var(--color-blue-600)); +@color-text-brand-secondary-hover-id: --color-text-brand-secondary-hover; +@color-text-error-primary: var(--color-text-error-primary, var(--color-red-600)); +@color-text-error-primary-id: --color-text-error-primary; +@color-text-success-primary: var(--color-text-success-primary, var(--color-green-600)); +@color-text-success-primary-id: --color-text-success-primary; +@color-fg-primary: var(--color-fg-primary, var(--color-purple-800)); +@color-fg-primary-id: --color-fg-primary; +@color-fg-secondary: var(--color-fg-secondary, var(--color-purple-800)); +@color-fg-secondary-id: --color-fg-secondary; +@color-fg-secondary-hover: var(--color-fg-secondary-hover, var(--color-purple-800)); +@color-fg-secondary-hover-id: --color-fg-secondary-hover; +@color-fg-tertiary: var(--color-fg-tertiary, var(--color-gray-500)); +@color-fg-tertiary-id: --color-fg-tertiary; +@color-fg-quaternary: var(--color-fg-quaternary, var(--color-purple-800)); +@color-fg-quaternary-id: --color-fg-quaternary; +@color-fg-white: var(--color-fg-white, var(--color-white)); +@color-fg-white-id: --color-fg-white; +@color-fg-brand-primary: var(--color-fg-brand-primary, var(--color-blue-500)); +@color-fg-brand-primary-id: --color-fg-brand-primary; +@color-fg-error-primary: var(--color-fg-error-primary, var(--color-red-500)); +@color-fg-error-primary-id: --color-fg-error-primary; +@color-fg-success-primary: var(--color-fg-success-primary, var(--color-green-500)); +@color-fg-success-primary-id: --color-fg-success-primary; +@color-fg-success-secondary: var(--color-fg-success-secondary, var(--color-green-400)); +@color-fg-success-secondary-id: --color-fg-success-secondary; +@color-fg-warning-primary: var(--color-fg-warning-primary, var(--color-yellow-700)); +@color-fg-warning-primary-id: --color-fg-warning-primary; +@color-border-primary: var(--color-border-primary, var(--color-gray-600)); +@color-border-primary-id: --color-border-primary; +@color-border-secondary: var(--color-border-secondary, var(--color-gray-500)); +@color-border-secondary-id: --color-border-secondary; +@color-border-secondary-alt: var(--color-border-secondary-alt, var(--color-gray-200)); +@color-border-secondary-alt-id: --color-border-secondary-alt; +@color-border-tertiary: var(--color-border-tertiary, var(--color-gray-300)); +@color-border-tertiary-id: --color-border-tertiary; +@color-border-brand: var(--color-border-brand, var(--color-blue-500)); +@color-border-brand-id: --color-border-brand; +@color-border-brand-alt: var(--color-border-brand-alt, var(--color-blue-300)); +@color-border-brand-alt-id: --color-border-brand-alt; +@color-border-error: var(--color-border-error, var(--color-red-500)); +@color-border-error-id: --color-border-error; +@color-border-error-subtle: var(--color-border-error-subtle, var(--color-red-300)); +@color-border-error-subtle-id: --color-border-error-subtle; +@color-bg-primary: var(--color-bg-primary, var(--color-white)); +@color-bg-primary-id: --color-bg-primary; +@color-bg-secondary: var(--color-bg-secondary, var(--color-gray-200)); +@color-bg-secondary-id: --color-bg-secondary; +@color-bg-secondary-hover: var(--color-bg-secondary-hover, var(--color-gray-200)); +@color-bg-secondary-hover-id: --color-bg-secondary-hover; +@color-bg-tertiary: var(--color-bg-tertiary, var(--color-gray-300)); +@color-bg-tertiary-id: --color-bg-tertiary; +@color-bg-primary-solid: var(--color-bg-primary-solid, var(--color-purple-800)); +@color-bg-primary-solid-id: --color-bg-primary-solid; +@color-bg-secondary-solid: var(--color-bg-secondary-solid, var(--color-gray-600)); +@color-bg-secondary-solid-id: --color-bg-secondary-solid; +@color-bg-overlay: var(--color-bg-overlay, var(--color-white)); +@color-bg-overlay-id: --color-bg-overlay; +@color-bg-brand-primary: var(--color-bg-brand-primary, var(--color-blue-100)); +@color-bg-brand-primary-id: --color-bg-brand-primary; +@color-bg-brand-secondary: var(--color-bg-brand-secondary, var(--color-blue-200)); +@color-bg-brand-secondary-id: --color-bg-brand-secondary; +@color-bg-brand-solid: var(--color-bg-brand-solid, var(--color-blue-500)); +@color-bg-brand-solid-id: --color-bg-brand-solid; +@color-bg-brand-solid-hover: var(--color-bg-brand-solid-hover, var(--color-blue-700)); +@color-bg-brand-solid-hover-id: --color-bg-brand-solid-hover; +@color-bg-error-primary: var(--color-bg-error-primary, var(--color-red-100)); +@color-bg-error-primary-id: --color-bg-error-primary; +@color-bg-error-secondary: var(--color-bg-error-secondary, var(--color-red-300)); +@color-bg-error-secondary-id: --color-bg-error-secondary; +@color-bg-error-solid: var(--color-bg-error-solid, var(--color-red-400)); +@color-bg-error-solid-id: --color-bg-error-solid; +@color-bg-success-primary: var(--color-bg-success-primary, var(--color-green-100)); +@color-bg-success-primary-id: --color-bg-success-primary; +@color-bg-success-secondary: var(--color-bg-success-secondary, var(--color-green-300)); +@color-bg-success-secondary-id: --color-bg-success-secondary; +@color-bg-success-solid: var(--color-bg-success-solid, var(--color-green-600)); +@color-bg-success-solid-id: --color-bg-success-solid; +@color-bg-warning-primary: var(--color-bg-warning-primary, var(--color-yellow-100)); +@color-bg-warning-primary-id: --color-bg-warning-primary; +@color-bg-warning-secondary: var(--color-bg-warning-secondary, var(--color-yellow-400)); +@color-bg-warning-secondary-id: --color-bg-warning-secondary; +@color-bg-warning-solid: var(--color-bg-warning-solid, var(--color-yellow-400)); +@color-bg-warning-solid-id: --color-bg-warning-solid; +@color-text-primary: var(--color-text-primary, var(--color-purple-800)); +@color-text-primary-id: --color-text-primary; +@color-text-secondary: var(--color-text-secondary, var(--color-gray-700)); +@color-text-secondary-id: --color-text-secondary; +@color-text-tertiary: var(--color-text-tertiary, var(--color-gray-600)); +@color-text-tertiary-id: --color-text-tertiary; +@color-text-quaternary: var(--color-text-quaternary, var(--color-gray-550)); +@color-text-quaternary-id: --color-text-quaternary; +@color-text-placeholder: var(--color-text-placeholder, var(--color-gray-550)); +@color-text-placeholder-id: --color-text-placeholder; +@color-text-secondary-on-brand: var(--color-text-secondary-on-brand, var(--color-white)); +@color-text-secondary-on-brand-id: --color-text-secondary-on-brand; +@color-text-quaternary-on-brand: var(--color-text-quaternary-on-brand, var(--color-white)); +@color-text-quaternary-on-brand-id: --color-text-quaternary-on-brand; +@color-text-brand-primary: var(--color-text-brand-primary, var(--color-blue-500)); +@color-text-brand-primary-id: --color-text-brand-primary; +@color-text-brand-secondary: var(--color-text-brand-secondary, var(--color-blue-700)); +@color-text-brand-secondary-id: --color-text-brand-secondary; +@color-text-brand-secondary-hover: var(--color-text-brand-secondary-hover, var(--color-blue-600)); +@color-text-brand-secondary-hover-id: --color-text-brand-secondary-hover; +@color-text-error-primary: var(--color-text-error-primary, var(--color-red-600)); +@color-text-error-primary-id: --color-text-error-primary; +@color-text-success-primary: var(--color-text-success-primary, var(--color-green-600)); +@color-text-success-primary-id: --color-text-success-primary; +@color-fg-primary: var(--color-fg-primary, var(--color-purple-800)); +@color-fg-primary-id: --color-fg-primary; +@color-fg-secondary: var(--color-fg-secondary, var(--color-purple-800)); +@color-fg-secondary-id: --color-fg-secondary; +@color-fg-secondary-hover: var(--color-fg-secondary-hover, var(--color-purple-800)); +@color-fg-secondary-hover-id: --color-fg-secondary-hover; +@color-fg-tertiary: var(--color-fg-tertiary, var(--color-gray-500)); +@color-fg-tertiary-id: --color-fg-tertiary; +@color-fg-quaternary: var(--color-fg-quaternary, var(--color-purple-800)); +@color-fg-quaternary-id: --color-fg-quaternary; +@color-fg-white: var(--color-fg-white, var(--color-white)); +@color-fg-white-id: --color-fg-white; +@color-fg-brand-primary: var(--color-fg-brand-primary, var(--color-blue-500)); +@color-fg-brand-primary-id: --color-fg-brand-primary; +@color-fg-error-primary: var(--color-fg-error-primary, var(--color-red-500)); +@color-fg-error-primary-id: --color-fg-error-primary; +@color-fg-success-primary: var(--color-fg-success-primary, var(--color-green-500)); +@color-fg-success-primary-id: --color-fg-success-primary; +@color-fg-success-secondary: var(--color-fg-success-secondary, var(--color-green-400)); +@color-fg-success-secondary-id: --color-fg-success-secondary; +@color-fg-warning-primary: var(--color-fg-warning-primary, var(--color-yellow-700)); +@color-fg-warning-primary-id: --color-fg-warning-primary; +@color-border-primary: var(--color-border-primary, var(--color-gray-600)); +@color-border-primary-id: --color-border-primary; +@color-border-secondary: var(--color-border-secondary, var(--color-gray-500)); +@color-border-secondary-id: --color-border-secondary; +@color-border-secondary-alt: var(--color-border-secondary-alt, var(--color-gray-200)); +@color-border-secondary-alt-id: --color-border-secondary-alt; +@color-border-tertiary: var(--color-border-tertiary, var(--color-gray-300)); +@color-border-tertiary-id: --color-border-tertiary; +@color-border-brand: var(--color-border-brand, var(--color-blue-500)); +@color-border-brand-id: --color-border-brand; +@color-border-brand-alt: var(--color-border-brand-alt, var(--color-blue-300)); +@color-border-brand-alt-id: --color-border-brand-alt; +@color-border-error: var(--color-border-error, var(--color-red-500)); +@color-border-error-id: --color-border-error; +@color-border-error-subtle: var(--color-border-error-subtle, var(--color-red-300)); +@color-border-error-subtle-id: --color-border-error-subtle; diff --git a/packages/design-tokens/sass/color.scss b/packages/design-tokens/sass/color.scss index 1ca178cdeba..91c08ce32b5 100644 --- a/packages/design-tokens/sass/color.scss +++ b/packages/design-tokens/sass/color.scss @@ -220,3 +220,207 @@ $color-black: var(--color-black, #000000); $color-black-rgb: var(--color-black-rgb, 0, 0, 0); $color-black-rgb-id: --color-black-rgb; $color-black-id: --color-black; +$color-bg-primary: var(--color-bg-primary, var(--color-white)); +$color-bg-primary-id: --color-bg-primary; +$color-bg-secondary: var(--color-bg-secondary, var(--color-gray-200)); +$color-bg-secondary-id: --color-bg-secondary; +$color-bg-secondary-hover: var(--color-bg-secondary-hover, var(--color-gray-200)); +$color-bg-secondary-hover-id: --color-bg-secondary-hover; +$color-bg-tertiary: var(--color-bg-tertiary, var(--color-gray-300)); +$color-bg-tertiary-id: --color-bg-tertiary; +$color-bg-primary-solid: var(--color-bg-primary-solid, var(--color-purple-800)); +$color-bg-primary-solid-id: --color-bg-primary-solid; +$color-bg-secondary-solid: var(--color-bg-secondary-solid, var(--color-gray-600)); +$color-bg-secondary-solid-id: --color-bg-secondary-solid; +$color-bg-overlay: var(--color-bg-overlay, var(--color-white)); +$color-bg-overlay-id: --color-bg-overlay; +$color-bg-brand-primary: var(--color-bg-brand-primary, var(--color-blue-100)); +$color-bg-brand-primary-id: --color-bg-brand-primary; +$color-bg-brand-secondary: var(--color-bg-brand-secondary, var(--color-blue-200)); +$color-bg-brand-secondary-id: --color-bg-brand-secondary; +$color-bg-brand-solid: var(--color-bg-brand-solid, var(--color-blue-500)); +$color-bg-brand-solid-id: --color-bg-brand-solid; +$color-bg-brand-solid-hover: var(--color-bg-brand-solid-hover, var(--color-blue-700)); +$color-bg-brand-solid-hover-id: --color-bg-brand-solid-hover; +$color-bg-error-primary: var(--color-bg-error-primary, var(--color-red-100)); +$color-bg-error-primary-id: --color-bg-error-primary; +$color-bg-error-secondary: var(--color-bg-error-secondary, var(--color-red-300)); +$color-bg-error-secondary-id: --color-bg-error-secondary; +$color-bg-error-solid: var(--color-bg-error-solid, var(--color-red-400)); +$color-bg-error-solid-id: --color-bg-error-solid; +$color-bg-success-primary: var(--color-bg-success-primary, var(--color-green-100)); +$color-bg-success-primary-id: --color-bg-success-primary; +$color-bg-success-secondary: var(--color-bg-success-secondary, var(--color-green-300)); +$color-bg-success-secondary-id: --color-bg-success-secondary; +$color-bg-success-solid: var(--color-bg-success-solid, var(--color-green-600)); +$color-bg-success-solid-id: --color-bg-success-solid; +$color-bg-warning-primary: var(--color-bg-warning-primary, var(--color-yellow-100)); +$color-bg-warning-primary-id: --color-bg-warning-primary; +$color-bg-warning-secondary: var(--color-bg-warning-secondary, var(--color-yellow-400)); +$color-bg-warning-secondary-id: --color-bg-warning-secondary; +$color-bg-warning-solid: var(--color-bg-warning-solid, var(--color-yellow-400)); +$color-bg-warning-solid-id: --color-bg-warning-solid; +$color-text-primary: var(--color-text-primary, var(--color-purple-800)); +$color-text-primary-id: --color-text-primary; +$color-text-secondary: var(--color-text-secondary, var(--color-gray-700)); +$color-text-secondary-id: --color-text-secondary; +$color-text-tertiary: var(--color-text-tertiary, var(--color-gray-600)); +$color-text-tertiary-id: --color-text-tertiary; +$color-text-quaternary: var(--color-text-quaternary, var(--color-gray-550)); +$color-text-quaternary-id: --color-text-quaternary; +$color-text-placeholder: var(--color-text-placeholder, var(--color-gray-550)); +$color-text-placeholder-id: --color-text-placeholder; +$color-text-secondary-on-brand: var(--color-text-secondary-on-brand, var(--color-white)); +$color-text-secondary-on-brand-id: --color-text-secondary-on-brand; +$color-text-quaternary-on-brand: var(--color-text-quaternary-on-brand, var(--color-white)); +$color-text-quaternary-on-brand-id: --color-text-quaternary-on-brand; +$color-text-brand-primary: var(--color-text-brand-primary, var(--color-blue-500)); +$color-text-brand-primary-id: --color-text-brand-primary; +$color-text-brand-secondary: var(--color-text-brand-secondary, var(--color-blue-700)); +$color-text-brand-secondary-id: --color-text-brand-secondary; +$color-text-brand-secondary-hover: var(--color-text-brand-secondary-hover, var(--color-blue-600)); +$color-text-brand-secondary-hover-id: --color-text-brand-secondary-hover; +$color-text-error-primary: var(--color-text-error-primary, var(--color-red-600)); +$color-text-error-primary-id: --color-text-error-primary; +$color-text-success-primary: var(--color-text-success-primary, var(--color-green-600)); +$color-text-success-primary-id: --color-text-success-primary; +$color-fg-primary: var(--color-fg-primary, var(--color-purple-800)); +$color-fg-primary-id: --color-fg-primary; +$color-fg-secondary: var(--color-fg-secondary, var(--color-purple-800)); +$color-fg-secondary-id: --color-fg-secondary; +$color-fg-secondary-hover: var(--color-fg-secondary-hover, var(--color-purple-800)); +$color-fg-secondary-hover-id: --color-fg-secondary-hover; +$color-fg-tertiary: var(--color-fg-tertiary, var(--color-gray-500)); +$color-fg-tertiary-id: --color-fg-tertiary; +$color-fg-quaternary: var(--color-fg-quaternary, var(--color-purple-800)); +$color-fg-quaternary-id: --color-fg-quaternary; +$color-fg-white: var(--color-fg-white, var(--color-white)); +$color-fg-white-id: --color-fg-white; +$color-fg-brand-primary: var(--color-fg-brand-primary, var(--color-blue-500)); +$color-fg-brand-primary-id: --color-fg-brand-primary; +$color-fg-error-primary: var(--color-fg-error-primary, var(--color-red-500)); +$color-fg-error-primary-id: --color-fg-error-primary; +$color-fg-success-primary: var(--color-fg-success-primary, var(--color-green-500)); +$color-fg-success-primary-id: --color-fg-success-primary; +$color-fg-success-secondary: var(--color-fg-success-secondary, var(--color-green-400)); +$color-fg-success-secondary-id: --color-fg-success-secondary; +$color-fg-warning-primary: var(--color-fg-warning-primary, var(--color-yellow-700)); +$color-fg-warning-primary-id: --color-fg-warning-primary; +$color-border-primary: var(--color-border-primary, var(--color-gray-600)); +$color-border-primary-id: --color-border-primary; +$color-border-secondary: var(--color-border-secondary, var(--color-gray-500)); +$color-border-secondary-id: --color-border-secondary; +$color-border-secondary-alt: var(--color-border-secondary-alt, var(--color-gray-200)); +$color-border-secondary-alt-id: --color-border-secondary-alt; +$color-border-tertiary: var(--color-border-tertiary, var(--color-gray-300)); +$color-border-tertiary-id: --color-border-tertiary; +$color-border-brand: var(--color-border-brand, var(--color-blue-500)); +$color-border-brand-id: --color-border-brand; +$color-border-brand-alt: var(--color-border-brand-alt, var(--color-blue-300)); +$color-border-brand-alt-id: --color-border-brand-alt; +$color-border-error: var(--color-border-error, var(--color-red-500)); +$color-border-error-id: --color-border-error; +$color-border-error-subtle: var(--color-border-error-subtle, var(--color-red-300)); +$color-border-error-subtle-id: --color-border-error-subtle; +$color-bg-primary: var(--color-bg-primary, var(--color-white)); +$color-bg-primary-id: --color-bg-primary; +$color-bg-secondary: var(--color-bg-secondary, var(--color-gray-200)); +$color-bg-secondary-id: --color-bg-secondary; +$color-bg-secondary-hover: var(--color-bg-secondary-hover, var(--color-gray-200)); +$color-bg-secondary-hover-id: --color-bg-secondary-hover; +$color-bg-tertiary: var(--color-bg-tertiary, var(--color-gray-300)); +$color-bg-tertiary-id: --color-bg-tertiary; +$color-bg-primary-solid: var(--color-bg-primary-solid, var(--color-purple-800)); +$color-bg-primary-solid-id: --color-bg-primary-solid; +$color-bg-secondary-solid: var(--color-bg-secondary-solid, var(--color-gray-600)); +$color-bg-secondary-solid-id: --color-bg-secondary-solid; +$color-bg-overlay: var(--color-bg-overlay, var(--color-white)); +$color-bg-overlay-id: --color-bg-overlay; +$color-bg-brand-primary: var(--color-bg-brand-primary, var(--color-blue-100)); +$color-bg-brand-primary-id: --color-bg-brand-primary; +$color-bg-brand-secondary: var(--color-bg-brand-secondary, var(--color-blue-200)); +$color-bg-brand-secondary-id: --color-bg-brand-secondary; +$color-bg-brand-solid: var(--color-bg-brand-solid, var(--color-blue-500)); +$color-bg-brand-solid-id: --color-bg-brand-solid; +$color-bg-brand-solid-hover: var(--color-bg-brand-solid-hover, var(--color-blue-700)); +$color-bg-brand-solid-hover-id: --color-bg-brand-solid-hover; +$color-bg-error-primary: var(--color-bg-error-primary, var(--color-red-100)); +$color-bg-error-primary-id: --color-bg-error-primary; +$color-bg-error-secondary: var(--color-bg-error-secondary, var(--color-red-300)); +$color-bg-error-secondary-id: --color-bg-error-secondary; +$color-bg-error-solid: var(--color-bg-error-solid, var(--color-red-400)); +$color-bg-error-solid-id: --color-bg-error-solid; +$color-bg-success-primary: var(--color-bg-success-primary, var(--color-green-100)); +$color-bg-success-primary-id: --color-bg-success-primary; +$color-bg-success-secondary: var(--color-bg-success-secondary, var(--color-green-300)); +$color-bg-success-secondary-id: --color-bg-success-secondary; +$color-bg-success-solid: var(--color-bg-success-solid, var(--color-green-600)); +$color-bg-success-solid-id: --color-bg-success-solid; +$color-bg-warning-primary: var(--color-bg-warning-primary, var(--color-yellow-100)); +$color-bg-warning-primary-id: --color-bg-warning-primary; +$color-bg-warning-secondary: var(--color-bg-warning-secondary, var(--color-yellow-400)); +$color-bg-warning-secondary-id: --color-bg-warning-secondary; +$color-bg-warning-solid: var(--color-bg-warning-solid, var(--color-yellow-400)); +$color-bg-warning-solid-id: --color-bg-warning-solid; +$color-text-primary: var(--color-text-primary, var(--color-purple-800)); +$color-text-primary-id: --color-text-primary; +$color-text-secondary: var(--color-text-secondary, var(--color-gray-700)); +$color-text-secondary-id: --color-text-secondary; +$color-text-tertiary: var(--color-text-tertiary, var(--color-gray-600)); +$color-text-tertiary-id: --color-text-tertiary; +$color-text-quaternary: var(--color-text-quaternary, var(--color-gray-550)); +$color-text-quaternary-id: --color-text-quaternary; +$color-text-placeholder: var(--color-text-placeholder, var(--color-gray-550)); +$color-text-placeholder-id: --color-text-placeholder; +$color-text-secondary-on-brand: var(--color-text-secondary-on-brand, var(--color-white)); +$color-text-secondary-on-brand-id: --color-text-secondary-on-brand; +$color-text-quaternary-on-brand: var(--color-text-quaternary-on-brand, var(--color-white)); +$color-text-quaternary-on-brand-id: --color-text-quaternary-on-brand; +$color-text-brand-primary: var(--color-text-brand-primary, var(--color-blue-500)); +$color-text-brand-primary-id: --color-text-brand-primary; +$color-text-brand-secondary: var(--color-text-brand-secondary, var(--color-blue-700)); +$color-text-brand-secondary-id: --color-text-brand-secondary; +$color-text-brand-secondary-hover: var(--color-text-brand-secondary-hover, var(--color-blue-600)); +$color-text-brand-secondary-hover-id: --color-text-brand-secondary-hover; +$color-text-error-primary: var(--color-text-error-primary, var(--color-red-600)); +$color-text-error-primary-id: --color-text-error-primary; +$color-text-success-primary: var(--color-text-success-primary, var(--color-green-600)); +$color-text-success-primary-id: --color-text-success-primary; +$color-fg-primary: var(--color-fg-primary, var(--color-purple-800)); +$color-fg-primary-id: --color-fg-primary; +$color-fg-secondary: var(--color-fg-secondary, var(--color-purple-800)); +$color-fg-secondary-id: --color-fg-secondary; +$color-fg-secondary-hover: var(--color-fg-secondary-hover, var(--color-purple-800)); +$color-fg-secondary-hover-id: --color-fg-secondary-hover; +$color-fg-tertiary: var(--color-fg-tertiary, var(--color-gray-500)); +$color-fg-tertiary-id: --color-fg-tertiary; +$color-fg-quaternary: var(--color-fg-quaternary, var(--color-purple-800)); +$color-fg-quaternary-id: --color-fg-quaternary; +$color-fg-white: var(--color-fg-white, var(--color-white)); +$color-fg-white-id: --color-fg-white; +$color-fg-brand-primary: var(--color-fg-brand-primary, var(--color-blue-500)); +$color-fg-brand-primary-id: --color-fg-brand-primary; +$color-fg-error-primary: var(--color-fg-error-primary, var(--color-red-500)); +$color-fg-error-primary-id: --color-fg-error-primary; +$color-fg-success-primary: var(--color-fg-success-primary, var(--color-green-500)); +$color-fg-success-primary-id: --color-fg-success-primary; +$color-fg-success-secondary: var(--color-fg-success-secondary, var(--color-green-400)); +$color-fg-success-secondary-id: --color-fg-success-secondary; +$color-fg-warning-primary: var(--color-fg-warning-primary, var(--color-yellow-700)); +$color-fg-warning-primary-id: --color-fg-warning-primary; +$color-border-primary: var(--color-border-primary, var(--color-gray-600)); +$color-border-primary-id: --color-border-primary; +$color-border-secondary: var(--color-border-secondary, var(--color-gray-500)); +$color-border-secondary-id: --color-border-secondary; +$color-border-secondary-alt: var(--color-border-secondary-alt, var(--color-gray-200)); +$color-border-secondary-alt-id: --color-border-secondary-alt; +$color-border-tertiary: var(--color-border-tertiary, var(--color-gray-300)); +$color-border-tertiary-id: --color-border-tertiary; +$color-border-brand: var(--color-border-brand, var(--color-blue-500)); +$color-border-brand-id: --color-border-brand; +$color-border-brand-alt: var(--color-border-brand-alt, var(--color-blue-300)); +$color-border-brand-alt-id: --color-border-brand-alt; +$color-border-error: var(--color-border-error, var(--color-red-500)); +$color-border-error-id: --color-border-error; +$color-border-error-subtle: var(--color-border-error-subtle, var(--color-red-300)); +$color-border-error-subtle-id: --color-border-error-subtle; diff --git a/packages/design-tokens/src/lib/makeCssVariableDefinitionsMap.ts b/packages/design-tokens/src/lib/makeCssVariableDefinitionsMap.ts index fb1581a948b..74f7c8ccafc 100644 --- a/packages/design-tokens/src/lib/makeCssVariableDefinitionsMap.ts +++ b/packages/design-tokens/src/lib/makeCssVariableDefinitionsMap.ts @@ -36,6 +36,9 @@ export function makeCssVariableDefinitionsMap( // Shamelessly using a map function like a forEach mapLeafsOfObject(theme, (path, value) => { + // Semantic tokens with no confident mapping yet are `null`; skip them so we + // don't emit a literal `null` definition (e.g. `--color-bg-primary-alt: null`). + if (value === null) return // Key will be `--color-blah` const key = objectPathToCssVarIdentifier(path) const nextCssVariables = addExtraThemeEntries(path, key, value, (_, v) => `${v}`, { diff --git a/packages/design-tokens/src/lib/makeCssVariableTheme.ts b/packages/design-tokens/src/lib/makeCssVariableTheme.ts index 27c5583a697..79f2dfbb2b2 100644 --- a/packages/design-tokens/src/lib/makeCssVariableTheme.ts +++ b/packages/design-tokens/src/lib/makeCssVariableTheme.ts @@ -42,6 +42,9 @@ export function makeCSSVariableTheme = {} const mapper = (leafPath: string[], value: unknown): void => { + // Semantic tokens with no confident mapping yet are `null`. A null token has + // no value, so emit nothing for it (rather than a literal `null` fallback). + if (value === null) return const leafKey = leafPath[leafPath.length - 1] const pathWithoutLast = leafPath.slice(0, leafPath.length - 1) const leafObject = pathWithoutLast.reduce( diff --git a/packages/design-tokens/tokens/color.json b/packages/design-tokens/tokens/color.json index 0f4ff331e4f..7d24b2bd49e 100644 --- a/packages/design-tokens/tokens/color.json +++ b/packages/design-tokens/tokens/color.json @@ -235,6 +235,210 @@ "black": "var(--color-black, #000000)", "black-rgb": "var(--color-black-rgb, 0, 0, 0)", "black-rgb-id": "--color-black-rgb", - "black-id": "--color-black" + "black-id": "--color-black", + "bg-primary": "var(--color-bg-primary, var(--color-white))", + "bg-primary-id": "--color-bg-primary", + "bg-secondary": "var(--color-bg-secondary, var(--color-gray-200))", + "bg-secondary-id": "--color-bg-secondary", + "bg-secondary_hover": "var(--color-bg-secondary-hover, var(--color-gray-200))", + "bg-secondary_hover-id": "--color-bg-secondary-hover", + "bg-tertiary": "var(--color-bg-tertiary, var(--color-gray-300))", + "bg-tertiary-id": "--color-bg-tertiary", + "bg-primary-solid": "var(--color-bg-primary-solid, var(--color-purple-800))", + "bg-primary-solid-id": "--color-bg-primary-solid", + "bg-secondary-solid": "var(--color-bg-secondary-solid, var(--color-gray-600))", + "bg-secondary-solid-id": "--color-bg-secondary-solid", + "bg-overlay": "var(--color-bg-overlay, var(--color-white))", + "bg-overlay-id": "--color-bg-overlay", + "bg-brand-primary": "var(--color-bg-brand-primary, var(--color-blue-100))", + "bg-brand-primary-id": "--color-bg-brand-primary", + "bg-brand-secondary": "var(--color-bg-brand-secondary, var(--color-blue-200))", + "bg-brand-secondary-id": "--color-bg-brand-secondary", + "bg-brand-solid": "var(--color-bg-brand-solid, var(--color-blue-500))", + "bg-brand-solid-id": "--color-bg-brand-solid", + "bg-brand-solid_hover": "var(--color-bg-brand-solid-hover, var(--color-blue-700))", + "bg-brand-solid_hover-id": "--color-bg-brand-solid-hover", + "bg-error-primary": "var(--color-bg-error-primary, var(--color-red-100))", + "bg-error-primary-id": "--color-bg-error-primary", + "bg-error-secondary": "var(--color-bg-error-secondary, var(--color-red-300))", + "bg-error-secondary-id": "--color-bg-error-secondary", + "bg-error-solid": "var(--color-bg-error-solid, var(--color-red-400))", + "bg-error-solid-id": "--color-bg-error-solid", + "bg-success-primary": "var(--color-bg-success-primary, var(--color-green-100))", + "bg-success-primary-id": "--color-bg-success-primary", + "bg-success-secondary": "var(--color-bg-success-secondary, var(--color-green-300))", + "bg-success-secondary-id": "--color-bg-success-secondary", + "bg-success-solid": "var(--color-bg-success-solid, var(--color-green-600))", + "bg-success-solid-id": "--color-bg-success-solid", + "bg-warning-primary": "var(--color-bg-warning-primary, var(--color-yellow-100))", + "bg-warning-primary-id": "--color-bg-warning-primary", + "bg-warning-secondary": "var(--color-bg-warning-secondary, var(--color-yellow-400))", + "bg-warning-secondary-id": "--color-bg-warning-secondary", + "bg-warning-solid": "var(--color-bg-warning-solid, var(--color-yellow-400))", + "bg-warning-solid-id": "--color-bg-warning-solid", + "text-primary": "var(--color-text-primary, var(--color-purple-800))", + "text-primary-id": "--color-text-primary", + "text-secondary": "var(--color-text-secondary, var(--color-gray-700))", + "text-secondary-id": "--color-text-secondary", + "text-tertiary": "var(--color-text-tertiary, var(--color-gray-600))", + "text-tertiary-id": "--color-text-tertiary", + "text-quaternary": "var(--color-text-quaternary, var(--color-gray-550))", + "text-quaternary-id": "--color-text-quaternary", + "text-placeholder": "var(--color-text-placeholder, var(--color-gray-550))", + "text-placeholder-id": "--color-text-placeholder", + "text-secondary_on-brand": "var(--color-text-secondary-on-brand, var(--color-white))", + "text-secondary_on-brand-id": "--color-text-secondary-on-brand", + "text-quaternary_on-brand": "var(--color-text-quaternary-on-brand, var(--color-white))", + "text-quaternary_on-brand-id": "--color-text-quaternary-on-brand", + "text-brand-primary": "var(--color-text-brand-primary, var(--color-blue-500))", + "text-brand-primary-id": "--color-text-brand-primary", + "text-brand-secondary": "var(--color-text-brand-secondary, var(--color-blue-700))", + "text-brand-secondary-id": "--color-text-brand-secondary", + "text-brand-secondary_hover": "var(--color-text-brand-secondary-hover, var(--color-blue-600))", + "text-brand-secondary_hover-id": "--color-text-brand-secondary-hover", + "text-error-primary": "var(--color-text-error-primary, var(--color-red-600))", + "text-error-primary-id": "--color-text-error-primary", + "text-success-primary": "var(--color-text-success-primary, var(--color-green-600))", + "text-success-primary-id": "--color-text-success-primary", + "fg-primary": "var(--color-fg-primary, var(--color-purple-800))", + "fg-primary-id": "--color-fg-primary", + "fg-secondary": "var(--color-fg-secondary, var(--color-purple-800))", + "fg-secondary-id": "--color-fg-secondary", + "fg-secondary_hover": "var(--color-fg-secondary-hover, var(--color-purple-800))", + "fg-secondary_hover-id": "--color-fg-secondary-hover", + "fg-tertiary": "var(--color-fg-tertiary, var(--color-gray-500))", + "fg-tertiary-id": "--color-fg-tertiary", + "fg-quaternary": "var(--color-fg-quaternary, var(--color-purple-800))", + "fg-quaternary-id": "--color-fg-quaternary", + "fg-white": "var(--color-fg-white, var(--color-white))", + "fg-white-id": "--color-fg-white", + "fg-brand-primary": "var(--color-fg-brand-primary, var(--color-blue-500))", + "fg-brand-primary-id": "--color-fg-brand-primary", + "fg-error-primary": "var(--color-fg-error-primary, var(--color-red-500))", + "fg-error-primary-id": "--color-fg-error-primary", + "fg-success-primary": "var(--color-fg-success-primary, var(--color-green-500))", + "fg-success-primary-id": "--color-fg-success-primary", + "fg-success-secondary": "var(--color-fg-success-secondary, var(--color-green-400))", + "fg-success-secondary-id": "--color-fg-success-secondary", + "fg-warning-primary": "var(--color-fg-warning-primary, var(--color-yellow-700))", + "fg-warning-primary-id": "--color-fg-warning-primary", + "border-primary": "var(--color-border-primary, var(--color-gray-600))", + "border-primary-id": "--color-border-primary", + "border-secondary": "var(--color-border-secondary, var(--color-gray-500))", + "border-secondary-id": "--color-border-secondary", + "border-secondary_alt": "var(--color-border-secondary-alt, var(--color-gray-200))", + "border-secondary_alt-id": "--color-border-secondary-alt", + "border-tertiary": "var(--color-border-tertiary, var(--color-gray-300))", + "border-tertiary-id": "--color-border-tertiary", + "border-brand": "var(--color-border-brand, var(--color-blue-500))", + "border-brand-id": "--color-border-brand", + "border-brand_alt": "var(--color-border-brand-alt, var(--color-blue-300))", + "border-brand_alt-id": "--color-border-brand-alt", + "border-error": "var(--color-border-error, var(--color-red-500))", + "border-error-id": "--color-border-error", + "border-error_subtle": "var(--color-border-error-subtle, var(--color-red-300))", + "border-error_subtle-id": "--color-border-error-subtle", + "bgPrimary": "var(--color-bg-primary, var(--color-white))", + "bgPrimary-id": "--color-bg-primary", + "bgSecondary": "var(--color-bg-secondary, var(--color-gray-200))", + "bgSecondary-id": "--color-bg-secondary", + "bgSecondaryHover": "var(--color-bg-secondary-hover, var(--color-gray-200))", + "bgSecondaryHover-id": "--color-bg-secondary-hover", + "bgTertiary": "var(--color-bg-tertiary, var(--color-gray-300))", + "bgTertiary-id": "--color-bg-tertiary", + "bgPrimarySolid": "var(--color-bg-primary-solid, var(--color-purple-800))", + "bgPrimarySolid-id": "--color-bg-primary-solid", + "bgSecondarySolid": "var(--color-bg-secondary-solid, var(--color-gray-600))", + "bgSecondarySolid-id": "--color-bg-secondary-solid", + "bgOverlay": "var(--color-bg-overlay, var(--color-white))", + "bgOverlay-id": "--color-bg-overlay", + "bgBrandPrimary": "var(--color-bg-brand-primary, var(--color-blue-100))", + "bgBrandPrimary-id": "--color-bg-brand-primary", + "bgBrandSecondary": "var(--color-bg-brand-secondary, var(--color-blue-200))", + "bgBrandSecondary-id": "--color-bg-brand-secondary", + "bgBrandSolid": "var(--color-bg-brand-solid, var(--color-blue-500))", + "bgBrandSolid-id": "--color-bg-brand-solid", + "bgBrandSolidHover": "var(--color-bg-brand-solid-hover, var(--color-blue-700))", + "bgBrandSolidHover-id": "--color-bg-brand-solid-hover", + "bgErrorPrimary": "var(--color-bg-error-primary, var(--color-red-100))", + "bgErrorPrimary-id": "--color-bg-error-primary", + "bgErrorSecondary": "var(--color-bg-error-secondary, var(--color-red-300))", + "bgErrorSecondary-id": "--color-bg-error-secondary", + "bgErrorSolid": "var(--color-bg-error-solid, var(--color-red-400))", + "bgErrorSolid-id": "--color-bg-error-solid", + "bgSuccessPrimary": "var(--color-bg-success-primary, var(--color-green-100))", + "bgSuccessPrimary-id": "--color-bg-success-primary", + "bgSuccessSecondary": "var(--color-bg-success-secondary, var(--color-green-300))", + "bgSuccessSecondary-id": "--color-bg-success-secondary", + "bgSuccessSolid": "var(--color-bg-success-solid, var(--color-green-600))", + "bgSuccessSolid-id": "--color-bg-success-solid", + "bgWarningPrimary": "var(--color-bg-warning-primary, var(--color-yellow-100))", + "bgWarningPrimary-id": "--color-bg-warning-primary", + "bgWarningSecondary": "var(--color-bg-warning-secondary, var(--color-yellow-400))", + "bgWarningSecondary-id": "--color-bg-warning-secondary", + "bgWarningSolid": "var(--color-bg-warning-solid, var(--color-yellow-400))", + "bgWarningSolid-id": "--color-bg-warning-solid", + "textPrimary": "var(--color-text-primary, var(--color-purple-800))", + "textPrimary-id": "--color-text-primary", + "textSecondary": "var(--color-text-secondary, var(--color-gray-700))", + "textSecondary-id": "--color-text-secondary", + "textTertiary": "var(--color-text-tertiary, var(--color-gray-600))", + "textTertiary-id": "--color-text-tertiary", + "textQuaternary": "var(--color-text-quaternary, var(--color-gray-550))", + "textQuaternary-id": "--color-text-quaternary", + "textPlaceholder": "var(--color-text-placeholder, var(--color-gray-550))", + "textPlaceholder-id": "--color-text-placeholder", + "textSecondaryOnBrand": "var(--color-text-secondary-on-brand, var(--color-white))", + "textSecondaryOnBrand-id": "--color-text-secondary-on-brand", + "textQuaternaryOnBrand": "var(--color-text-quaternary-on-brand, var(--color-white))", + "textQuaternaryOnBrand-id": "--color-text-quaternary-on-brand", + "textBrandPrimary": "var(--color-text-brand-primary, var(--color-blue-500))", + "textBrandPrimary-id": "--color-text-brand-primary", + "textBrandSecondary": "var(--color-text-brand-secondary, var(--color-blue-700))", + "textBrandSecondary-id": "--color-text-brand-secondary", + "textBrandSecondaryHover": "var(--color-text-brand-secondary-hover, var(--color-blue-600))", + "textBrandSecondaryHover-id": "--color-text-brand-secondary-hover", + "textErrorPrimary": "var(--color-text-error-primary, var(--color-red-600))", + "textErrorPrimary-id": "--color-text-error-primary", + "textSuccessPrimary": "var(--color-text-success-primary, var(--color-green-600))", + "textSuccessPrimary-id": "--color-text-success-primary", + "fgPrimary": "var(--color-fg-primary, var(--color-purple-800))", + "fgPrimary-id": "--color-fg-primary", + "fgSecondary": "var(--color-fg-secondary, var(--color-purple-800))", + "fgSecondary-id": "--color-fg-secondary", + "fgSecondaryHover": "var(--color-fg-secondary-hover, var(--color-purple-800))", + "fgSecondaryHover-id": "--color-fg-secondary-hover", + "fgTertiary": "var(--color-fg-tertiary, var(--color-gray-500))", + "fgTertiary-id": "--color-fg-tertiary", + "fgQuaternary": "var(--color-fg-quaternary, var(--color-purple-800))", + "fgQuaternary-id": "--color-fg-quaternary", + "fgWhite": "var(--color-fg-white, var(--color-white))", + "fgWhite-id": "--color-fg-white", + "fgBrandPrimary": "var(--color-fg-brand-primary, var(--color-blue-500))", + "fgBrandPrimary-id": "--color-fg-brand-primary", + "fgErrorPrimary": "var(--color-fg-error-primary, var(--color-red-500))", + "fgErrorPrimary-id": "--color-fg-error-primary", + "fgSuccessPrimary": "var(--color-fg-success-primary, var(--color-green-500))", + "fgSuccessPrimary-id": "--color-fg-success-primary", + "fgSuccessSecondary": "var(--color-fg-success-secondary, var(--color-green-400))", + "fgSuccessSecondary-id": "--color-fg-success-secondary", + "fgWarningPrimary": "var(--color-fg-warning-primary, var(--color-yellow-700))", + "fgWarningPrimary-id": "--color-fg-warning-primary", + "borderPrimary": "var(--color-border-primary, var(--color-gray-600))", + "borderPrimary-id": "--color-border-primary", + "borderSecondary": "var(--color-border-secondary, var(--color-gray-500))", + "borderSecondary-id": "--color-border-secondary", + "borderSecondaryAlt": "var(--color-border-secondary-alt, var(--color-gray-200))", + "borderSecondaryAlt-id": "--color-border-secondary-alt", + "borderTertiary": "var(--color-border-tertiary, var(--color-gray-300))", + "borderTertiary-id": "--color-border-tertiary", + "borderBrand": "var(--color-border-brand, var(--color-blue-500))", + "borderBrand-id": "--color-border-brand", + "borderBrandAlt": "var(--color-border-brand-alt, var(--color-blue-300))", + "borderBrandAlt-id": "--color-border-brand-alt", + "borderError": "var(--color-border-error, var(--color-red-500))", + "borderError-id": "--color-border-error", + "borderErrorSubtle": "var(--color-border-error-subtle, var(--color-red-300))", + "borderErrorSubtle-id": "--color-border-error-subtle" } } From f0727d3dee172942691796deae8e69821249741b Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Wed, 1 Jul 2026 13:25:13 +1000 Subject: [PATCH 17/25] fix(design-tokens): make build:json the single owner of variables.css MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Semantic CSS vars were appended to variables.css by build:semantic AFTER build:json wrote it. Running build:json alone (partial rebuild, watch task) overwrote the file and silently dropped every semantic --bg-* var, breaking all semantic Tailwind classes with no error. build:json now emits the semantic block itself, in the same write, so variables.css is always complete from one script — no order coupling. build:semantic no longer touches variables.css; it still writes the standalone semantic-color.css / .scss. A shared semanticColorCssVariableLines helper keeps the two outputs from drifting. Both naming schemes remain (--bg-* for Tailwind, --color-bg-* for SCSS/LESS), the tokens.color merge is untouched, and consumers need no extra import. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../design-tokens/bin/buildCssVarTokens.ts | 19 +++++-- .../design-tokens/bin/buildSemanticTokens.ts | 27 +++------ packages/design-tokens/css/variables.css | 56 ++++++++++++++++++- .../src/js/semanticColorTokens.ts | 11 ++++ 4 files changed, 90 insertions(+), 23 deletions(-) diff --git a/packages/design-tokens/bin/buildCssVarTokens.ts b/packages/design-tokens/bin/buildCssVarTokens.ts index 34f0b03fbf4..d33a3cd6409 100644 --- a/packages/design-tokens/bin/buildCssVarTokens.ts +++ b/packages/design-tokens/bin/buildCssVarTokens.ts @@ -3,9 +3,12 @@ import path from 'path' import { toCustomPropertiesString } from 'object-to-css-variables' import { format } from 'prettier' import { tokens } from '../src/js' +import { semanticColorCssVariableLines } from '../src/js/semanticColorTokens' import { makeCssVariableDefinitionsMap } from '../src/lib/makeCssVariableDefinitionsMap' import { makeCSSVariableTheme } from '../src/lib/makeCssVariableTheme' +const SEMANTIC_MARKER = '/* --- Semantic colour tokens (autogenerated) --- */' + const JSON_OUTPUT_DIR = `${process.cwd()}/tokens` const CSS_OUTPUT_DIR = `${process.cwd()}/css` @@ -18,13 +21,21 @@ const run = async (): Promise => { // Write CSS vars tokens to CSS format const cssVars = toCustomPropertiesString(makeCssVariableDefinitionsMap(tokens)) - fs.writeFileSync( - path.resolve(CSS_OUTPUT_DIR, 'variables.css'), - ` + // Emit the semantic colour tokens (`--bg-*`, `--text-*`, `--fg-*`, `--border-*`) + // in the SAME write, so variables.css is always complete from this one script. + // (Previously build:semantic appended them afterwards, which meant running + // build:json alone silently dropped every semantic var.) + const semanticBlock = `${SEMANTIC_MARKER}\n:root {\n${semanticColorCssVariableLines().join('\n')}\n}\n` + + const primitivesCss = ` /** THIS IS AN AUTOGENERATED FILE **/ :root{${cssVars}} - `, + ` + + fs.writeFileSync( + path.resolve(CSS_OUTPUT_DIR, 'variables.css'), + `${primitivesCss.trimEnd()}\n\n${semanticBlock}`, ) /** diff --git a/packages/design-tokens/bin/buildSemanticTokens.ts b/packages/design-tokens/bin/buildSemanticTokens.ts index 89a0ef5c687..1b4c51957d1 100644 --- a/packages/design-tokens/bin/buildSemanticTokens.ts +++ b/packages/design-tokens/bin/buildSemanticTokens.ts @@ -1,6 +1,9 @@ import fs from 'fs' import path from 'path' -import { semanticColorTokens } from '../src/js/semanticColorTokens' +import { + semanticColorCssVariableLines, + semanticColorTokens, +} from '../src/js/semanticColorTokens' const CSS_OUTPUT_DIR = `${process.cwd()}/css` const SASS_OUTPUT_DIR = `${process.cwd()}/sass` @@ -19,27 +22,15 @@ const run = (): void => { fs.mkdirSync(CSS_OUTPUT_DIR, { recursive: true }) fs.mkdirSync(SASS_OUTPUT_DIR, { recursive: true }) - // css/semantic-color.css — CSS custom properties on :root - const cssLines = flatEntries.map(([key, value]) => ` --${key}: ${value};`) + // css/semantic-color.css — standalone CSS custom properties on :root. + // The same block is also emitted directly into variables.css by build:json + // (via the shared semanticColorCssVariableLines helper), so consumers of + // variables.css get the semantic vars without importing this file. fs.writeFileSync( path.resolve(CSS_OUTPUT_DIR, 'semantic-color.css'), - `${AUTOGENERATED_HEADER}\n\n:root {\n${cssLines.join('\n')}\n}\n`, + `${AUTOGENERATED_HEADER}\n\n:root {\n${semanticColorCssVariableLines().join('\n')}\n}\n`, ) - // Inline the same semantic vars into the primitives entrypoint (variables.css) - // so every consumer of variables.css gets them automatically — no extra import. - // Runs after build:json (which regenerates variables.css), and is idempotent - // via the marker so re-running build:semantic alone won't duplicate the block. - const VARIABLES_PATH = path.resolve(CSS_OUTPUT_DIR, 'variables.css') - const SEMANTIC_MARKER = '/* --- Semantic colour tokens (autogenerated) --- */' - if (fs.existsSync(VARIABLES_PATH)) { - const existing = fs.readFileSync(VARIABLES_PATH, 'utf8') - const markerIdx = existing.indexOf(SEMANTIC_MARKER) - const primitives = markerIdx === -1 ? existing : existing.slice(0, markerIdx) - const semanticBlock = `${SEMANTIC_MARKER}\n:root {\n${cssLines.join('\n')}\n}\n` - fs.writeFileSync(VARIABLES_PATH, `${primitives.trimEnd()}\n\n${semanticBlock}`) - } - // sass/semantic-color.scss — SCSS variables that fall back through the CSS var const scssLines = flatEntries.map(([key, value]) => `$${key}: var(--${key}, ${value});`) fs.writeFileSync( diff --git a/packages/design-tokens/css/variables.css b/packages/design-tokens/css/variables.css index f448d41bc95..6f955b8f6d7 100644 --- a/packages/design-tokens/css/variables.css +++ b/packages/design-tokens/css/variables.css @@ -2,4 +2,58 @@ /** THIS IS AN AUTOGENERATED FILE **/ :root{--animation-easing-function-ease-in-out: cubic-bezier(0.455, 0.03, 0.515, 0.955); --animation-easing-function-ease-in: cubic-bezier(0.55, 0.085, 0.68, 0.53); --animation-easing-function-ease-out: cubic-bezier(0.25, 0.46, 0.45, 0.94); --animation-easing-function-linear: linear; --animation-easing-function-bounce-in: cubic-bezier(0.485, 0.155, 0.24, 1.245); --animation-easing-function-bounce-out: cubic-bezier(0.485, 0.155, 0.515, 0.845); --animation-easing-function-bounce-in-out: cubic-bezier(0.76, -0.245, 0.24, 1.245); --animation-duration-instant: 0ms; --animation-duration-immediate: 100ms; --animation-duration-rapid: 200ms; --animation-duration-fast: 300ms; --animation-duration-slow: 400ms; --animation-duration-deliberate: 700ms; --border-solid-border-width: 2px; --border-solid-border-radius: 7px; --border-solid-border-style: solid; --border-solid-border-color: #e1e2ea; --border-solid-border-color-rgb: 225, 226, 234; --border-dashed-border-width: 2px; --border-dashed-border-radius: 7px; --border-dashed-border-style: dashed; --border-borderless-border-width: 2px; --border-borderless-border-radius: 7px; --border-borderless-border-style: solid; --border-borderless-border-color: transparent; --border-borderless-border-color-rgb: 0, 0, 0; --border-focus-ring-border-width: 2px; --border-focus-ring-border-radius: 10px; --border-focus-ring-border-style: solid; --border-width-1: 1px; --color-purple-100: #f4edf8; --color-purple-100-rgb: 244, 237, 248; --color-purple-200: #dfc9ea; --color-purple-200-rgb: 223, 201, 234; --color-purple-300: #c9a5dd; --color-purple-300-rgb: 201, 165, 221; --color-purple-400: #ae67b1; --color-purple-400-rgb: 174, 103, 177; --color-purple-500: #844587; --color-purple-500-rgb: 132, 69, 135; --color-purple-600: #5f3361; --color-purple-600-rgb: 95, 51, 97; --color-purple-700: #4a234d; --color-purple-700-rgb: 74, 35, 77; --color-purple-800: #2f2438; --color-purple-800-rgb: 47, 36, 56; --color-blue-100: #e6f6ff; --color-blue-100-rgb: 230, 246, 255; --color-blue-200: #bde2f5; --color-blue-200-rgb: 189, 226, 245; --color-blue-300: #73c0e8; --color-blue-300-rgb: 115, 192, 232; --color-blue-400: #008bd6; --color-blue-400-rgb: 0, 139, 214; --color-blue-500: #0168b3; --color-blue-500-rgb: 1, 104, 179; --color-blue-600: #004970; --color-blue-600-rgb: 0, 73, 112; --color-blue-700: #003157; --color-blue-700-rgb: 0, 49, 87; --color-green-100: #e8f8f4; --color-green-100-rgb: 232, 248, 244; --color-green-200: #c4ede2; --color-green-200-rgb: 196, 237, 226; --color-green-300: #8fdbc7; --color-green-300-rgb: 143, 219, 199; --color-green-400: #5dcaad; --color-green-400-rgb: 93, 202, 173; --color-green-500: #3f9a86; --color-green-500-rgb: 63, 154, 134; --color-green-600: #2c7d67; --color-green-600-rgb: 44, 125, 103; --color-green-700: #22594a; --color-green-700-rgb: 34, 89, 74; --color-yellow-100: #fff9e4; --color-yellow-100-rgb: 255, 249, 228; --color-yellow-200: #ffeeb3; --color-yellow-200-rgb: 255, 238, 179; --color-yellow-300: #ffe36e; --color-yellow-300-rgb: 255, 227, 110; --color-yellow-400: #ffca4d; --color-yellow-400-rgb: 255, 202, 77; --color-yellow-500: #ffb600; --color-yellow-500-rgb: 255, 182, 0; --color-yellow-600: #c68600; --color-yellow-600-rgb: 198, 134, 0; --color-yellow-700: #876400; --color-yellow-700-rgb: 135, 100, 0; --color-red-100: #fdeaee; --color-red-100-rgb: 253, 234, 238; --color-red-200: #f9c2cb; --color-red-200-rgb: 249, 194, 203; --color-red-300: #f597a8; --color-red-300-rgb: 245, 151, 168; --color-red-400: #e0707d; --color-red-400-rgb: 224, 112, 125; --color-red-500: #c93b55; --color-red-500-rgb: 201, 59, 85; --color-red-600: #a82433; --color-red-600-rgb: 168, 36, 51; --color-red-700: #6c1e20; --color-red-700-rgb: 108, 30, 32; --color-orange-100: #fff0e8; --color-orange-100-rgb: 255, 240, 232; --color-orange-200: #ffd1b9; --color-orange-200-rgb: 255, 209, 185; --color-orange-300: #ffb08a; --color-orange-300-rgb: 255, 176, 138; --color-orange-400: #ff9461; --color-orange-400-rgb: 255, 148, 97; --color-orange-500: #e96c2f; --color-orange-500-rgb: 233, 108, 47; --color-orange-600: #b74302; --color-orange-600-rgb: 183, 67, 2; --color-orange-700: #903c00; --color-orange-700-rgb: 144, 60, 0; --color-gray-100: #f9f9f9; --color-gray-100-rgb: 249, 249, 249; --color-gray-200: #f4f4f5; --color-gray-200-rgb: 244, 244, 245; --color-gray-300: #eaeaec; --color-gray-300-rgb: 234, 234, 236; --color-gray-400: #cdcdd0; --color-gray-400-rgb: 205, 205, 208; --color-gray-500: #878792; --color-gray-500-rgb: 135, 135, 146; --color-gray-550: #6d6674; --color-gray-550-rgb: 109, 102, 116; --color-gray-600: #524e56; --color-gray-600-rgb: 82, 78, 86; --color-gray-700: #3f3c42; --color-gray-700-rgb: 63, 60, 66; --color-white: #ffffff; --color-white-rgb: 255, 255, 255; --color-black: #000000; --color-black-rgb: 0, 0, 0; --color-bg-primary: var(--color-white); --color-bg-secondary: var(--color-gray-200); --color-bg-secondary-hover: var(--color-gray-200); --color-bg-tertiary: var(--color-gray-300); --color-bg-primary-solid: var(--color-purple-800); --color-bg-secondary-solid: var(--color-gray-600); --color-bg-overlay: var(--color-white); --color-bg-brand-primary: var(--color-blue-100); --color-bg-brand-secondary: var(--color-blue-200); --color-bg-brand-solid: var(--color-blue-500); --color-bg-brand-solid-hover: var(--color-blue-700); --color-bg-error-primary: var(--color-red-100); --color-bg-error-secondary: var(--color-red-300); --color-bg-error-solid: var(--color-red-400); --color-bg-success-primary: var(--color-green-100); --color-bg-success-secondary: var(--color-green-300); --color-bg-success-solid: var(--color-green-600); --color-bg-warning-primary: var(--color-yellow-100); --color-bg-warning-secondary: var(--color-yellow-400); --color-bg-warning-solid: var(--color-yellow-400); --color-text-primary: var(--color-purple-800); --color-text-secondary: var(--color-gray-700); --color-text-tertiary: var(--color-gray-600); --color-text-quaternary: var(--color-gray-550); --color-text-placeholder: var(--color-gray-550); --color-text-secondary-on-brand: var(--color-white); --color-text-quaternary-on-brand: var(--color-white); --color-text-brand-primary: var(--color-blue-500); --color-text-brand-secondary: var(--color-blue-700); --color-text-brand-secondary-hover: var(--color-blue-600); --color-text-error-primary: var(--color-red-600); --color-text-success-primary: var(--color-green-600); --color-fg-primary: var(--color-purple-800); --color-fg-secondary: var(--color-purple-800); --color-fg-secondary-hover: var(--color-purple-800); --color-fg-tertiary: var(--color-gray-500); --color-fg-quaternary: var(--color-purple-800); --color-fg-white: var(--color-white); --color-fg-brand-primary: var(--color-blue-500); --color-fg-error-primary: var(--color-red-500); --color-fg-success-primary: var(--color-green-500); --color-fg-success-secondary: var(--color-green-400); --color-fg-warning-primary: var(--color-yellow-700); --color-border-primary: var(--color-gray-600); --color-border-secondary: var(--color-gray-500); --color-border-secondary-alt: var(--color-gray-200); --color-border-tertiary: var(--color-gray-300); --color-border-brand: var(--color-blue-500); --color-border-brand-alt: var(--color-blue-300); --color-border-error: var(--color-red-500); --color-border-error-subtle: var(--color-red-300); --data-viz-favorable: #7dd5bd; --data-viz-favorable-rgb: 125, 213, 189; --data-viz-unfavorable: #e68d97; --data-viz-unfavorable-rgb: 230, 141, 151; --layout-content-max-width: 1392px; --layout-content-max-width-with-sidebar: 1080px; --layout-content-side-margin: 72px; --layout-mobile-actions-drawer-height: 60px; --layout-navigation-bar-height: 72px; --layout-breakpoints-medium: 768px; --layout-breakpoints-large: 1080px; --shadow-small-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 3px 16px 0 rgba(0, 0, 0, 0.06); --shadow-large-box-shadow: 0 3px 9px 0 rgba(0, 0, 0, 0.1), 0 8px 40px 0 rgba(0, 0, 0, 0.08); --spacing-0: 0; --spacing-1: .0625rem; --spacing-2: .125rem; --spacing-4: .25rem; --spacing-6: .375rem; --spacing-8: .5rem; --spacing-12: .75rem; --spacing-16: 1rem; --spacing-20: 1.25rem; --spacing-24: 1.5rem; --spacing-32: 2rem; --spacing-40: 2.5rem; --spacing-48: 3rem; --spacing-56: 3.5rem; --spacing-64: 4rem; --spacing-72: 4.5rem; --spacing-80: 5rem; --spacing-96: 6rem; --spacing-112: 7rem; --spacing-128: 8rem; --spacing-160: 10rem; --spacing-200: 12.5rem; --spacing-240: 15rem; --spacing-280: 17.5rem; --spacing-320: 20rem; --spacing-xs: 0.375rem; --spacing-sm: 0.75rem; --spacing-md: 1.5rem; --spacing-lg: 2.25rem; --spacing-xl: 3rem; --spacing-xxl: 3.75rem; --spacing-xxxl: 4.5rem; --spacing-xxxxl: 5.25rem; --spacing-xxxxxl: 6rem; --typography-data-large-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-large-font-weight: 700; --typography-data-large-font-size: 5.25rem; --typography-data-large-line-height: 5.25rem; --typography-data-large-letter-spacing: normal; --typography-data-large-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-large-units-font-weight: 700; --typography-data-large-units-font-size: 2.625rem; --typography-data-large-units-line-height: 5.25rem; --typography-data-large-units-letter-spacing: normal; --typography-data-medium-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-medium-font-weight: 700; --typography-data-medium-font-size: 3rem; --typography-data-medium-line-height: 5rem; --typography-data-medium-letter-spacing: normal; --typography-data-medium-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-medium-units-font-weight: 700; --typography-data-medium-units-font-size: 1.5rem; --typography-data-medium-units-line-height: 5rem; --typography-data-medium-units-letter-spacing: normal; --typography-data-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-small-font-weight: 700; --typography-data-small-font-size: 1.5rem; --typography-data-small-line-height: 1.5rem; --typography-data-small-letter-spacing: normal; --typography-data-small-units-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-data-small-units-font-weight: 700; --typography-data-small-units-font-size: 1.125rem; --typography-data-small-units-line-height: 1.5rem; --typography-data-small-units-letter-spacing: normal; --typography-display-0-font-family: "Tiempos Headline", Georgia, serif; --typography-display-0-font-weight: 800; --typography-display-0-font-size: 4.5rem; --typography-display-0-line-height: 5.25rem; --typography-display-0-letter-spacing: 0em; --typography-heading-1-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-1-font-weight: 500; --typography-heading-1-font-size: 2.125rem; --typography-heading-1-line-height: 2.625rem; --typography-heading-1-letter-spacing: normal; --typography-heading-2-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-2-font-weight: 600; --typography-heading-2-font-size: 1.75rem; --typography-heading-2-line-height: 2.25rem; --typography-heading-2-letter-spacing: normal; --typography-heading-3-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-3-font-weight: 600; --typography-heading-3-font-size: 1.375rem; --typography-heading-3-line-height: 1.875rem; --typography-heading-3-letter-spacing: normal; --typography-heading-4-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-4-font-weight: 600; --typography-heading-4-font-size: 1.125rem; --typography-heading-4-line-height: 1.5rem; --typography-heading-4-letter-spacing: normal; --typography-heading-5-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-5-font-weight: 600; --typography-heading-5-font-size: 1rem; --typography-heading-5-line-height: 1.5rem; --typography-heading-5-letter-spacing: normal; --typography-heading-6-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-heading-6-font-weight: 600; --typography-heading-6-font-size: 0.875rem; --typography-heading-6-line-height: 1.5rem; --typography-heading-6-letter-spacing: normal; --typography-paragraph-intro-lede-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-intro-lede-font-weight: 400; --typography-paragraph-intro-lede-font-size: 1.25rem; --typography-paragraph-intro-lede-line-height: 1.875rem; --typography-paragraph-intro-lede-letter-spacing: 0; --typography-paragraph-intro-lede-max-width: 975px; --typography-paragraph-body-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-body-font-weight: 400; --typography-paragraph-body-font-size: 1rem; --typography-paragraph-body-line-height: 1.5rem; --typography-paragraph-body-letter-spacing: normal; --typography-paragraph-body-max-width: 780px; --typography-paragraph-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-small-font-weight: 400; --typography-paragraph-small-font-size: 0.875rem; --typography-paragraph-small-line-height: 1.125rem; --typography-paragraph-small-letter-spacing: normal; --typography-paragraph-small-max-width: 680px; --typography-paragraph-extra-small-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-paragraph-extra-small-font-weight: 400; --typography-paragraph-extra-small-font-size: 0.75rem; --typography-paragraph-extra-small-line-height: 1.125rem; --typography-paragraph-extra-small-letter-spacing: normal; --typography-paragraph-extra-small-max-width: 600px; --typography-paragraph-bold-font-weight: 600; --typography-button-primary-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-button-primary-font-weight: 500; --typography-button-primary-font-size: 1.125rem; --typography-button-primary-line-height: 1.5rem; --typography-button-primary-letter-spacing: normal; --typography-button-secondary-font-family: "Inter", "Noto Sans", Helvetica, Arial, sans-serif; --typography-button-secondary-font-weight: 500; --typography-button-secondary-font-size: 1rem; --typography-button-secondary-line-height: 1.5rem; --typography-button-secondary-letter-spacing: normal;} - \ No newline at end of file + +/* --- Semantic colour tokens (autogenerated) --- */ +:root { + --bg-primary: var(--color-white); + --bg-secondary: var(--color-gray-200); + --bg-secondary_hover: var(--color-gray-200); + --bg-tertiary: var(--color-gray-300); + --bg-primary-solid: var(--color-purple-800); + --bg-secondary-solid: var(--color-gray-600); + --bg-overlay: var(--color-white); + --bg-brand-primary: var(--color-blue-100); + --bg-brand-secondary: var(--color-blue-200); + --bg-brand-solid: var(--color-blue-500); + --bg-brand-solid_hover: var(--color-blue-700); + --bg-error-primary: var(--color-red-100); + --bg-error-secondary: var(--color-red-300); + --bg-error-solid: var(--color-red-400); + --bg-success-primary: var(--color-green-100); + --bg-success-secondary: var(--color-green-300); + --bg-success-solid: var(--color-green-600); + --bg-warning-primary: var(--color-yellow-100); + --bg-warning-secondary: var(--color-yellow-400); + --bg-warning-solid: var(--color-yellow-400); + --text-primary: var(--color-purple-800); + --text-secondary: var(--color-gray-700); + --text-tertiary: var(--color-gray-600); + --text-quaternary: var(--color-gray-550); + --text-placeholder: var(--color-gray-550); + --text-secondary_on-brand: var(--color-white); + --text-quaternary_on-brand: var(--color-white); + --text-brand-primary: var(--color-blue-500); + --text-brand-secondary: var(--color-blue-700); + --text-brand-secondary_hover: var(--color-blue-600); + --text-error-primary: var(--color-red-600); + --text-success-primary: var(--color-green-600); + --fg-primary: var(--color-purple-800); + --fg-secondary: var(--color-purple-800); + --fg-secondary_hover: var(--color-purple-800); + --fg-tertiary: var(--color-gray-500); + --fg-quaternary: var(--color-purple-800); + --fg-white: var(--color-white); + --fg-brand-primary: var(--color-blue-500); + --fg-error-primary: var(--color-red-500); + --fg-success-primary: var(--color-green-500); + --fg-success-secondary: var(--color-green-400); + --fg-warning-primary: var(--color-yellow-700); + --border-primary: var(--color-gray-600); + --border-secondary: var(--color-gray-500); + --border-secondary_alt: var(--color-gray-200); + --border-tertiary: var(--color-gray-300); + --border-brand: var(--color-blue-500); + --border-brand_alt: var(--color-blue-300); + --border-error: var(--color-red-500); + --border-error_subtle: var(--color-red-300); +} diff --git a/packages/design-tokens/src/js/semanticColorTokens.ts b/packages/design-tokens/src/js/semanticColorTokens.ts index cc8fff12893..982549905db 100644 --- a/packages/design-tokens/src/js/semanticColorTokens.ts +++ b/packages/design-tokens/src/js/semanticColorTokens.ts @@ -141,6 +141,17 @@ export const flatSemanticColorTokens = { ...semanticColorTokens.border, } satisfies Record +/** + * The `:root` body lines defining every mapped semantic colour token as a CSS + * custom property, e.g. ` --bg-primary: var(--color-white);`. Null (unmapped) + * tokens are skipped. Shared by the build scripts so the block emitted into + * `variables.css` and the standalone `semantic-color.css` can never drift. + */ +export const semanticColorCssVariableLines = (): string[] => + Object.entries(flatSemanticColorTokens) + .filter((entry): entry is [string, string] => entry[1] !== null) + .map(([key, value]) => ` --${key}: ${value};`) + /** Union of every canonical semantic colour token name. */ export type SemanticColorTokenName = keyof typeof flatSemanticColorTokens From 8ec754e6024129d7e34a2582e3de8f83e283c67d Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Wed, 1 Jul 2026 13:25:13 +1000 Subject: [PATCH 18/25] docs(tailwind): use semantic colours in guides, drop primitive examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Overview: replace the blue-400 anatomy diagram + CSS block with an inline modifier/prefix/suffix breakdown using a semantic example (hover:bg-brand-solid) and a note preferring semantic tokens over primitives; remove the now-unused tw-anatomy.png asset. - Utility Class References (Background/Text/Border Color): source the class list from the semantic-only extend.{backgroundColor,textColor,borderColor} maps instead of the primitive-laden colors/borderColor, so the pages list only semantic classes (bg-primary, bg-brand-solid, text-brand-secondary, border-brand…). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../tailwind/src/_docs/assets/tw-anatomy.png | Bin 55450 -> 0 bytes .../backgrounds/background-color.stories.tsx | 2 +- .../pages/borders/border-color.stories.tsx | 2 +- packages/tailwind/src/_docs/pages/overview.mdx | 15 ++++++--------- .../pages/typography/text-color.stories.tsx | 2 +- 5 files changed, 9 insertions(+), 12 deletions(-) delete mode 100644 packages/tailwind/src/_docs/assets/tw-anatomy.png diff --git a/packages/tailwind/src/_docs/assets/tw-anatomy.png b/packages/tailwind/src/_docs/assets/tw-anatomy.png deleted file mode 100644 index e24a96e2f8f8a3b625e964c371587a05ee9d38dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55450 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Æ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 B3LXFe diff --git a/packages/tailwind/src/_docs/pages/backgrounds/background-color.stories.tsx b/packages/tailwind/src/_docs/pages/backgrounds/background-color.stories.tsx index d2411045b89..957a012f415 100644 --- a/packages/tailwind/src/_docs/pages/backgrounds/background-color.stories.tsx +++ b/packages/tailwind/src/_docs/pages/backgrounds/background-color.stories.tsx @@ -7,7 +7,7 @@ import { utilityDescription } from '~tailwind/_docs/utils/utilityDescription' import { kaizenTailwindTheme } from '~tailwind/tailwind-presets' const prefix = 'bg-' -const classEntries = flattenEntries(prefix, kaizenTailwindTheme.colors ?? {}) +const classEntries = flattenEntries(prefix, kaizenTailwindTheme.extend?.backgroundColor ?? {}) export default { title: 'Guides/Tailwind/Utility Class References/Backgrounds/Background Color', diff --git a/packages/tailwind/src/_docs/pages/borders/border-color.stories.tsx b/packages/tailwind/src/_docs/pages/borders/border-color.stories.tsx index 93d919ce2bd..63ce633960b 100644 --- a/packages/tailwind/src/_docs/pages/borders/border-color.stories.tsx +++ b/packages/tailwind/src/_docs/pages/borders/border-color.stories.tsx @@ -7,7 +7,7 @@ import { utilityDescription } from '~tailwind/_docs/utils/utilityDescription' import { kaizenTailwindTheme } from '~tailwind/tailwind-presets' const prefix = 'border-' -const classEntries = flattenEntries(prefix, kaizenTailwindTheme.borderColor ?? {}) +const classEntries = flattenEntries(prefix, kaizenTailwindTheme.extend?.borderColor ?? {}) export default { title: 'Guides/Tailwind/Utility Class References/Borders/Border Color', diff --git a/packages/tailwind/src/_docs/pages/overview.mdx b/packages/tailwind/src/_docs/pages/overview.mdx index 3442e3b6d55..4d3bce831dd 100644 --- a/packages/tailwind/src/_docs/pages/overview.mdx +++ b/packages/tailwind/src/_docs/pages/overview.mdx @@ -1,5 +1,4 @@ import { Meta } from '@storybook/blocks' -import AnatomyDiagram from '../assets/tw-anatomy.png' @@ -11,13 +10,11 @@ import AnatomyDiagram from '../assets/tw-anatomy.png' The `@kaizen/tailwind` package is essentially a custom Tailwind preset. For more information about Tailwind presets, see their docs [here](https://tailwindcss.com/docs/presets). This package does not change how Tailwind works; it only defines the suffixes that can be applied when constructing utility classes. To see a list of utilities generated by our preset, see our [Utility Class Reference Docs](/docs/guides-tailwind-utility-class-references-overview--docs). -The following diagram shows the construction of a utility class that adds a background of `blue-400` on hover. The modifier `hover:` and the prefix `bg-` are part of Tailwind by default. The suffix `blue-400` is defined by our preset, and represents one of our color design tokens. -Tailwind utility class anatomy +A utility class is constructed from up to three parts. Take `hover:bg-brand-solid`, which applies our brand background colour on hover: -```css -.hover\:bg-blue-400:hover { - --tw-bg-opacity: 1; - background-color: rgb(0 139 214 / var(--tw-bg-opacity)); -} -``` +- **Modifier** — `hover:` (part of Tailwind by default) +- **Prefix** — `bg-` (part of Tailwind by default) +- **Suffix** — `brand-solid` (defined by our preset, and one of our semantic colour design tokens) + +Prefer our semantic colour tokens — e.g. `bg-brand-solid`, `text-brand-secondary`, `border-brand` — over raw primitives like `blue-500`. Semantic tokens describe intent rather than a specific hue, so they stay correct as the palette evolves. diff --git a/packages/tailwind/src/_docs/pages/typography/text-color.stories.tsx b/packages/tailwind/src/_docs/pages/typography/text-color.stories.tsx index ba42a3f07e5..61cfd34176f 100644 --- a/packages/tailwind/src/_docs/pages/typography/text-color.stories.tsx +++ b/packages/tailwind/src/_docs/pages/typography/text-color.stories.tsx @@ -7,7 +7,7 @@ import { utilityDescription } from '~tailwind/_docs/utils/utilityDescription' import { kaizenTailwindTheme } from '~tailwind/tailwind-presets' const prefix = 'text-' -const classEntries = flattenEntries(prefix, kaizenTailwindTheme.colors ?? {}) +const classEntries = flattenEntries(prefix, kaizenTailwindTheme.extend?.textColor ?? {}) export default { title: 'Guides/Tailwind/Utility Class References/Typography/Text Color', From 195ad3be8dd869105b62b8ecfd246e069df467d9 Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Wed, 1 Jul 2026 15:14:18 +1000 Subject: [PATCH 19/25] fix(design-tokens): satisfy eslint and prettier in colour token docs Fix the three eslint errors in color-tokens.tsx that broke CI: import order (semanticColorTokens before tokens), prefer-regexp-exec over String#match, and array-type (T[] over Array). Also run prettier over buildSemanticTokens.ts and tailwind-presets.ts. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/design-tokens/_docs/pages/color-tokens.tsx | 6 +++--- packages/design-tokens/bin/buildSemanticTokens.ts | 5 +---- packages/tailwind/src/tailwind-presets.ts | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/design-tokens/_docs/pages/color-tokens.tsx b/packages/design-tokens/_docs/pages/color-tokens.tsx index 1b81b770d37..24c5c803532 100644 --- a/packages/design-tokens/_docs/pages/color-tokens.tsx +++ b/packages/design-tokens/_docs/pages/color-tokens.tsx @@ -1,10 +1,10 @@ import React from 'react' import { Heading } from '~components/Heading' -import { tokens, semanticColorTokens } from '~design-tokens/js' +import { semanticColorTokens, tokens } from '~design-tokens/js' /** Pull the primitive name out of a semantic value, e.g. `var(--color-blue-500)` → `color-blue-500`. */ const primitiveFromValue = (value: string): string | null => - value.match(/var\(--(.+?)\)/)?.[1] ?? null + /var\(--(.+?)\)/.exec(value)?.[1] ?? null /** Resolve a primitive CSS-var name (`color-blue-500`, `color-white`) to its hex value. */ const primitiveHex = (primitiveName: string): string | null => { @@ -112,7 +112,7 @@ export const ColorTokensDemo = (): JSX.Element => ( gap: tokens.spacing[32], }} > - {(Object.keys(semanticColorTokens) as Array).map((group) => ( + {(Object.keys(semanticColorTokens) as (keyof typeof semanticColorTokens)[]).map((group) => (
, prefix: string): Reco * so strip those entries before spreading into `colors` / `borderColor`. */ function stripNulls>( - group: T + group: T, ): { [K in keyof T]: Exclude } { const result: Record = {} for (const [key, value] of Object.entries(group)) { From 29edd73fc065e0e9685df59aa7d20fbffd905519 Mon Sep 17 00:00:00 2001 From: Kitty Allen Date: Wed, 1 Jul 2026 15:23:48 +1000 Subject: [PATCH 20/25] fix(design-tokens): keep semantic colour tokens out of primitive color output Semantic tokens are merged into `tokens.color` for the JS export and Tailwind preset, but they leaked into the primitive `color.json` and therefore the generated `sass/color.scss` and `less/color.less`, surfacing as `$color-bg-*` entries that reference an undefined `--color-bg-*` variable (the canonical one is `--bg-*`, emitted separately by build:semantic). Strip semantic keys (both kebab and camelCase forms) before writing `color.json`, and regenerate the SCSS and LESS artifacts. Fixes the sass-tokens heart-colour-names unit test. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../design-tokens/bin/buildCssVarTokens.ts | 22 +- packages/design-tokens/less/color.less | 204 ----------------- packages/design-tokens/sass/color.scss | 204 ----------------- packages/design-tokens/tokens/color.json | 206 +----------------- 4 files changed, 22 insertions(+), 614 deletions(-) diff --git a/packages/design-tokens/bin/buildCssVarTokens.ts b/packages/design-tokens/bin/buildCssVarTokens.ts index d33a3cd6409..a87bd8bf8ca 100644 --- a/packages/design-tokens/bin/buildCssVarTokens.ts +++ b/packages/design-tokens/bin/buildCssVarTokens.ts @@ -14,6 +14,26 @@ const CSS_OUTPUT_DIR = `${process.cwd()}/css` const formatJson = (jsonString: string): Promise => format(jsonString, { parser: 'json' }) +/** + * Semantic colour tokens are merged into `tokens.color` for the JS export and + * Tailwind preset, but they are emitted as CSS variables separately (see + * `semanticColorCssVariableLines` / `build:semantic`) under their canonical + * names — `--bg-*`, `--text-*`, `--fg-*`, `--border-*`. + * + * They must NOT leak into the primitive `color.json`, because `build:sass` / + * `build:less` would then generate `$color-bg-*` entries referencing an + * undefined `--color-bg-*` variable (the real one is `--bg-*`). + * + * Tokens are merged under both their kebab (`bg-primary`) and camelCase + * (`bgPrimary`) forms, so match both — the camel form is kebab-cased back to + * `$color-bg-*` by `json-to-flat-sass`. + */ +const SEMANTIC_COLOR_KEY_PATTERN = /^(bg|text|fg|border)(-|[A-Z])/ +const stripSemanticColorKeys = >(color: T): T => + Object.fromEntries( + Object.entries(color).filter(([key]) => !SEMANTIC_COLOR_KEY_PATTERN.test(key)), + ) as T + const run = async (): Promise => { fs.mkdirSync(JSON_OUTPUT_DIR, { recursive: true }) fs.mkdirSync(CSS_OUTPUT_DIR, { recursive: true }) @@ -73,7 +93,7 @@ const run = async (): Promise => { await formatJson( JSON.stringify({ dataViz: augmentedThemeWithCSSVariableValuesVersion.dataViz, - color: augmentedThemeWithCSSVariableValuesVersion.color, + color: stripSemanticColorKeys(augmentedThemeWithCSSVariableValuesVersion.color), }), ), ) diff --git a/packages/design-tokens/less/color.less b/packages/design-tokens/less/color.less index 0a0a1c52809..0137b56c626 100644 --- a/packages/design-tokens/less/color.less +++ b/packages/design-tokens/less/color.less @@ -220,207 +220,3 @@ @color-black-rgb: var(--color-black-rgb, 0, 0, 0); @color-black-rgb-id: --color-black-rgb; @color-black-id: --color-black; -@color-bg-primary: var(--color-bg-primary, var(--color-white)); -@color-bg-primary-id: --color-bg-primary; -@color-bg-secondary: var(--color-bg-secondary, var(--color-gray-200)); -@color-bg-secondary-id: --color-bg-secondary; -@color-bg-secondary-hover: var(--color-bg-secondary-hover, var(--color-gray-200)); -@color-bg-secondary-hover-id: --color-bg-secondary-hover; -@color-bg-tertiary: var(--color-bg-tertiary, var(--color-gray-300)); -@color-bg-tertiary-id: --color-bg-tertiary; -@color-bg-primary-solid: var(--color-bg-primary-solid, var(--color-purple-800)); -@color-bg-primary-solid-id: --color-bg-primary-solid; -@color-bg-secondary-solid: var(--color-bg-secondary-solid, var(--color-gray-600)); -@color-bg-secondary-solid-id: --color-bg-secondary-solid; -@color-bg-overlay: var(--color-bg-overlay, var(--color-white)); -@color-bg-overlay-id: --color-bg-overlay; -@color-bg-brand-primary: var(--color-bg-brand-primary, var(--color-blue-100)); -@color-bg-brand-primary-id: --color-bg-brand-primary; -@color-bg-brand-secondary: var(--color-bg-brand-secondary, var(--color-blue-200)); -@color-bg-brand-secondary-id: --color-bg-brand-secondary; -@color-bg-brand-solid: var(--color-bg-brand-solid, var(--color-blue-500)); -@color-bg-brand-solid-id: --color-bg-brand-solid; -@color-bg-brand-solid-hover: var(--color-bg-brand-solid-hover, var(--color-blue-700)); -@color-bg-brand-solid-hover-id: --color-bg-brand-solid-hover; -@color-bg-error-primary: var(--color-bg-error-primary, var(--color-red-100)); -@color-bg-error-primary-id: --color-bg-error-primary; -@color-bg-error-secondary: var(--color-bg-error-secondary, var(--color-red-300)); -@color-bg-error-secondary-id: --color-bg-error-secondary; -@color-bg-error-solid: var(--color-bg-error-solid, var(--color-red-400)); -@color-bg-error-solid-id: --color-bg-error-solid; -@color-bg-success-primary: var(--color-bg-success-primary, var(--color-green-100)); -@color-bg-success-primary-id: --color-bg-success-primary; -@color-bg-success-secondary: var(--color-bg-success-secondary, var(--color-green-300)); -@color-bg-success-secondary-id: --color-bg-success-secondary; -@color-bg-success-solid: var(--color-bg-success-solid, var(--color-green-600)); -@color-bg-success-solid-id: --color-bg-success-solid; -@color-bg-warning-primary: var(--color-bg-warning-primary, var(--color-yellow-100)); -@color-bg-warning-primary-id: --color-bg-warning-primary; -@color-bg-warning-secondary: var(--color-bg-warning-secondary, var(--color-yellow-400)); -@color-bg-warning-secondary-id: --color-bg-warning-secondary; -@color-bg-warning-solid: var(--color-bg-warning-solid, var(--color-yellow-400)); -@color-bg-warning-solid-id: --color-bg-warning-solid; -@color-text-primary: var(--color-text-primary, var(--color-purple-800)); -@color-text-primary-id: --color-text-primary; -@color-text-secondary: var(--color-text-secondary, var(--color-gray-700)); -@color-text-secondary-id: --color-text-secondary; -@color-text-tertiary: var(--color-text-tertiary, var(--color-gray-600)); -@color-text-tertiary-id: --color-text-tertiary; -@color-text-quaternary: var(--color-text-quaternary, var(--color-gray-550)); -@color-text-quaternary-id: --color-text-quaternary; -@color-text-placeholder: var(--color-text-placeholder, var(--color-gray-550)); -@color-text-placeholder-id: --color-text-placeholder; -@color-text-secondary-on-brand: var(--color-text-secondary-on-brand, var(--color-white)); -@color-text-secondary-on-brand-id: --color-text-secondary-on-brand; -@color-text-quaternary-on-brand: var(--color-text-quaternary-on-brand, var(--color-white)); -@color-text-quaternary-on-brand-id: --color-text-quaternary-on-brand; -@color-text-brand-primary: var(--color-text-brand-primary, var(--color-blue-500)); -@color-text-brand-primary-id: --color-text-brand-primary; -@color-text-brand-secondary: var(--color-text-brand-secondary, var(--color-blue-700)); -@color-text-brand-secondary-id: --color-text-brand-secondary; -@color-text-brand-secondary-hover: var(--color-text-brand-secondary-hover, var(--color-blue-600)); -@color-text-brand-secondary-hover-id: --color-text-brand-secondary-hover; -@color-text-error-primary: var(--color-text-error-primary, var(--color-red-600)); -@color-text-error-primary-id: --color-text-error-primary; -@color-text-success-primary: var(--color-text-success-primary, var(--color-green-600)); -@color-text-success-primary-id: --color-text-success-primary; -@color-fg-primary: var(--color-fg-primary, var(--color-purple-800)); -@color-fg-primary-id: --color-fg-primary; -@color-fg-secondary: var(--color-fg-secondary, var(--color-purple-800)); -@color-fg-secondary-id: --color-fg-secondary; -@color-fg-secondary-hover: var(--color-fg-secondary-hover, var(--color-purple-800)); -@color-fg-secondary-hover-id: --color-fg-secondary-hover; -@color-fg-tertiary: var(--color-fg-tertiary, var(--color-gray-500)); -@color-fg-tertiary-id: --color-fg-tertiary; -@color-fg-quaternary: var(--color-fg-quaternary, var(--color-purple-800)); -@color-fg-quaternary-id: --color-fg-quaternary; -@color-fg-white: var(--color-fg-white, var(--color-white)); -@color-fg-white-id: --color-fg-white; -@color-fg-brand-primary: var(--color-fg-brand-primary, var(--color-blue-500)); -@color-fg-brand-primary-id: --color-fg-brand-primary; -@color-fg-error-primary: var(--color-fg-error-primary, var(--color-red-500)); -@color-fg-error-primary-id: --color-fg-error-primary; -@color-fg-success-primary: var(--color-fg-success-primary, var(--color-green-500)); -@color-fg-success-primary-id: --color-fg-success-primary; -@color-fg-success-secondary: var(--color-fg-success-secondary, var(--color-green-400)); -@color-fg-success-secondary-id: --color-fg-success-secondary; -@color-fg-warning-primary: var(--color-fg-warning-primary, var(--color-yellow-700)); -@color-fg-warning-primary-id: --color-fg-warning-primary; -@color-border-primary: var(--color-border-primary, var(--color-gray-600)); -@color-border-primary-id: --color-border-primary; -@color-border-secondary: var(--color-border-secondary, var(--color-gray-500)); -@color-border-secondary-id: --color-border-secondary; -@color-border-secondary-alt: var(--color-border-secondary-alt, var(--color-gray-200)); -@color-border-secondary-alt-id: --color-border-secondary-alt; -@color-border-tertiary: var(--color-border-tertiary, var(--color-gray-300)); -@color-border-tertiary-id: --color-border-tertiary; -@color-border-brand: var(--color-border-brand, var(--color-blue-500)); -@color-border-brand-id: --color-border-brand; -@color-border-brand-alt: var(--color-border-brand-alt, var(--color-blue-300)); -@color-border-brand-alt-id: --color-border-brand-alt; -@color-border-error: var(--color-border-error, var(--color-red-500)); -@color-border-error-id: --color-border-error; -@color-border-error-subtle: var(--color-border-error-subtle, var(--color-red-300)); -@color-border-error-subtle-id: --color-border-error-subtle; -@color-bg-primary: var(--color-bg-primary, var(--color-white)); -@color-bg-primary-id: --color-bg-primary; -@color-bg-secondary: var(--color-bg-secondary, var(--color-gray-200)); -@color-bg-secondary-id: --color-bg-secondary; -@color-bg-secondary-hover: var(--color-bg-secondary-hover, var(--color-gray-200)); -@color-bg-secondary-hover-id: --color-bg-secondary-hover; -@color-bg-tertiary: var(--color-bg-tertiary, var(--color-gray-300)); -@color-bg-tertiary-id: --color-bg-tertiary; -@color-bg-primary-solid: var(--color-bg-primary-solid, var(--color-purple-800)); -@color-bg-primary-solid-id: --color-bg-primary-solid; -@color-bg-secondary-solid: var(--color-bg-secondary-solid, var(--color-gray-600)); -@color-bg-secondary-solid-id: --color-bg-secondary-solid; -@color-bg-overlay: var(--color-bg-overlay, var(--color-white)); -@color-bg-overlay-id: --color-bg-overlay; -@color-bg-brand-primary: var(--color-bg-brand-primary, var(--color-blue-100)); -@color-bg-brand-primary-id: --color-bg-brand-primary; -@color-bg-brand-secondary: var(--color-bg-brand-secondary, var(--color-blue-200)); -@color-bg-brand-secondary-id: --color-bg-brand-secondary; -@color-bg-brand-solid: var(--color-bg-brand-solid, var(--color-blue-500)); -@color-bg-brand-solid-id: --color-bg-brand-solid; -@color-bg-brand-solid-hover: var(--color-bg-brand-solid-hover, var(--color-blue-700)); -@color-bg-brand-solid-hover-id: --color-bg-brand-solid-hover; -@color-bg-error-primary: var(--color-bg-error-primary, var(--color-red-100)); -@color-bg-error-primary-id: --color-bg-error-primary; -@color-bg-error-secondary: var(--color-bg-error-secondary, var(--color-red-300)); -@color-bg-error-secondary-id: --color-bg-error-secondary; -@color-bg-error-solid: var(--color-bg-error-solid, var(--color-red-400)); -@color-bg-error-solid-id: --color-bg-error-solid; -@color-bg-success-primary: var(--color-bg-success-primary, var(--color-green-100)); -@color-bg-success-primary-id: --color-bg-success-primary; -@color-bg-success-secondary: var(--color-bg-success-secondary, var(--color-green-300)); -@color-bg-success-secondary-id: --color-bg-success-secondary; -@color-bg-success-solid: var(--color-bg-success-solid, var(--color-green-600)); -@color-bg-success-solid-id: --color-bg-success-solid; -@color-bg-warning-primary: var(--color-bg-warning-primary, var(--color-yellow-100)); -@color-bg-warning-primary-id: --color-bg-warning-primary; -@color-bg-warning-secondary: var(--color-bg-warning-secondary, var(--color-yellow-400)); -@color-bg-warning-secondary-id: --color-bg-warning-secondary; -@color-bg-warning-solid: var(--color-bg-warning-solid, var(--color-yellow-400)); -@color-bg-warning-solid-id: --color-bg-warning-solid; -@color-text-primary: var(--color-text-primary, var(--color-purple-800)); -@color-text-primary-id: --color-text-primary; -@color-text-secondary: var(--color-text-secondary, var(--color-gray-700)); -@color-text-secondary-id: --color-text-secondary; -@color-text-tertiary: var(--color-text-tertiary, var(--color-gray-600)); -@color-text-tertiary-id: --color-text-tertiary; -@color-text-quaternary: var(--color-text-quaternary, var(--color-gray-550)); -@color-text-quaternary-id: --color-text-quaternary; -@color-text-placeholder: var(--color-text-placeholder, var(--color-gray-550)); -@color-text-placeholder-id: --color-text-placeholder; -@color-text-secondary-on-brand: var(--color-text-secondary-on-brand, var(--color-white)); -@color-text-secondary-on-brand-id: --color-text-secondary-on-brand; -@color-text-quaternary-on-brand: var(--color-text-quaternary-on-brand, var(--color-white)); -@color-text-quaternary-on-brand-id: --color-text-quaternary-on-brand; -@color-text-brand-primary: var(--color-text-brand-primary, var(--color-blue-500)); -@color-text-brand-primary-id: --color-text-brand-primary; -@color-text-brand-secondary: var(--color-text-brand-secondary, var(--color-blue-700)); -@color-text-brand-secondary-id: --color-text-brand-secondary; -@color-text-brand-secondary-hover: var(--color-text-brand-secondary-hover, var(--color-blue-600)); -@color-text-brand-secondary-hover-id: --color-text-brand-secondary-hover; -@color-text-error-primary: var(--color-text-error-primary, var(--color-red-600)); -@color-text-error-primary-id: --color-text-error-primary; -@color-text-success-primary: var(--color-text-success-primary, var(--color-green-600)); -@color-text-success-primary-id: --color-text-success-primary; -@color-fg-primary: var(--color-fg-primary, var(--color-purple-800)); -@color-fg-primary-id: --color-fg-primary; -@color-fg-secondary: var(--color-fg-secondary, var(--color-purple-800)); -@color-fg-secondary-id: --color-fg-secondary; -@color-fg-secondary-hover: var(--color-fg-secondary-hover, var(--color-purple-800)); -@color-fg-secondary-hover-id: --color-fg-secondary-hover; -@color-fg-tertiary: var(--color-fg-tertiary, var(--color-gray-500)); -@color-fg-tertiary-id: --color-fg-tertiary; -@color-fg-quaternary: var(--color-fg-quaternary, var(--color-purple-800)); -@color-fg-quaternary-id: --color-fg-quaternary; -@color-fg-white: var(--color-fg-white, var(--color-white)); -@color-fg-white-id: --color-fg-white; -@color-fg-brand-primary: var(--color-fg-brand-primary, var(--color-blue-500)); -@color-fg-brand-primary-id: --color-fg-brand-primary; -@color-fg-error-primary: var(--color-fg-error-primary, var(--color-red-500)); -@color-fg-error-primary-id: --color-fg-error-primary; -@color-fg-success-primary: var(--color-fg-success-primary, var(--color-green-500)); -@color-fg-success-primary-id: --color-fg-success-primary; -@color-fg-success-secondary: var(--color-fg-success-secondary, var(--color-green-400)); -@color-fg-success-secondary-id: --color-fg-success-secondary; -@color-fg-warning-primary: var(--color-fg-warning-primary, var(--color-yellow-700)); -@color-fg-warning-primary-id: --color-fg-warning-primary; -@color-border-primary: var(--color-border-primary, var(--color-gray-600)); -@color-border-primary-id: --color-border-primary; -@color-border-secondary: var(--color-border-secondary, var(--color-gray-500)); -@color-border-secondary-id: --color-border-secondary; -@color-border-secondary-alt: var(--color-border-secondary-alt, var(--color-gray-200)); -@color-border-secondary-alt-id: --color-border-secondary-alt; -@color-border-tertiary: var(--color-border-tertiary, var(--color-gray-300)); -@color-border-tertiary-id: --color-border-tertiary; -@color-border-brand: var(--color-border-brand, var(--color-blue-500)); -@color-border-brand-id: --color-border-brand; -@color-border-brand-alt: var(--color-border-brand-alt, var(--color-blue-300)); -@color-border-brand-alt-id: --color-border-brand-alt; -@color-border-error: var(--color-border-error, var(--color-red-500)); -@color-border-error-id: --color-border-error; -@color-border-error-subtle: var(--color-border-error-subtle, var(--color-red-300)); -@color-border-error-subtle-id: --color-border-error-subtle; diff --git a/packages/design-tokens/sass/color.scss b/packages/design-tokens/sass/color.scss index 91c08ce32b5..1ca178cdeba 100644 --- a/packages/design-tokens/sass/color.scss +++ b/packages/design-tokens/sass/color.scss @@ -220,207 +220,3 @@ $color-black: var(--color-black, #000000); $color-black-rgb: var(--color-black-rgb, 0, 0, 0); $color-black-rgb-id: --color-black-rgb; $color-black-id: --color-black; -$color-bg-primary: var(--color-bg-primary, var(--color-white)); -$color-bg-primary-id: --color-bg-primary; -$color-bg-secondary: var(--color-bg-secondary, var(--color-gray-200)); -$color-bg-secondary-id: --color-bg-secondary; -$color-bg-secondary-hover: var(--color-bg-secondary-hover, var(--color-gray-200)); -$color-bg-secondary-hover-id: --color-bg-secondary-hover; -$color-bg-tertiary: var(--color-bg-tertiary, var(--color-gray-300)); -$color-bg-tertiary-id: --color-bg-tertiary; -$color-bg-primary-solid: var(--color-bg-primary-solid, var(--color-purple-800)); -$color-bg-primary-solid-id: --color-bg-primary-solid; -$color-bg-secondary-solid: var(--color-bg-secondary-solid, var(--color-gray-600)); -$color-bg-secondary-solid-id: --color-bg-secondary-solid; -$color-bg-overlay: var(--color-bg-overlay, var(--color-white)); -$color-bg-overlay-id: --color-bg-overlay; -$color-bg-brand-primary: var(--color-bg-brand-primary, var(--color-blue-100)); -$color-bg-brand-primary-id: --color-bg-brand-primary; -$color-bg-brand-secondary: var(--color-bg-brand-secondary, var(--color-blue-200)); -$color-bg-brand-secondary-id: --color-bg-brand-secondary; -$color-bg-brand-solid: var(--color-bg-brand-solid, var(--color-blue-500)); -$color-bg-brand-solid-id: --color-bg-brand-solid; -$color-bg-brand-solid-hover: var(--color-bg-brand-solid-hover, var(--color-blue-700)); -$color-bg-brand-solid-hover-id: --color-bg-brand-solid-hover; -$color-bg-error-primary: var(--color-bg-error-primary, var(--color-red-100)); -$color-bg-error-primary-id: --color-bg-error-primary; -$color-bg-error-secondary: var(--color-bg-error-secondary, var(--color-red-300)); -$color-bg-error-secondary-id: --color-bg-error-secondary; -$color-bg-error-solid: var(--color-bg-error-solid, var(--color-red-400)); -$color-bg-error-solid-id: --color-bg-error-solid; -$color-bg-success-primary: var(--color-bg-success-primary, var(--color-green-100)); -$color-bg-success-primary-id: --color-bg-success-primary; -$color-bg-success-secondary: var(--color-bg-success-secondary, var(--color-green-300)); -$color-bg-success-secondary-id: --color-bg-success-secondary; -$color-bg-success-solid: var(--color-bg-success-solid, var(--color-green-600)); -$color-bg-success-solid-id: --color-bg-success-solid; -$color-bg-warning-primary: var(--color-bg-warning-primary, var(--color-yellow-100)); -$color-bg-warning-primary-id: --color-bg-warning-primary; -$color-bg-warning-secondary: var(--color-bg-warning-secondary, var(--color-yellow-400)); -$color-bg-warning-secondary-id: --color-bg-warning-secondary; -$color-bg-warning-solid: var(--color-bg-warning-solid, var(--color-yellow-400)); -$color-bg-warning-solid-id: --color-bg-warning-solid; -$color-text-primary: var(--color-text-primary, var(--color-purple-800)); -$color-text-primary-id: --color-text-primary; -$color-text-secondary: var(--color-text-secondary, var(--color-gray-700)); -$color-text-secondary-id: --color-text-secondary; -$color-text-tertiary: var(--color-text-tertiary, var(--color-gray-600)); -$color-text-tertiary-id: --color-text-tertiary; -$color-text-quaternary: var(--color-text-quaternary, var(--color-gray-550)); -$color-text-quaternary-id: --color-text-quaternary; -$color-text-placeholder: var(--color-text-placeholder, var(--color-gray-550)); -$color-text-placeholder-id: --color-text-placeholder; -$color-text-secondary-on-brand: var(--color-text-secondary-on-brand, var(--color-white)); -$color-text-secondary-on-brand-id: --color-text-secondary-on-brand; -$color-text-quaternary-on-brand: var(--color-text-quaternary-on-brand, var(--color-white)); -$color-text-quaternary-on-brand-id: --color-text-quaternary-on-brand; -$color-text-brand-primary: var(--color-text-brand-primary, var(--color-blue-500)); -$color-text-brand-primary-id: --color-text-brand-primary; -$color-text-brand-secondary: var(--color-text-brand-secondary, var(--color-blue-700)); -$color-text-brand-secondary-id: --color-text-brand-secondary; -$color-text-brand-secondary-hover: var(--color-text-brand-secondary-hover, var(--color-blue-600)); -$color-text-brand-secondary-hover-id: --color-text-brand-secondary-hover; -$color-text-error-primary: var(--color-text-error-primary, var(--color-red-600)); -$color-text-error-primary-id: --color-text-error-primary; -$color-text-success-primary: var(--color-text-success-primary, var(--color-green-600)); -$color-text-success-primary-id: --color-text-success-primary; -$color-fg-primary: var(--color-fg-primary, var(--color-purple-800)); -$color-fg-primary-id: --color-fg-primary; -$color-fg-secondary: var(--color-fg-secondary, var(--color-purple-800)); -$color-fg-secondary-id: --color-fg-secondary; -$color-fg-secondary-hover: var(--color-fg-secondary-hover, var(--color-purple-800)); -$color-fg-secondary-hover-id: --color-fg-secondary-hover; -$color-fg-tertiary: var(--color-fg-tertiary, var(--color-gray-500)); -$color-fg-tertiary-id: --color-fg-tertiary; -$color-fg-quaternary: var(--color-fg-quaternary, var(--color-purple-800)); -$color-fg-quaternary-id: --color-fg-quaternary; -$color-fg-white: var(--color-fg-white, var(--color-white)); -$color-fg-white-id: --color-fg-white; -$color-fg-brand-primary: var(--color-fg-brand-primary, var(--color-blue-500)); -$color-fg-brand-primary-id: --color-fg-brand-primary; -$color-fg-error-primary: var(--color-fg-error-primary, var(--color-red-500)); -$color-fg-error-primary-id: --color-fg-error-primary; -$color-fg-success-primary: var(--color-fg-success-primary, var(--color-green-500)); -$color-fg-success-primary-id: --color-fg-success-primary; -$color-fg-success-secondary: var(--color-fg-success-secondary, var(--color-green-400)); -$color-fg-success-secondary-id: --color-fg-success-secondary; -$color-fg-warning-primary: var(--color-fg-warning-primary, var(--color-yellow-700)); -$color-fg-warning-primary-id: --color-fg-warning-primary; -$color-border-primary: var(--color-border-primary, var(--color-gray-600)); -$color-border-primary-id: --color-border-primary; -$color-border-secondary: var(--color-border-secondary, var(--color-gray-500)); -$color-border-secondary-id: --color-border-secondary; -$color-border-secondary-alt: var(--color-border-secondary-alt, var(--color-gray-200)); -$color-border-secondary-alt-id: --color-border-secondary-alt; -$color-border-tertiary: var(--color-border-tertiary, var(--color-gray-300)); -$color-border-tertiary-id: --color-border-tertiary; -$color-border-brand: var(--color-border-brand, var(--color-blue-500)); -$color-border-brand-id: --color-border-brand; -$color-border-brand-alt: var(--color-border-brand-alt, var(--color-blue-300)); -$color-border-brand-alt-id: --color-border-brand-alt; -$color-border-error: var(--color-border-error, var(--color-red-500)); -$color-border-error-id: --color-border-error; -$color-border-error-subtle: var(--color-border-error-subtle, var(--color-red-300)); -$color-border-error-subtle-id: --color-border-error-subtle; -$color-bg-primary: var(--color-bg-primary, var(--color-white)); -$color-bg-primary-id: --color-bg-primary; -$color-bg-secondary: var(--color-bg-secondary, var(--color-gray-200)); -$color-bg-secondary-id: --color-bg-secondary; -$color-bg-secondary-hover: var(--color-bg-secondary-hover, var(--color-gray-200)); -$color-bg-secondary-hover-id: --color-bg-secondary-hover; -$color-bg-tertiary: var(--color-bg-tertiary, var(--color-gray-300)); -$color-bg-tertiary-id: --color-bg-tertiary; -$color-bg-primary-solid: var(--color-bg-primary-solid, var(--color-purple-800)); -$color-bg-primary-solid-id: --color-bg-primary-solid; -$color-bg-secondary-solid: var(--color-bg-secondary-solid, var(--color-gray-600)); -$color-bg-secondary-solid-id: --color-bg-secondary-solid; -$color-bg-overlay: var(--color-bg-overlay, var(--color-white)); -$color-bg-overlay-id: --color-bg-overlay; -$color-bg-brand-primary: var(--color-bg-brand-primary, var(--color-blue-100)); -$color-bg-brand-primary-id: --color-bg-brand-primary; -$color-bg-brand-secondary: var(--color-bg-brand-secondary, var(--color-blue-200)); -$color-bg-brand-secondary-id: --color-bg-brand-secondary; -$color-bg-brand-solid: var(--color-bg-brand-solid, var(--color-blue-500)); -$color-bg-brand-solid-id: --color-bg-brand-solid; -$color-bg-brand-solid-hover: var(--color-bg-brand-solid-hover, var(--color-blue-700)); -$color-bg-brand-solid-hover-id: --color-bg-brand-solid-hover; -$color-bg-error-primary: var(--color-bg-error-primary, var(--color-red-100)); -$color-bg-error-primary-id: --color-bg-error-primary; -$color-bg-error-secondary: var(--color-bg-error-secondary, var(--color-red-300)); -$color-bg-error-secondary-id: --color-bg-error-secondary; -$color-bg-error-solid: var(--color-bg-error-solid, var(--color-red-400)); -$color-bg-error-solid-id: --color-bg-error-solid; -$color-bg-success-primary: var(--color-bg-success-primary, var(--color-green-100)); -$color-bg-success-primary-id: --color-bg-success-primary; -$color-bg-success-secondary: var(--color-bg-success-secondary, var(--color-green-300)); -$color-bg-success-secondary-id: --color-bg-success-secondary; -$color-bg-success-solid: var(--color-bg-success-solid, var(--color-green-600)); -$color-bg-success-solid-id: --color-bg-success-solid; -$color-bg-warning-primary: var(--color-bg-warning-primary, var(--color-yellow-100)); -$color-bg-warning-primary-id: --color-bg-warning-primary; -$color-bg-warning-secondary: var(--color-bg-warning-secondary, var(--color-yellow-400)); -$color-bg-warning-secondary-id: --color-bg-warning-secondary; -$color-bg-warning-solid: var(--color-bg-warning-solid, var(--color-yellow-400)); -$color-bg-warning-solid-id: --color-bg-warning-solid; -$color-text-primary: var(--color-text-primary, var(--color-purple-800)); -$color-text-primary-id: --color-text-primary; -$color-text-secondary: var(--color-text-secondary, var(--color-gray-700)); -$color-text-secondary-id: --color-text-secondary; -$color-text-tertiary: var(--color-text-tertiary, var(--color-gray-600)); -$color-text-tertiary-id: --color-text-tertiary; -$color-text-quaternary: var(--color-text-quaternary, var(--color-gray-550)); -$color-text-quaternary-id: --color-text-quaternary; -$color-text-placeholder: var(--color-text-placeholder, var(--color-gray-550)); -$color-text-placeholder-id: --color-text-placeholder; -$color-text-secondary-on-brand: var(--color-text-secondary-on-brand, var(--color-white)); -$color-text-secondary-on-brand-id: --color-text-secondary-on-brand; -$color-text-quaternary-on-brand: var(--color-text-quaternary-on-brand, var(--color-white)); -$color-text-quaternary-on-brand-id: --color-text-quaternary-on-brand; -$color-text-brand-primary: var(--color-text-brand-primary, var(--color-blue-500)); -$color-text-brand-primary-id: --color-text-brand-primary; -$color-text-brand-secondary: var(--color-text-brand-secondary, var(--color-blue-700)); -$color-text-brand-secondary-id: --color-text-brand-secondary; -$color-text-brand-secondary-hover: var(--color-text-brand-secondary-hover, var(--color-blue-600)); -$color-text-brand-secondary-hover-id: --color-text-brand-secondary-hover; -$color-text-error-primary: var(--color-text-error-primary, var(--color-red-600)); -$color-text-error-primary-id: --color-text-error-primary; -$color-text-success-primary: var(--color-text-success-primary, var(--color-green-600)); -$color-text-success-primary-id: --color-text-success-primary; -$color-fg-primary: var(--color-fg-primary, var(--color-purple-800)); -$color-fg-primary-id: --color-fg-primary; -$color-fg-secondary: var(--color-fg-secondary, var(--color-purple-800)); -$color-fg-secondary-id: --color-fg-secondary; -$color-fg-secondary-hover: var(--color-fg-secondary-hover, var(--color-purple-800)); -$color-fg-secondary-hover-id: --color-fg-secondary-hover; -$color-fg-tertiary: var(--color-fg-tertiary, var(--color-gray-500)); -$color-fg-tertiary-id: --color-fg-tertiary; -$color-fg-quaternary: var(--color-fg-quaternary, var(--color-purple-800)); -$color-fg-quaternary-id: --color-fg-quaternary; -$color-fg-white: var(--color-fg-white, var(--color-white)); -$color-fg-white-id: --color-fg-white; -$color-fg-brand-primary: var(--color-fg-brand-primary, var(--color-blue-500)); -$color-fg-brand-primary-id: --color-fg-brand-primary; -$color-fg-error-primary: var(--color-fg-error-primary, var(--color-red-500)); -$color-fg-error-primary-id: --color-fg-error-primary; -$color-fg-success-primary: var(--color-fg-success-primary, var(--color-green-500)); -$color-fg-success-primary-id: --color-fg-success-primary; -$color-fg-success-secondary: var(--color-fg-success-secondary, var(--color-green-400)); -$color-fg-success-secondary-id: --color-fg-success-secondary; -$color-fg-warning-primary: var(--color-fg-warning-primary, var(--color-yellow-700)); -$color-fg-warning-primary-id: --color-fg-warning-primary; -$color-border-primary: var(--color-border-primary, var(--color-gray-600)); -$color-border-primary-id: --color-border-primary; -$color-border-secondary: var(--color-border-secondary, var(--color-gray-500)); -$color-border-secondary-id: --color-border-secondary; -$color-border-secondary-alt: var(--color-border-secondary-alt, var(--color-gray-200)); -$color-border-secondary-alt-id: --color-border-secondary-alt; -$color-border-tertiary: var(--color-border-tertiary, var(--color-gray-300)); -$color-border-tertiary-id: --color-border-tertiary; -$color-border-brand: var(--color-border-brand, var(--color-blue-500)); -$color-border-brand-id: --color-border-brand; -$color-border-brand-alt: var(--color-border-brand-alt, var(--color-blue-300)); -$color-border-brand-alt-id: --color-border-brand-alt; -$color-border-error: var(--color-border-error, var(--color-red-500)); -$color-border-error-id: --color-border-error; -$color-border-error-subtle: var(--color-border-error-subtle, var(--color-red-300)); -$color-border-error-subtle-id: --color-border-error-subtle; diff --git a/packages/design-tokens/tokens/color.json b/packages/design-tokens/tokens/color.json index 7d24b2bd49e..0f4ff331e4f 100644 --- a/packages/design-tokens/tokens/color.json +++ b/packages/design-tokens/tokens/color.json @@ -235,210 +235,6 @@ "black": "var(--color-black, #000000)", "black-rgb": "var(--color-black-rgb, 0, 0, 0)", "black-rgb-id": "--color-black-rgb", - "black-id": "--color-black", - "bg-primary": "var(--color-bg-primary, var(--color-white))", - "bg-primary-id": "--color-bg-primary", - "bg-secondary": "var(--color-bg-secondary, var(--color-gray-200))", - "bg-secondary-id": "--color-bg-secondary", - "bg-secondary_hover": "var(--color-bg-secondary-hover, var(--color-gray-200))", - "bg-secondary_hover-id": "--color-bg-secondary-hover", - "bg-tertiary": "var(--color-bg-tertiary, var(--color-gray-300))", - "bg-tertiary-id": "--color-bg-tertiary", - "bg-primary-solid": "var(--color-bg-primary-solid, var(--color-purple-800))", - "bg-primary-solid-id": "--color-bg-primary-solid", - "bg-secondary-solid": "var(--color-bg-secondary-solid, var(--color-gray-600))", - "bg-secondary-solid-id": "--color-bg-secondary-solid", - "bg-overlay": "var(--color-bg-overlay, var(--color-white))", - "bg-overlay-id": "--color-bg-overlay", - "bg-brand-primary": "var(--color-bg-brand-primary, var(--color-blue-100))", - "bg-brand-primary-id": "--color-bg-brand-primary", - "bg-brand-secondary": "var(--color-bg-brand-secondary, var(--color-blue-200))", - "bg-brand-secondary-id": "--color-bg-brand-secondary", - "bg-brand-solid": "var(--color-bg-brand-solid, var(--color-blue-500))", - "bg-brand-solid-id": "--color-bg-brand-solid", - "bg-brand-solid_hover": "var(--color-bg-brand-solid-hover, var(--color-blue-700))", - "bg-brand-solid_hover-id": "--color-bg-brand-solid-hover", - "bg-error-primary": "var(--color-bg-error-primary, var(--color-red-100))", - "bg-error-primary-id": "--color-bg-error-primary", - "bg-error-secondary": "var(--color-bg-error-secondary, var(--color-red-300))", - "bg-error-secondary-id": "--color-bg-error-secondary", - "bg-error-solid": "var(--color-bg-error-solid, var(--color-red-400))", - "bg-error-solid-id": "--color-bg-error-solid", - "bg-success-primary": "var(--color-bg-success-primary, var(--color-green-100))", - "bg-success-primary-id": "--color-bg-success-primary", - "bg-success-secondary": "var(--color-bg-success-secondary, var(--color-green-300))", - "bg-success-secondary-id": "--color-bg-success-secondary", - "bg-success-solid": "var(--color-bg-success-solid, var(--color-green-600))", - "bg-success-solid-id": "--color-bg-success-solid", - "bg-warning-primary": "var(--color-bg-warning-primary, var(--color-yellow-100))", - "bg-warning-primary-id": "--color-bg-warning-primary", - "bg-warning-secondary": "var(--color-bg-warning-secondary, var(--color-yellow-400))", - "bg-warning-secondary-id": "--color-bg-warning-secondary", - "bg-warning-solid": "var(--color-bg-warning-solid, var(--color-yellow-400))", - "bg-warning-solid-id": "--color-bg-warning-solid", - "text-primary": "var(--color-text-primary, var(--color-purple-800))", - "text-primary-id": "--color-text-primary", - "text-secondary": "var(--color-text-secondary, var(--color-gray-700))", - "text-secondary-id": "--color-text-secondary", - "text-tertiary": "var(--color-text-tertiary, var(--color-gray-600))", - "text-tertiary-id": "--color-text-tertiary", - "text-quaternary": "var(--color-text-quaternary, var(--color-gray-550))", - "text-quaternary-id": "--color-text-quaternary", - "text-placeholder": "var(--color-text-placeholder, var(--color-gray-550))", - "text-placeholder-id": "--color-text-placeholder", - "text-secondary_on-brand": "var(--color-text-secondary-on-brand, var(--color-white))", - "text-secondary_on-brand-id": "--color-text-secondary-on-brand", - "text-quaternary_on-brand": "var(--color-text-quaternary-on-brand, var(--color-white))", - "text-quaternary_on-brand-id": "--color-text-quaternary-on-brand", - "text-brand-primary": "var(--color-text-brand-primary, var(--color-blue-500))", - "text-brand-primary-id": "--color-text-brand-primary", - "text-brand-secondary": "var(--color-text-brand-secondary, var(--color-blue-700))", - "text-brand-secondary-id": "--color-text-brand-secondary", - "text-brand-secondary_hover": "var(--color-text-brand-secondary-hover, var(--color-blue-600))", - "text-brand-secondary_hover-id": "--color-text-brand-secondary-hover", - "text-error-primary": "var(--color-text-error-primary, var(--color-red-600))", - "text-error-primary-id": "--color-text-error-primary", - "text-success-primary": "var(--color-text-success-primary, var(--color-green-600))", - "text-success-primary-id": "--color-text-success-primary", - "fg-primary": "var(--color-fg-primary, var(--color-purple-800))", - "fg-primary-id": "--color-fg-primary", - "fg-secondary": "var(--color-fg-secondary, var(--color-purple-800))", - "fg-secondary-id": "--color-fg-secondary", - "fg-secondary_hover": "var(--color-fg-secondary-hover, var(--color-purple-800))", - "fg-secondary_hover-id": "--color-fg-secondary-hover", - "fg-tertiary": "var(--color-fg-tertiary, var(--color-gray-500))", - "fg-tertiary-id": "--color-fg-tertiary", - "fg-quaternary": "var(--color-fg-quaternary, var(--color-purple-800))", - "fg-quaternary-id": "--color-fg-quaternary", - "fg-white": "var(--color-fg-white, var(--color-white))", - "fg-white-id": "--color-fg-white", - "fg-brand-primary": "var(--color-fg-brand-primary, var(--color-blue-500))", - "fg-brand-primary-id": "--color-fg-brand-primary", - "fg-error-primary": "var(--color-fg-error-primary, var(--color-red-500))", - "fg-error-primary-id": "--color-fg-error-primary", - "fg-success-primary": "var(--color-fg-success-primary, var(--color-green-500))", - "fg-success-primary-id": "--color-fg-success-primary", - "fg-success-secondary": "var(--color-fg-success-secondary, var(--color-green-400))", - "fg-success-secondary-id": "--color-fg-success-secondary", - "fg-warning-primary": "var(--color-fg-warning-primary, var(--color-yellow-700))", - "fg-warning-primary-id": "--color-fg-warning-primary", - "border-primary": "var(--color-border-primary, var(--color-gray-600))", - "border-primary-id": "--color-border-primary", - "border-secondary": "var(--color-border-secondary, var(--color-gray-500))", - "border-secondary-id": "--color-border-secondary", - "border-secondary_alt": "var(--color-border-secondary-alt, var(--color-gray-200))", - "border-secondary_alt-id": "--color-border-secondary-alt", - "border-tertiary": "var(--color-border-tertiary, var(--color-gray-300))", - "border-tertiary-id": "--color-border-tertiary", - "border-brand": "var(--color-border-brand, var(--color-blue-500))", - "border-brand-id": "--color-border-brand", - "border-brand_alt": "var(--color-border-brand-alt, var(--color-blue-300))", - "border-brand_alt-id": "--color-border-brand-alt", - "border-error": "var(--color-border-error, var(--color-red-500))", - "border-error-id": "--color-border-error", - "border-error_subtle": "var(--color-border-error-subtle, var(--color-red-300))", - "border-error_subtle-id": "--color-border-error-subtle", - "bgPrimary": "var(--color-bg-primary, var(--color-white))", - "bgPrimary-id": "--color-bg-primary", - "bgSecondary": "var(--color-bg-secondary, var(--color-gray-200))", - "bgSecondary-id": "--color-bg-secondary", - "bgSecondaryHover": "var(--color-bg-secondary-hover, var(--color-gray-200))", - "bgSecondaryHover-id": "--color-bg-secondary-hover", - "bgTertiary": "var(--color-bg-tertiary, var(--color-gray-300))", - "bgTertiary-id": "--color-bg-tertiary", - "bgPrimarySolid": "var(--color-bg-primary-solid, var(--color-purple-800))", - "bgPrimarySolid-id": "--color-bg-primary-solid", - "bgSecondarySolid": "var(--color-bg-secondary-solid, var(--color-gray-600))", - "bgSecondarySolid-id": "--color-bg-secondary-solid", - "bgOverlay": "var(--color-bg-overlay, var(--color-white))", - "bgOverlay-id": "--color-bg-overlay", - "bgBrandPrimary": "var(--color-bg-brand-primary, var(--color-blue-100))", - "bgBrandPrimary-id": "--color-bg-brand-primary", - "bgBrandSecondary": "var(--color-bg-brand-secondary, var(--color-blue-200))", - "bgBrandSecondary-id": "--color-bg-brand-secondary", - "bgBrandSolid": "var(--color-bg-brand-solid, var(--color-blue-500))", - "bgBrandSolid-id": "--color-bg-brand-solid", - "bgBrandSolidHover": "var(--color-bg-brand-solid-hover, var(--color-blue-700))", - "bgBrandSolidHover-id": "--color-bg-brand-solid-hover", - "bgErrorPrimary": "var(--color-bg-error-primary, var(--color-red-100))", - "bgErrorPrimary-id": "--color-bg-error-primary", - "bgErrorSecondary": "var(--color-bg-error-secondary, var(--color-red-300))", - "bgErrorSecondary-id": "--color-bg-error-secondary", - "bgErrorSolid": "var(--color-bg-error-solid, var(--color-red-400))", - "bgErrorSolid-id": "--color-bg-error-solid", - "bgSuccessPrimary": "var(--color-bg-success-primary, var(--color-green-100))", - "bgSuccessPrimary-id": "--color-bg-success-primary", - "bgSuccessSecondary": "var(--color-bg-success-secondary, var(--color-green-300))", - "bgSuccessSecondary-id": "--color-bg-success-secondary", - "bgSuccessSolid": "var(--color-bg-success-solid, var(--color-green-600))", - "bgSuccessSolid-id": "--color-bg-success-solid", - "bgWarningPrimary": "var(--color-bg-warning-primary, var(--color-yellow-100))", - "bgWarningPrimary-id": "--color-bg-warning-primary", - "bgWarningSecondary": "var(--color-bg-warning-secondary, var(--color-yellow-400))", - "bgWarningSecondary-id": "--color-bg-warning-secondary", - "bgWarningSolid": "var(--color-bg-warning-solid, var(--color-yellow-400))", - "bgWarningSolid-id": "--color-bg-warning-solid", - "textPrimary": "var(--color-text-primary, var(--color-purple-800))", - "textPrimary-id": "--color-text-primary", - "textSecondary": "var(--color-text-secondary, var(--color-gray-700))", - "textSecondary-id": "--color-text-secondary", - "textTertiary": "var(--color-text-tertiary, var(--color-gray-600))", - "textTertiary-id": "--color-text-tertiary", - "textQuaternary": "var(--color-text-quaternary, var(--color-gray-550))", - "textQuaternary-id": "--color-text-quaternary", - "textPlaceholder": "var(--color-text-placeholder, var(--color-gray-550))", - "textPlaceholder-id": "--color-text-placeholder", - "textSecondaryOnBrand": "var(--color-text-secondary-on-brand, var(--color-white))", - "textSecondaryOnBrand-id": "--color-text-secondary-on-brand", - "textQuaternaryOnBrand": "var(--color-text-quaternary-on-brand, var(--color-white))", - "textQuaternaryOnBrand-id": "--color-text-quaternary-on-brand", - "textBrandPrimary": "var(--color-text-brand-primary, var(--color-blue-500))", - "textBrandPrimary-id": "--color-text-brand-primary", - "textBrandSecondary": "var(--color-text-brand-secondary, var(--color-blue-700))", - "textBrandSecondary-id": "--color-text-brand-secondary", - "textBrandSecondaryHover": "var(--color-text-brand-secondary-hover, var(--color-blue-600))", - "textBrandSecondaryHover-id": "--color-text-brand-secondary-hover", - "textErrorPrimary": "var(--color-text-error-primary, var(--color-red-600))", - "textErrorPrimary-id": "--color-text-error-primary", - "textSuccessPrimary": "var(--color-text-success-primary, var(--color-green-600))", - "textSuccessPrimary-id": "--color-text-success-primary", - "fgPrimary": "var(--color-fg-primary, var(--color-purple-800))", - "fgPrimary-id": "--color-fg-primary", - "fgSecondary": "var(--color-fg-secondary, var(--color-purple-800))", - "fgSecondary-id": "--color-fg-secondary", - "fgSecondaryHover": "var(--color-fg-secondary-hover, var(--color-purple-800))", - "fgSecondaryHover-id": "--color-fg-secondary-hover", - "fgTertiary": "var(--color-fg-tertiary, var(--color-gray-500))", - "fgTertiary-id": "--color-fg-tertiary", - "fgQuaternary": "var(--color-fg-quaternary, var(--color-purple-800))", - "fgQuaternary-id": "--color-fg-quaternary", - "fgWhite": "var(--color-fg-white, var(--color-white))", - "fgWhite-id": "--color-fg-white", - "fgBrandPrimary": "var(--color-fg-brand-primary, var(--color-blue-500))", - "fgBrandPrimary-id": "--color-fg-brand-primary", - "fgErrorPrimary": "var(--color-fg-error-primary, var(--color-red-500))", - "fgErrorPrimary-id": "--color-fg-error-primary", - "fgSuccessPrimary": "var(--color-fg-success-primary, var(--color-green-500))", - "fgSuccessPrimary-id": "--color-fg-success-primary", - "fgSuccessSecondary": "var(--color-fg-success-secondary, var(--color-green-400))", - "fgSuccessSecondary-id": "--color-fg-success-secondary", - "fgWarningPrimary": "var(--color-fg-warning-primary, var(--color-yellow-700))", - "fgWarningPrimary-id": "--color-fg-warning-primary", - "borderPrimary": "var(--color-border-primary, var(--color-gray-600))", - "borderPrimary-id": "--color-border-primary", - "borderSecondary": "var(--color-border-secondary, var(--color-gray-500))", - "borderSecondary-id": "--color-border-secondary", - "borderSecondaryAlt": "var(--color-border-secondary-alt, var(--color-gray-200))", - "borderSecondaryAlt-id": "--color-border-secondary-alt", - "borderTertiary": "var(--color-border-tertiary, var(--color-gray-300))", - "borderTertiary-id": "--color-border-tertiary", - "borderBrand": "var(--color-border-brand, var(--color-blue-500))", - "borderBrand-id": "--color-border-brand", - "borderBrandAlt": "var(--color-border-brand-alt, var(--color-blue-300))", - "borderBrandAlt-id": "--color-border-brand-alt", - "borderError": "var(--color-border-error, var(--color-red-500))", - "borderError-id": "--color-border-error", - "borderErrorSubtle": "var(--color-border-error-subtle, var(--color-red-300))", - "borderErrorSubtle-id": "--color-border-error-subtle" + "black-id": "--color-black" } } From 95b9ace233d79bc65f0812d17f71909656926a19 Mon Sep 17 00:00:00 2001 From: AliceMenzie Date: Thu, 2 Jul 2026 13:36:55 +1000 Subject: [PATCH 21/25] initial border skill codemod --- .../skills/semantic-border-migration/SKILL.md | 104 +++++++++++ packages/components/codemods/README.md | 4 + .../README.md | 162 +++++++++++++++++ .../borderColorPostcss.ts | 137 ++++++++++++++ .../borderTokenMap.ts | 95 ++++++++++ .../index.ts | 109 +++++++++++ .../transformCssBorderColors.spec.ts | 58 ++++++ .../transformCssBorderColors.ts | 27 +++ .../transformScssBorderColors.spec.ts | 86 +++++++++ .../transformScssBorderColors.ts | 31 ++++ .../transformTailwindBorderClasses.spec.ts | 52 ++++++ .../transformTailwindBorderClasses.ts | 170 ++++++++++++++++++ 12 files changed, 1035 insertions(+) create mode 100644 .claude/skills/semantic-border-migration/SKILL.md create mode 100644 packages/components/codemods/migrateBorderColorsToSemanticTokens/README.md create mode 100644 packages/components/codemods/migrateBorderColorsToSemanticTokens/borderColorPostcss.ts create mode 100644 packages/components/codemods/migrateBorderColorsToSemanticTokens/borderTokenMap.ts create mode 100644 packages/components/codemods/migrateBorderColorsToSemanticTokens/index.ts create mode 100644 packages/components/codemods/migrateBorderColorsToSemanticTokens/transformCssBorderColors.spec.ts create mode 100644 packages/components/codemods/migrateBorderColorsToSemanticTokens/transformCssBorderColors.ts create mode 100644 packages/components/codemods/migrateBorderColorsToSemanticTokens/transformScssBorderColors.spec.ts create mode 100644 packages/components/codemods/migrateBorderColorsToSemanticTokens/transformScssBorderColors.ts create mode 100644 packages/components/codemods/migrateBorderColorsToSemanticTokens/transformTailwindBorderClasses.spec.ts create mode 100644 packages/components/codemods/migrateBorderColorsToSemanticTokens/transformTailwindBorderClasses.ts diff --git a/.claude/skills/semantic-border-migration/SKILL.md b/.claude/skills/semantic-border-migration/SKILL.md new file mode 100644 index 00000000000..e25878a3caf --- /dev/null +++ b/.claude/skills/semantic-border-migration/SKILL.md @@ -0,0 +1,104 @@ +--- +name: semantic-border-migration +description: Migrate a component's border styles to the new semantic border tokens. Runs the migrateBorderColorsToSemanticTokens codemod first, then falls back to a guided manual migration only after the user confirms the codemod was incomplete. Use when asked to migrate borders to semantic tokens, apply border semantic tokens, or run the border token migration for a component. +--- + +## Semantic Border Migration + +Use this skill to migrate a component's borders from hard-coded **primitive** +colors — CSS `var(--color-gray-500)`, SCSS `$color-gray-500`, or Tailwind +`border-gray-500` — to the new **semantic +border tokens** (`--border-primary`, `--border-secondary`, `--border-secondary_alt`, +`--border-tertiary`, `--border-brand`, `--border-brand_alt`, `--border-error`, +`--border-error_subtle`). + +This runs in **two stages with a hard gate between them**. Stage 1 is the +deterministic codemod. Stage 2 is a guided manual migration that you only enter +**after the user has verified Stage 1 failed or is incomplete**. Never jump +straight to Stage 2, and never run Stage 2 automatically off the back of Stage 1. + +## Preconditions + +- Package manager: `pnpm`. Repo uses Changesets + Buildkite/GitHub Actions CI. +- `@kaizen/components` is installed (ships the `kaizen-codemod` bin). +- Know the **target component / directory** to migrate. +- If the consumer repo sets a Tailwind `prefix`, know its value (e.g. `goals-` + or `EP:`) so the codemod preserves it. + +## Reference + +- Codemod: [`migrateBorderColorsToSemanticTokens`](../../../packages/components/codemods/migrateBorderColorsToSemanticTokens/README.md) — the single source of truth for the confident mapping table and CLI usage. +- Semantic token definitions: [`semanticColorTokens.ts`](../../../packages/design-tokens/src/js/semanticColorTokens.ts) (the `border` group). + +--- + +## Stage 1 — Attempt the codemod (deterministic) + +1. **Confirm the target** directory/component with the user, and the Tailwind + prefix if any. +2. **Run the codemod:** + ```sh + pnpm kaizen-codemod migrateBorderColorsToSemanticTokens + ``` + If there is a Tailwind prefix, pass it via the env var: + ```sh + KAIZEN_TW_PREFIX=goals- pnpm kaizen-codemod migrateBorderColorsToSemanticTokens + ``` +3. **Tidy rewrites:** run prettier/lint over the changed files (e.g. + `pnpm prettier --write `), since AST/text rewrites may need reformatting. +4. **Surface the report.** The codemod prints a **`✅ Converted N`** count and, + crucially, a **`⚠️ SKIPPED`** list of border colors it could not confidently + map (`file:line — detail`). Show this to the user, along with the diff. +5. **STOP and ask the user to verify.** Explicitly ask: + + > Did Stage 1 fully migrate this component's borders, or are there skipped / + > incomplete / ambiguous cases still to resolve? + + Do **not** proceed. Only continue to Stage 2 if the user confirms Stage 1 is + incomplete or failed. If the user says it's complete, verify (below) and stop. + +--- + +## Stage 2 — Guided manual fallback (only after user verification) + +Enter this stage **only** when the user has confirmed Stage 1 left work behind. +Work through the codemod's `SKIPPED` report plus anything the user flagged. + +1. **Resolve each skipped border color.** For each entry, decide the correct + semantic border token using the intent of the border and the mappings in + [`semanticColorTokens.ts`](../../../packages/design-tokens/src/js/semanticColorTokens.ts). + Apply the change by hand (CSS `var(--color-*)` → `var(--border-*)`; SCSS + `$color-*` → `$border-*`, importing `@kaizen/design-tokens/sass/semantic` if + the `$border-*` var isn't already available; Tailwind `border-*` → the + semantic utility, preserving any prefix/variant). +2. **Handle what the codemod can't:** + - **No direct equivalent** (yellow / orange / green / purple borders, alpha / + `rgb()` usages, raw hex). These often need a **design decision** — do not + force a mapping. Propose the closest semantic token and flag it for + designer/user sign-off rather than guessing silently. + - **Dynamic / computed class names** (template literals, variables) the + codemod skipped. + - **Unusual selectors or non-standard files** not covered by the walk. +3. **Record decisions** for ambiguous cases (what you chose and why) so reviewers + can check them. + +--- + +## Verification (either stage) + +- **Tests:** `pnpm --filter @kaizen/components test` (or scope to the component). +- **Build:** `pnpm build`. +- **Visual:** Storybook + Chromatic to confirm no border regressions on the + migrated component. +- **Summarise** what was auto-migrated (Stage 1), what was hand-migrated + (Stage 2), and anything deferred for design sign-off. + +## Do / Don't + +- **Do** keep the change scoped to one component/directory and add a changeset if + it ships to consumers. +- **Do** preserve Tailwind prefixes and variant chains exactly. +- **Don't** enter Stage 2 without explicit user verification that Stage 1 is + incomplete. +- **Don't** guess a semantic token for a color with no confident mapping — surface + it for a design decision. diff --git a/packages/components/codemods/README.md b/packages/components/codemods/README.md index ea16972860d..950ab7ec10b 100644 --- a/packages/components/codemods/README.md +++ b/packages/components/codemods/README.md @@ -25,6 +25,10 @@ pnpm kaizen-codemod src migrateWellVariantToColor ## Available codemods +### `migrateBorderColorsToSemanticTokens` + +Migrates hard-coded primitive border colors to the new semantic border tokens across CSS, SCSS, and Tailwind, via three transformers dispatched by file extension: CSS custom properties (`var(--color-gray-500)` → `var(--border-secondary)`), SCSS variables (`$color-gray-500` → `$border-secondary`, adding the `@kaizen/design-tokens/sass/semantic` import when needed), and Tailwind utilities (`border-gray-500` → `border-secondary`). Only confident border-context mappings are rewritten; ambiguous/unmapped colors and alpha/`rgb()` usages (e.g. `rgba($color-gray-600-rgb, 0.1)`) are skipped and reported. Honours a consumer Tailwind `prefix` via `KAIZEN_TW_PREFIX`. See the [README](./migrateBorderColorsToSemanticTokens/README.md), and pair it with the `/semantic-border-migration` skill for the stage-2 fallback. + Released in `1.80.6` ### `runV1Codemods` diff --git a/packages/components/codemods/migrateBorderColorsToSemanticTokens/README.md b/packages/components/codemods/migrateBorderColorsToSemanticTokens/README.md new file mode 100644 index 00000000000..9c6fae5f8aa --- /dev/null +++ b/packages/components/codemods/migrateBorderColorsToSemanticTokens/README.md @@ -0,0 +1,162 @@ +# `migrateBorderColorsToSemanticTokens` + +Migrates hard-coded **primitive border colors** to the new **semantic border +tokens** across CSS, SCSS, and Tailwind. It is the deterministic first stage of +the border migration; the companion [`/semantic-border-migration`](../../../../.claude/skills/semantic-border-migration/SKILL.md) +skill runs this codemod and then guides a manual fallback for anything it +deliberately skips. + +## Prerequisites + +- Install `@kaizen/components` (the `kaizen-codemod` bin ships with the package). + +## Usage + +``` +pnpm kaizen-codemod {DIR} migrateBorderColorsToSemanticTokens +``` + +- `{DIR}` — directory to scan (e.g. `src`, or a single component folder to scope + to one component). `node_modules` is excluded. +- After it runs, **run prettier/lint** to tidy any rewritten lines. +- Review the printed **`SKIPPED`** report and resolve the remaining cases with + the `/semantic-border-migration` skill (stage 2). + +### Tailwind prefix + +If your repo sets a Tailwind `prefix`, tell the codemod so prefixed border +utilities are matched and the prefix is **preserved** on rewrite. The codemod +resolves the prefix from (in order): a `--prefix=` arg, the `KAIZEN_TW_PREFIX` +env var, or a `tailwind.config.*` in the current directory. + +``` +# utility prefix (Tailwind `prefix: 'goals-'`) +KAIZEN_TW_PREFIX=goals- pnpm kaizen-codemod src migrateBorderColorsToSemanticTokens +# goals-border-gray-500 → goals-border-secondary + +# colon namespace prefix (e.g. Employee Profile) +KAIZEN_TW_PREFIX=EP: pnpm kaizen-codemod src migrateBorderColorsToSemanticTokens +# EP:border-gray-500 → EP:border-secondary +``` + +Stacked variants (`hover:`, `md:`) are always preserved automatically. + +## How it works + +The codemod walks `{DIR}` (excluding `node_modules`) and dispatches each file to +one of three transformers by extension. They share the confident mapping and +skip/report rules, but each handles the reference styles native to its language: + +| Files | Transformer | Reference styles handled | +| --------------- | -------------------------------- | ----------------------------------------------------------------------- | +| `.css` | `transformCssBorderColors` | CSS custom property `var(--color-*)` | +| `.scss` | `transformScssBorderColors` | SCSS variable `$color-*` **and** CSS custom property `var(--color-*)` | +| `.tsx/.jsx/.ts` | `transformTailwindBorderClasses` | Tailwind border utilities in `className`/`class` and `clsx`-style calls | + +CSS/SCSS use a `postcss` AST (`postcss-scss` for `.scss`); Tailwind uses the +TypeScript compiler API. Only file writes happen for files with at least one +conversion. + +## What it converts + +Only **confident 1:1 mappings in a border context** are rewritten. Anything +else is left untouched and reported for stage 2. + +| Primitive | Semantic token | CSS / SCSS `var(--color-*)` | SCSS `$color-*` | Tailwind `border-*` | +| ---------- | ---------------------- | --------------------------------------------------- | --------------------------------------- | -------------------------------------- | +| `gray-600` | `border-primary` | `var(--color-gray-600)` → `var(--border-primary)` | `$color-gray-600` → `$border-primary` | `border-gray-600` → `border-primary` | +| `gray-500` | `border-secondary` | `var(--color-gray-500)` → `var(--border-secondary)` | `$color-gray-500` → `$border-secondary` | `border-gray-500` → `border-secondary` | +| `gray-200` | `border-secondary_alt` | … | … | … | +| `gray-300` | `border-tertiary` | … | … | … | +| `blue-500` | `border-brand` | … | … | … | +| `blue-300` | `border-brand_alt` | … | … | … | +| `red-500` | `border-error` | … | … | … | +| `red-300` | `border-error_subtle` | … | … | … | + +**Border context** = the `border` shorthand, per-side/logical shorthands +(`border-top`, `border-inline-start`, …), the `*-color` longhands, or a custom +property whose name contains `border` (e.g. `--border-color`). Non-border uses +of the same primitive (e.g. `background: var(--color-gray-500)` or +`background: $color-gray-500`) are never touched. + +### SCSS specifics + +- Consumer SCSS usually references Kaizen colors as **SCSS variables** + (`$color-gray-500`, imported from `@kaizen/design-tokens/sass/color`), so those + are matched in addition to raw `var(--color-*)`. Solid `$color-*` borders are + rewritten to the semantic SCSS variable (`$border-secondary`, …). +- Because `$border-*` is defined in `@kaizen/design-tokens/sass/semantic`, the + codemod **adds that import** when it introduces a `$border-*` variable and the + file doesn't already import it — cloning the style (`~` prefix / quotes) of an + existing kaizen sass import so the addition matches your convention. +- **Namespaced** refs (`@use` → `color.$color-*`) are left for stage 2 rather + than rewritten with an assumed namespace. + +### What is skipped (reported, never guessed) + +- Colors with no confident semantic border equivalent (`white`, `yellow`, + `orange`, `green`, `purple`, `blue-400`, `gray-400`, raw hex …). +- **Alpha / `rgb()` / `rgba()` usages**, e.g. `rgba($color-gray-600-rgb, 0.1)` or + the `$color-*-rgb` helpers — the semantic tokens are solid colors, so these + need a design decision. +- Dynamic/computed Tailwind class names (template literals, variables). + +## Examples + +**CSS** + +```css +/* before */ +.card { + border: var(--border-width-1) solid var(--color-gray-500); +} +.error { + --border-color: var(--color-red-500); +} +/* after */ +.card { + border: var(--border-width-1) solid var(--border-secondary); +} +.error { + --border-color: var(--border-error); +} +``` + +**SCSS** (note the injected semantic import and the skipped alpha border) + +```scss +/* before */ +@import '~@kaizen/design-tokens/sass/color'; +.card { + border: 1px solid $color-gray-500; +} +.footer { + border-top: 1px solid rgba($color-gray-600-rgb, 0.1); /* skipped — design decision */ +} +/* after */ +@import '~@kaizen/design-tokens/sass/color'; +@import '~@kaizen/design-tokens/sass/semantic'; +.card { + border: 1px solid $border-secondary; +} +.footer { + border-top: 1px solid rgba($color-gray-600-rgb, 0.1); /* left for stage 2 */ +} +``` + +**Tailwind** + +```tsx +// before +
+// after +
+``` + +## Source of truth + +Mappings mirror the `border` group in +[`packages/design-tokens/src/js/semanticColorTokens.ts`](../../../design-tokens/src/js/semanticColorTokens.ts) +and live in [`borderTokenMap.ts`](./borderTokenMap.ts). The CSS and SCSS +transformers share the postcss engine in +[`borderColorPostcss.ts`](./borderColorPostcss.ts). diff --git a/packages/components/codemods/migrateBorderColorsToSemanticTokens/borderColorPostcss.ts b/packages/components/codemods/migrateBorderColorsToSemanticTokens/borderColorPostcss.ts new file mode 100644 index 00000000000..2fc8258efbe --- /dev/null +++ b/packages/components/codemods/migrateBorderColorsToSemanticTokens/borderColorPostcss.ts @@ -0,0 +1,137 @@ +import postcss from 'postcss' +import { + BORDER_COLOR_MAP, + COLOR_VAR_REFERENCE, + SCSS_COLOR_VAR_REFERENCE, + hasAlphaColorUsage, + isBorderColorProperty, + referencesPrimitiveColor, +} from './borderTokenMap' + +/** + * Shared postcss engine for the CSS and SCSS border-color transformers. Both + * public transformers ({@link transformCssBorderColors}, + * {@link transformScssBorderColors}) parse with their own syntax and delegate + * the declaration rewriting here so the border-context rules, confident mapping, + * and skip/report behaviour stay identical across CSS and SCSS. + */ + +export type ConvertedToken = { + line: number + property: string + from: string + to: string +} + +export type SkippedToken = { + line: number + property: string + value: string +} + +export type BorderColorResult = { + converted: ConvertedToken[] + skipped: SkippedToken[] +} + +/** Path to the semantic sass partial that defines the `$border-*` variables. */ +const SEMANTIC_SASS_MODULE = '@kaizen/design-tokens/sass/semantic' + +/** + * Ensures the semantic sass partial is imported once a `$border-*` variable has + * been introduced, otherwise the rewritten SCSS would reference an undefined + * variable and fail to compile. Clones the style (quote + `~` prefix) of an + * existing `@kaizen/design-tokens/sass/*` import so the added line matches the + * file's convention; falls back to a plain `@import` when no kaizen import + * exists. No-op when the semantic partial is already imported/used. + */ +const ensureSemanticImport = (root: postcss.Root): void => { + let kaizenImport: postcss.AtRule | undefined + let alreadyImported = false + + root.walkAtRules((atRule) => { + if (atRule.name !== 'import' && atRule.name !== 'use') return + if (atRule.params.includes('design-tokens/sass/semantic')) alreadyImported = true + if (!kaizenImport && atRule.params.includes('design-tokens/sass/')) kaizenImport = atRule + }) + + if (alreadyImported) return + + if (kaizenImport) { + const params = kaizenImport.params.replace(/(design-tokens\/sass\/)[a-z-]+/i, `$1semantic`) + // Clone the existing import's own-line formatting so the addition sits on its + // own line rather than being appended to the source import. + kaizenImport.cloneAfter({ params, raws: { ...kaizenImport.raws, before: '\n' } }) + return + } + + root.prepend(postcss.atRule({ name: 'import', params: `'${SEMANTIC_SASS_MODULE}'` })) +} + +/** + * Walks every declaration in `root`, rewriting hard-coded primitive border + * colors to the new semantic border tokens. When `scss` is true, SCSS + * `$color-*` variables are also rewritten (to `$border-*`) and the semantic sass + * import is injected if needed. + * + * Only confident 1:1 mappings in a border context are rewritten (see + * {@link BORDER_COLOR_MAP}). Unmapped border colors, and alpha/`rgb()`/`rgba()` + * usages such as `rgba($color-gray-600-rgb, 0.1)`, are left untouched and + * returned in `skipped` for the stage-2 fallback. Non-border usages of the same + * primitives (e.g. `background: var(--color-gray-500)`) are never touched. + */ +export const rewriteBorderColors = ( + root: postcss.Root, + { scss = false }: { scss?: boolean } = {}, +): BorderColorResult => { + const converted: ConvertedToken[] = [] + const skipped: SkippedToken[] = [] + let introducedScssSemantic = false + + root.walkDecls((decl) => { + if (!isBorderColorProperty(decl.prop)) return + if (!referencesPrimitiveColor(decl.value)) return + + const line = decl.source?.start?.line ?? 0 + + // Alpha / rgb() usages are solid-color-only in the semantic set — flag for a + // design decision (stage 2) instead of guessing, and don't touch the value. + if (hasAlphaColorUsage(decl.value)) { + skipped.push({ line, property: decl.prop, value: decl.value.trim() }) + return + } + + // CSS custom property references: var(--color-X) → var(--border-Y). + let value = decl.value.replace(COLOR_VAR_REFERENCE, (match, primitive: string) => { + const semantic = BORDER_COLOR_MAP[primitive] + if (semantic) { + const replacement = `var(--${semantic})` + converted.push({ line, property: decl.prop, from: match, to: replacement }) + return replacement + } + skipped.push({ line, property: decl.prop, value: match }) + return match + }) + + // SCSS variable references: $color-X → $border-Y (SCSS files only). + if (scss) { + value = value.replace(SCSS_COLOR_VAR_REFERENCE, (match, primitive: string) => { + const semantic = BORDER_COLOR_MAP[primitive] + if (semantic) { + const replacement = `$${semantic}` + converted.push({ line, property: decl.prop, from: match, to: replacement }) + introducedScssSemantic = true + return replacement + } + skipped.push({ line, property: decl.prop, value: match }) + return match + }) + } + + decl.value = value + }) + + if (introducedScssSemantic) ensureSemanticImport(root) + + return { converted, skipped } +} diff --git a/packages/components/codemods/migrateBorderColorsToSemanticTokens/borderTokenMap.ts b/packages/components/codemods/migrateBorderColorsToSemanticTokens/borderTokenMap.ts new file mode 100644 index 00000000000..4f6ae8ce686 --- /dev/null +++ b/packages/components/codemods/migrateBorderColorsToSemanticTokens/borderTokenMap.ts @@ -0,0 +1,95 @@ +/** + * Confident primitive → semantic border-token mappings for the border codemod. + * + * Source of truth: `packages/design-tokens/src/js/semanticColorTokens.ts` (the + * `border` group). That file maps a semantic token → the primitive it paints + * with; here we invert it (primitive → semantic) because the codemod rewrites + * hard-coded primitives to the new semantic token. + * + * We ONLY include mappings that are safe to apply automatically in a border + * context. Ambiguous or unmapped primitives (e.g. `gray-400`, `blue-400`, + * `white`, and any `yellow`/`orange`/`green`/`purple` used on a border) have no + * confident 1:1 semantic border token, so they are intentionally omitted — the + * codemod skips and reports them for the `/semantic-border-migration` stage-2 + * fallback rather than guessing. + */ + +/** primitive color-token name (e.g. `gray-500`) → semantic border-token name (e.g. `border-secondary`) */ +export const BORDER_COLOR_MAP: Record = { + 'gray-600': 'border-primary', + 'gray-500': 'border-secondary', + 'gray-200': 'border-secondary_alt', + 'gray-300': 'border-tertiary', + 'blue-500': 'border-brand', + 'blue-300': 'border-brand_alt', + 'red-500': 'border-error', + 'red-300': 'border-error_subtle', +} + +/** + * Tailwind border utility (e.g. `border-gray-500`) → semantic border utility + * (e.g. `border-secondary`). Derived from {@link BORDER_COLOR_MAP}; the semantic + * token name already starts with `border-`, so it doubles as the utility class. + */ +export const TAILWIND_BORDER_MAP: Record = Object.fromEntries( + Object.entries(BORDER_COLOR_MAP).map(([primitive, semantic]) => [ + `border-${primitive}`, + semantic, + ]), +) + +/** + * Matches CSS properties that can carry a border *color*: the `border` + * shorthand, per-side/logical shorthands, and the explicit `*-color` longhands. + * Deliberately excludes `border-width`/`border-style`/`border-radius`/ + * `border-image`/`border-spacing`/`border-collapse`, which never hold a color. + */ +const BORDER_COLOR_PROPERTY = + /^border(-(top|right|bottom|left|block|inline)(-(start|end))?)?(-color)?$/ + +/** + * True when a declaration property can hold a border color — either a standard + * border color property, or a custom property whose name mentions `border` + * (e.g. `--border-color`, `--border-hover-color`). + */ +export const isBorderColorProperty = (property: string): boolean => { + const prop = property.trim().toLowerCase() + if (prop.startsWith('--')) return prop.includes('border') + return BORDER_COLOR_PROPERTY.test(prop) +} + +/** Matches a `var(--color-)` reference and captures the primitive name. */ +export const COLOR_VAR_REFERENCE = /var\(\s*--color-([a-z0-9-]+)\s*\)/gi + +/** + * Matches a solid `$color--` SCSS variable reference (the form + * consumers get from `@import '@kaizen/design-tokens/sass/color'`) and captures + * the primitive name. Deliberately does NOT match the `-rgb`/`-id` companions + * (`$color-gray-600-rgb`) — those are alpha/identifier helpers with no solid + * semantic border equivalent. A leading `\w`/`.`/`-` is disallowed so namespaced + * (`color.$color-…`) refs are left for stage 2 rather than mis-rewritten. + */ +export const SCSS_COLOR_VAR_REFERENCE = /(? + /var\(\s*--color-/i.test(value) || /(? + /\brgba?\(/i.test(value) || /\$color-[a-z0-9-]+-rgb\b/i.test(value) + +/** + * Heuristic for a Tailwind border-*color* utility so unmapped ones can be + * reported (skipped) rather than silently ignored. Matches + * `border--` and arbitrary values like `border-[var(--color-…)]`. + * Excludes structural utilities (`border-2`, `border-t`, `border-solid`) and + * already-semantic classes (`border-primary`). + */ +export const TAILWIND_BORDER_COLOR_UTILITY = + /^border-(gray|blue|red|green|yellow|orange|purple|teal|pink|white|black)(-\d+)?$|^border-\[.+\]$/i diff --git a/packages/components/codemods/migrateBorderColorsToSemanticTokens/index.ts b/packages/components/codemods/migrateBorderColorsToSemanticTokens/index.ts new file mode 100644 index 00000000000..c7df4bc8f81 --- /dev/null +++ b/packages/components/codemods/migrateBorderColorsToSemanticTokens/index.ts @@ -0,0 +1,109 @@ +import fs from 'fs' +import path from 'path' +import ts from 'typescript' +import { transformCssBorderColors } from './transformCssBorderColors' +import { transformScssBorderColors } from './transformScssBorderColors' +import { transformTailwindBorderClasses } from './transformTailwindBorderClasses' + +type SkipReport = { file: string; line: number; detail: string } + +/** + * Resolves the consumer's Tailwind prefix. + * + * The `kaizen-codemod` wrapper only forwards the target dir, so the prefix is + * taken from (in priority order): a `--prefix=` CLI arg (when run directly via + * tsx), the `KAIZEN_TW_PREFIX` env var, or a best-effort read of a + * `tailwind.config.*` in the current working directory. + */ +const resolveTailwindPrefix = (): string => { + const argPrefix = process.argv.find((arg) => arg.startsWith('--prefix=')) + if (argPrefix) return argPrefix.slice('--prefix='.length) + if (process.env.KAIZEN_TW_PREFIX) return process.env.KAIZEN_TW_PREFIX + + const configName = [ + 'tailwind.config.ts', + 'tailwind.config.js', + 'tailwind.config.cjs', + 'tailwind.config.mjs', + ].find((name) => fs.existsSync(path.join(process.cwd(), name))) + if (configName) { + try { + const contents = fs.readFileSync(path.join(process.cwd(), configName), 'utf8') + const match = /prefix:\s*['"`]([^'"`]+)['"`]/.exec(contents) + if (match) return match[1] + } catch { + // best effort only — fall through to no prefix + } + } + return '' +} + +const traverseDir = (dir: string, onFile: (filePath: string) => void): void => { + if (dir.includes('node_modules')) return + for (const entry of fs.readdirSync(dir)) { + const fullPath = path.join(dir, entry) + if (fs.statSync(fullPath).isDirectory()) { + traverseDir(fullPath, onFile) + } else { + onFile(fullPath) + } + } +} + +const run = (): void => { + console.log(' ~(-_- ~) Running border colors → semantic tokens transformer (~ -_-)~') + const targetDir = process.argv[2] + if (!targetDir || targetDir.startsWith('--')) { + console.error('Usage: kaizen-codemod migrateBorderColorsToSemanticTokens') + process.exit(1) + } + + const prefix = resolveTailwindPrefix() + if (prefix) console.log(`Using Tailwind prefix: "${prefix}"`) + + let convertedCount = 0 + const skips: SkipReport[] = [] + + traverseDir(targetDir, (filePath) => { + const relative = path.relative(process.cwd(), filePath) + + if (filePath.endsWith('.scss') || filePath.endsWith('.css')) { + const source = fs.readFileSync(filePath, 'utf8') + const { code, converted, skipped } = filePath.endsWith('.scss') + ? transformScssBorderColors(source) + : transformCssBorderColors(source) + if (converted.length > 0) fs.writeFileSync(filePath, code, 'utf8') + convertedCount += converted.length + skipped.forEach((s) => + skips.push({ file: relative, line: s.line, detail: `${s.property}: ${s.value}` }), + ) + return + } + + if (/\.(tsx|jsx|ts)$/.test(filePath)) { + const source = fs.readFileSync(filePath, 'utf8') + const scriptKind = filePath.endsWith('.ts') ? ts.ScriptKind.TS : ts.ScriptKind.TSX + const { code, converted, skipped } = transformTailwindBorderClasses(source, { + prefix, + scriptKind, + }) + if (converted.length > 0) fs.writeFileSync(filePath, code, 'utf8') + convertedCount += converted.length + skipped.forEach((s) => skips.push({ file: relative, line: s.line, detail: s.token })) + } + }) + + console.log('') + console.log(`✅ Converted ${convertedCount} border color token(s) to semantic tokens.`) + + if (skips.length > 0) { + console.log('') + console.log(`⚠️ SKIPPED ${skips.length} border color(s) with no confident semantic mapping.`) + console.log(' Resolve these with the /semantic-border-migration skill (stage 2):') + skips.forEach((s) => console.log(` - ${s.file}:${s.line} — ${s.detail}`)) + } else { + console.log('No ambiguous border colors detected — stage 2 may not be needed.') + } +} + +run() diff --git a/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformCssBorderColors.spec.ts b/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformCssBorderColors.spec.ts new file mode 100644 index 00000000000..5d79c871c80 --- /dev/null +++ b/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformCssBorderColors.spec.ts @@ -0,0 +1,58 @@ +import { transformCssBorderColors } from './transformCssBorderColors' + +describe('transformCssBorderColors()', () => { + it('swaps only the color token in a border shorthand', () => { + const input = `.a { + border: var(--border-solid-border-width) var(--border-solid-border-style) var(--color-gray-500); +}` + const { code, converted } = transformCssBorderColors(input) + expect(code).toContain( + 'border: var(--border-solid-border-width) var(--border-solid-border-style) var(--border-secondary);', + ) + expect(converted).toHaveLength(1) + expect(converted[0]).toMatchObject({ to: 'var(--border-secondary)' }) + }) + + it('rewrites border-color longhand', () => { + const { code } = transformCssBorderColors('.a { border-color: var(--color-gray-600); }') + expect(code).toContain('border-color: var(--border-primary);') + }) + + it('rewrites a border-related custom property', () => { + const { code } = transformCssBorderColors('.a { --border-color: var(--color-blue-500); }') + expect(code).toContain('--border-color: var(--border-brand);') + }) + + it('rewrites per-side and logical border color properties', () => { + const { code } = transformCssBorderColors( + '.a { border-bottom-color: var(--color-red-500); border-inline-start: 1px solid var(--color-red-300); }', + ) + expect(code).toContain('border-bottom-color: var(--border-error);') + expect(code).toContain('border-inline-start: 1px solid var(--border-error_subtle);') + }) + + it('leaves non-border usages of the same primitive untouched', () => { + const input = '.a { background: var(--color-gray-500); color: var(--color-gray-600); }' + const { code, converted } = transformCssBorderColors(input) + expect(code).toBe(input) + expect(converted).toHaveLength(0) + }) + + it('skips and reports border colors with no confident semantic mapping', () => { + const { code, converted, skipped } = transformCssBorderColors( + '.a { border-color: var(--color-yellow-700); }', + ) + expect(code).toContain('border-color: var(--color-yellow-700);') + expect(converted).toHaveLength(0) + expect(skipped).toHaveLength(1) + expect(skipped[0]).toMatchObject({ property: 'border-color', value: 'var(--color-yellow-700)' }) + }) + + it('does not touch border-width / border-style / border-radius', () => { + const input = + '.a { border-width: var(--color-gray-500); border-radius: var(--color-gray-500); }' + // These properties never carry a color; even if a color var appears we leave it. + const { converted } = transformCssBorderColors(input) + expect(converted).toHaveLength(0) + }) +}) diff --git a/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformCssBorderColors.ts b/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformCssBorderColors.ts new file mode 100644 index 00000000000..21918913540 --- /dev/null +++ b/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformCssBorderColors.ts @@ -0,0 +1,27 @@ +import postcss from 'postcss' +import { + rewriteBorderColors, + type BorderColorResult, + type ConvertedToken, + type SkippedToken, +} from './borderColorPostcss' + +export type { ConvertedToken, SkippedToken } + +export type CssTransformResult = BorderColorResult & { code: string } + +/** + * Rewrites hard-coded primitive border colors to the new semantic border tokens + * in plain **CSS**, matching CSS custom property references: + * `border-color: var(--color-gray-500)` → `border-color: var(--border-secondary)` + * + * SCSS `$variable` references are handled by {@link transformScssBorderColors}. + * Only confident 1:1 mappings in a border context are rewritten; unmapped and + * alpha/`rgb()` border colors are left untouched and returned in `skipped` for + * the stage-2 fallback. + */ +export const transformCssBorderColors = (source: string): CssTransformResult => { + const root = postcss.parse(source) + const { converted, skipped } = rewriteBorderColors(root, { scss: false }) + return { code: root.toString(), converted, skipped } +} diff --git a/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformScssBorderColors.spec.ts b/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformScssBorderColors.spec.ts new file mode 100644 index 00000000000..86a238346e4 --- /dev/null +++ b/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformScssBorderColors.spec.ts @@ -0,0 +1,86 @@ +import { transformScssBorderColors } from './transformScssBorderColors' + +describe('transformScssBorderColors()', () => { + it('rewrites SCSS $color-* variables to the semantic $border-* variable', () => { + const input = `@import "~@kaizen/design-tokens/sass/color"; +.a { + border: 1px solid $color-gray-500; +}` + const { code, converted } = transformScssBorderColors(input) + expect(code).toContain('border: 1px solid $border-secondary;') + expect(converted).toHaveLength(1) + expect(converted[0]).toMatchObject({ from: '$color-gray-500', to: '$border-secondary' }) + }) + + it('rewrites CSS custom property references inside SCSS too', () => { + const input = `.a { + &:hover { border-color: var(--color-gray-500); } +}` + const { code } = transformScssBorderColors(input) + expect(code).toContain('border-color: var(--border-secondary);') + }) + + it('preserves nested rules and unrelated $variables', () => { + const input = `$x: 1; +.a { + &:hover { border-color: $color-gray-600; } +}` + const { code } = transformScssBorderColors(input) + expect(code).toContain('border-color: $border-primary;') + expect(code).toContain('$x: 1;') + }) + + it('adds the semantic sass import (matching existing import style) when introducing a $border-* var', () => { + const input = `@import "~@kaizen/design-tokens/sass/color"; +.a { + border-color: $color-gray-600; +}` + const { code } = transformScssBorderColors(input) + expect(code).toContain('@import "~@kaizen/design-tokens/sass/semantic";') + expect(code).toContain('border-color: $border-primary;') + }) + + it('prepends a plain semantic import when no kaizen sass import exists', () => { + const { code } = transformScssBorderColors('.a { border-color: $color-blue-500; }') + expect(code).toContain("@import '@kaizen/design-tokens/sass/semantic';") + expect(code).toContain('border-color: $border-brand;') + }) + + it('does not duplicate the semantic import when already present', () => { + const input = `@import "~@kaizen/design-tokens/sass/color"; +@import "~@kaizen/design-tokens/sass/semantic"; +.a { + border-color: $color-gray-600; +}` + const { code } = transformScssBorderColors(input) + expect(code.match(/sass\/semantic/g)).toHaveLength(1) + }) + + it('skips and reports rgba()/alpha border colors for a design decision', () => { + const input = `@import "~@kaizen/design-tokens/sass/color"; +.footer { + border-top: 1px solid rgba($color-gray-600-rgb, 0.1); +}` + const { code, converted, skipped } = transformScssBorderColors(input) + expect(code).toContain('border-top: 1px solid rgba($color-gray-600-rgb, 0.1);') + expect(code).not.toContain('$border-') + expect(converted).toHaveLength(0) + expect(skipped).toHaveLength(1) + expect(skipped[0]).toMatchObject({ property: 'border-top' }) + }) + + it('skips and reports unmapped $color-* border variables', () => { + const input = '.a { border-color: $color-gray-400; }' + const { code, converted, skipped } = transformScssBorderColors(input) + expect(code).toContain('border-color: $color-gray-400;') + expect(converted).toHaveLength(0) + expect(skipped).toHaveLength(1) + }) + + it('leaves non-border $color-* usages untouched', () => { + const input = '.a { background: $color-gray-500; }' + const { code, converted } = transformScssBorderColors(input) + expect(code).toBe(input) + expect(converted).toHaveLength(0) + }) +}) diff --git a/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformScssBorderColors.ts b/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformScssBorderColors.ts new file mode 100644 index 00000000000..8a0cdca0f80 --- /dev/null +++ b/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformScssBorderColors.ts @@ -0,0 +1,31 @@ +import scssSyntax from 'postcss-scss' +import { + rewriteBorderColors, + type BorderColorResult, + type ConvertedToken, + type SkippedToken, +} from './borderColorPostcss' + +export type { ConvertedToken, SkippedToken } + +export type ScssTransformResult = BorderColorResult & { code: string } + +/** + * Rewrites hard-coded primitive border colors to the new semantic border tokens + * in **SCSS**, covering both reference styles a `.scss` file can use: + * - SCSS variable (Kaizen sass): `border: 1px solid $color-gray-500` → `$border-secondary` + * - CSS custom property: `border-color: var(--color-gray-500)` → `var(--border-secondary)` + * + * When a `$border-*` variable is introduced, the `@kaizen/design-tokens/sass/semantic` + * import is added (matching the file's existing import style) so the output still + * compiles. Only confident 1:1 mappings in a border context are rewritten; + * unmapped border colors and alpha/`rgb()`/`rgba()` usages such as + * `rgba($color-gray-600-rgb, 0.1)` are left untouched and returned in `skipped` + * for the stage-2 fallback. Nested rules, `@layer`, and other SCSS constructs + * are preserved by the SCSS parser. + */ +export const transformScssBorderColors = (source: string): ScssTransformResult => { + const root = scssSyntax.parse(source) + const { converted, skipped } = rewriteBorderColors(root, { scss: true }) + return { code: root.toString(), converted, skipped } +} diff --git a/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformTailwindBorderClasses.spec.ts b/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformTailwindBorderClasses.spec.ts new file mode 100644 index 00000000000..95d6e7b41bb --- /dev/null +++ b/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformTailwindBorderClasses.spec.ts @@ -0,0 +1,52 @@ +import { transformTailwindBorderClasses } from './transformTailwindBorderClasses' + +describe('transformTailwindBorderClasses()', () => { + it('rewrites a named border color utility in a className attribute', () => { + const input = `const A = () =>
` + const { code, converted } = transformTailwindBorderClasses(input) + expect(code).toContain('className="border border-secondary p-2"') + expect(converted).toEqual([{ line: 1, from: 'border-gray-500', to: 'border-secondary' }]) + }) + + it('rewrites an arbitrary-value border utility', () => { + const input = `const A = () =>
` + const { code } = transformTailwindBorderClasses(input) + expect(code).toContain('className="border-brand"') + }) + + it('rewrites classes inside a clsx call, including object keys', () => { + const input = `const A = () =>
` + const { code } = transformTailwindBorderClasses(input) + expect(code).toContain("'border-error'") + expect(code).toContain("'border-primary'") + }) + + it('preserves a Tailwind utility prefix (goals-)', () => { + const input = `const A = () =>
` + const { code, converted } = transformTailwindBorderClasses(input, { prefix: 'goals-' }) + expect(code).toContain('className="goals-border-secondary"') + expect(converted[0]).toMatchObject({ to: 'goals-border-secondary' }) + }) + + it('preserves a colon namespace prefix (EP:) and stacked variants', () => { + const input = `const A = () =>
` + const { code } = transformTailwindBorderClasses(input) + expect(code).toContain('EP:border-secondary') + expect(code).toContain('hover:border-brand') + }) + + it('skips dynamic class names and reports unmapped border colors', () => { + const input = `const A = () =>
` + const { code, converted, skipped } = transformTailwindBorderClasses(input) + expect(converted).toHaveLength(0) + expect(code).toContain('border-yellow-700') + expect(skipped).toEqual([{ line: 1, token: 'border-yellow-700' }]) + }) + + it('leaves non-className strings untouched', () => { + const input = `const label = "border-gray-500"` + const { code, converted } = transformTailwindBorderClasses(input) + expect(code).toBe(input) + expect(converted).toHaveLength(0) + }) +}) diff --git a/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformTailwindBorderClasses.ts b/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformTailwindBorderClasses.ts new file mode 100644 index 00000000000..82edc46f7bf --- /dev/null +++ b/packages/components/codemods/migrateBorderColorsToSemanticTokens/transformTailwindBorderClasses.ts @@ -0,0 +1,170 @@ +import ts from 'typescript' +import { + BORDER_COLOR_MAP, + TAILWIND_BORDER_COLOR_UTILITY, + TAILWIND_BORDER_MAP, +} from './borderTokenMap' + +export type ConvertedClass = { line: number; from: string; to: string } +export type SkippedClass = { line: number; token: string } + +export type TailwindTransformResult = { + code: string + converted: ConvertedClass[] + skipped: SkippedClass[] +} + +/** JSX attributes whose string value is a class list. */ +const CLASSNAME_ATTRIBUTES = new Set(['className', 'class']) +/** Call expressions whose string arguments are class names. */ +const CLASSNAME_FUNCTIONS = new Set(['clsx', 'classnames', 'classNames', 'cx', 'cn']) +/** Matches an arbitrary-value border utility: `border-[var(--color-)]`. */ +const ARBITRARY_BORDER_VALUE = /^border-\[var\(\s*--color-([a-z0-9-]+)\s*\)\]$/i + +type TokenResult = + | { status: 'converted'; token: string } + | { status: 'skipped' } + | { status: 'unchanged' } + +/** + * Transforms a single class token, preserving any variant chain (`hover:`, + * `md:`, or a namespace prefix like `EP:`) and any configured utility prefix + * (Tailwind `prefix`, like `goals-`). Only the utility portion is matched + * against the border maps; the prefix/variant is re-attached verbatim. + */ +const transformToken = (token: string, prefix: string): TokenResult => { + // Split off the variant chain: everything up to and including the last colon. + // This handles stacked variants (`hover:md:`) and colon-style prefixes (`EP:`). + const lastColon = token.lastIndexOf(':') + const variant = lastColon >= 0 ? token.slice(0, lastColon + 1) : '' + let utility = lastColon >= 0 ? token.slice(lastColon + 1) : token + + // Strip a configured dash-style utility prefix (e.g. `goals-`) so we can match + // the bare utility, then re-apply it. Colon-style prefixes are already handled + // by the variant split above. + let utilityPrefix = '' + if (prefix && !prefix.endsWith(':') && utility.startsWith(prefix)) { + utilityPrefix = prefix + utility = utility.slice(prefix.length) + } + + const rebuild = (mapped: string): string => `${variant}${utilityPrefix}${mapped}` + + // Named utility, e.g. `border-gray-500` → `border-secondary`. + const mapped = TAILWIND_BORDER_MAP[utility] + if (mapped) return { status: 'converted', token: rebuild(mapped) } + + // Arbitrary value, e.g. `border-[var(--color-gray-500)]` → `border-secondary`. + const arbitrary = ARBITRARY_BORDER_VALUE.exec(utility) + if (arbitrary) { + const semantic = BORDER_COLOR_MAP[arbitrary[1]] + if (semantic) return { status: 'converted', token: rebuild(semantic) } + return { status: 'skipped' } + } + + // A border color utility we can't confidently map — report for stage 2. + if (TAILWIND_BORDER_COLOR_UTILITY.test(utility)) return { status: 'skipped' } + + return { status: 'unchanged' } +} + +const transformClassValue = ( + text: string, + prefix: string, + line: number, + converted: ConvertedClass[], + skipped: SkippedClass[], +): { value: string; changed: boolean } => { + let changed = false + const value = text + .split(/(\s+)/) // keep whitespace separators so spacing is preserved + .map((part) => { + if (part.trim() === '') return part + const result = transformToken(part, prefix) + if (result.status === 'converted') { + converted.push({ line, from: part, to: result.token }) + changed = true + return result.token + } + if (result.status === 'skipped') skipped.push({ line, token: part }) + return part + }) + .join('') + return { value, changed } +} + +/** + * Rewrites Tailwind border color utilities in `className`/`class` attributes and + * `clsx`-style calls to the new semantic border utilities, honouring a consumer + * Tailwind `prefix` (e.g. `goals-` or `EP:`). + * + * Edits are spliced back into the original source by node position, so file + * formatting is otherwise preserved (run prettier afterwards regardless). + * Dynamic/computed class names and unmapped border colors are left untouched; + * unmapped border colors are returned in `skipped` for the stage-2 fallback. + */ +export const transformTailwindBorderClasses = ( + source: string, + { + prefix = '', + scriptKind = ts.ScriptKind.TSX, + }: { prefix?: string; scriptKind?: ts.ScriptKind } = {}, +): TailwindTransformResult => { + const sourceFile = ts.createSourceFile( + 'temp.tsx', + source, + ts.ScriptTarget.Latest, + true, + scriptKind, + ) + + const converted: ConvertedClass[] = [] + const skipped: SkippedClass[] = [] + // Inner-text edits keyed by start position to avoid processing a literal twice + // (e.g. a clsx call that also lives inside a className attribute). + const edits = new Map() + + const collectFromStringLiteral = (node: ts.StringLiteralLike): void => { + const start = node.getStart(sourceFile) + if (edits.has(start)) return + const line = sourceFile.getLineAndCharacterOfPosition(start).line + 1 + const { value, changed } = transformClassValue(node.text, prefix, line, converted, skipped) + if (changed) { + // Replace the inner text only, leaving the surrounding quotes/backticks intact. + edits.set(start, { start: start + 1, end: node.getEnd() - 1, text: value }) + } else { + edits.set(start, { start, end: start, text: '' }) // mark as seen, no-op + } + } + + const collectStrings = (node: ts.Node): void => { + if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) { + collectFromStringLiteral(node) + return + } + ts.forEachChild(node, collectStrings) + } + + const visit = (node: ts.Node): void => { + if (ts.isJsxAttribute(node) && CLASSNAME_ATTRIBUTES.has(node.name.getText(sourceFile))) { + if (node.initializer) collectStrings(node.initializer) + } + if (ts.isCallExpression(node) && CLASSNAME_FUNCTIONS.has(node.expression.getText(sourceFile))) { + node.arguments.forEach(collectStrings) + } + ts.forEachChild(node, visit) + } + visit(sourceFile) + + // Apply edits back-to-front so earlier offsets stay valid. + const realEdits = Array.from(edits.values()) + .filter((edit) => edit.end > edit.start) + .sort((a, b) => b.start - a.start) + + let code = source + for (const edit of realEdits) { + code = code.slice(0, edit.start) + edit.text + code.slice(edit.end) + } + + return { code, converted, skipped } +} From c1c45791b214e304cbb616b0a7a9f976b91c9602 Mon Sep 17 00:00:00 2001 From: AliceMenzie Date: Thu, 2 Jul 2026 14:17:17 +1000 Subject: [PATCH 22/25] initial colour skill codemod --- .../semantic-colours-migration/SKILL.md | 126 +++++++++ .../README.md | 195 ++++++++++++++ .../migratePrimitivesToSemanticTokens/TODO.md | 54 ++++ .../index.ts | 109 ++++++++ .../semanticColorPostcss.ts | 145 +++++++++++ .../semanticTokenMap.spec.ts | 90 +++++++ .../semanticTokenMap.ts | 246 ++++++++++++++++++ .../transformCssSemanticColors.spec.ts | 80 ++++++ .../transformCssSemanticColors.ts | 31 +++ .../transformScssSemanticColors.spec.ts | 82 ++++++ .../transformScssSemanticColors.ts | 32 +++ .../transformTailwindSemanticClasses.spec.ts | 78 ++++++ .../transformTailwindSemanticClasses.ts | 182 +++++++++++++ 13 files changed, 1450 insertions(+) create mode 100644 .claude/skills/semantic-colours-migration/SKILL.md create mode 100644 packages/components/codemods/migratePrimitivesToSemanticTokens/README.md create mode 100644 packages/components/codemods/migratePrimitivesToSemanticTokens/TODO.md create mode 100644 packages/components/codemods/migratePrimitivesToSemanticTokens/index.ts create mode 100644 packages/components/codemods/migratePrimitivesToSemanticTokens/semanticColorPostcss.ts create mode 100644 packages/components/codemods/migratePrimitivesToSemanticTokens/semanticTokenMap.spec.ts create mode 100644 packages/components/codemods/migratePrimitivesToSemanticTokens/semanticTokenMap.ts create mode 100644 packages/components/codemods/migratePrimitivesToSemanticTokens/transformCssSemanticColors.spec.ts create mode 100644 packages/components/codemods/migratePrimitivesToSemanticTokens/transformCssSemanticColors.ts create mode 100644 packages/components/codemods/migratePrimitivesToSemanticTokens/transformScssSemanticColors.spec.ts create mode 100644 packages/components/codemods/migratePrimitivesToSemanticTokens/transformScssSemanticColors.ts create mode 100644 packages/components/codemods/migratePrimitivesToSemanticTokens/transformTailwindSemanticClasses.spec.ts create mode 100644 packages/components/codemods/migratePrimitivesToSemanticTokens/transformTailwindSemanticClasses.ts diff --git a/.claude/skills/semantic-colours-migration/SKILL.md b/.claude/skills/semantic-colours-migration/SKILL.md new file mode 100644 index 00000000000..6254ede610a --- /dev/null +++ b/.claude/skills/semantic-colours-migration/SKILL.md @@ -0,0 +1,126 @@ +--- +name: semantic-colours-migration +description: Migrate a component's colours (background, text, foreground/icon, and border) to the new semantic colour tokens. Runs the migratePrimitivesToSemanticTokens codemod first (deterministic), then falls back to a guided manual migration only after the user confirms the codemod was incomplete. Use when asked to migrate colours to semantic tokens, apply semantic colour tokens, or run the semantic colour token migration for a component. +--- + +## Semantic Colours Migration + +Use this skill to migrate a component's colours from hard-coded **primitives** — +CSS `var(--color-blue-500)`, SCSS `$color-blue-500`, or Tailwind `bg-blue-500` — +to the new **semantic colour tokens** across all four groups: + +- **background** → `--bg-*` (e.g. `bg-brand-solid`, `bg-tertiary`) +- **text** → `--text-*` (e.g. `text-primary`, `text-secondary`) +- **foreground** (icons / glyphs) → `--fg-*` (e.g. `fg-tertiary`, `fg-brand-primary`) +- **border** → `--border-*` (e.g. `border-secondary`, `border-brand`) + +This runs in **two stages with a hard gate between them**. Stage 1 is the +deterministic codemod. Stage 2 is a guided manual migration that you only enter +**after the user has verified Stage 1 failed or is incomplete**. Never jump +straight to Stage 2, and never run Stage 2 automatically off the back of Stage 1. + +> **Borders are handled here.** This skill and its codemod fully cover the +> `border-*` group alongside background/text/foreground — do **not** hand off to +> the separate `/semantic-border-migration` skill or run the +> `migrateBorderColorsToSemanticTokens` codemod. Those were the reference/basis +> this skill and codemod were built from; treat them as prior art only. + +## Preconditions + +- Package manager: `pnpm`. Repo uses Changesets + Buildkite/GitHub Actions CI. +- `@kaizen/components` is installed (ships the `kaizen-codemod` bin). +- Know the **target component / directory** to migrate. +- If the consumer repo sets a Tailwind `prefix`, know its value (e.g. `goals-` + or `EP:`) so the codemod preserves it. + +## Reference + +- Codemod: [`migratePrimitivesToSemanticTokens`](../../../packages/components/codemods/migratePrimitivesToSemanticTokens/README.md) — the single source of truth for the confident mapping, group-context rules, and CLI usage. +- Semantic token definitions: [`semanticColorTokens.ts`](../../../packages/design-tokens/src/js/semanticColorTokens.ts) (the `background`, `text`, `foreground`, `border` groups). +- Known follow-ups / outliers: [`TODO.md`](../../../packages/components/codemods/migratePrimitivesToSemanticTokens/TODO.md). +- Prior art (reference only — **not** to be run from this skill): the border-only [`/semantic-border-migration`](../semantic-border-migration/SKILL.md) skill and [`migrateBorderColorsToSemanticTokens`](../../../packages/components/codemods/migrateBorderColorsToSemanticTokens/README.md) codemod, whose two-stage design and border mappings this skill/codemod are built on and fully supersede. + +--- + +## Stage 1 — Attempt the codemod (deterministic) + +Stage 1 is **deterministic**: it only applies confident 1:1 primitive→semantic +mappings and reports everything else. Do not hand-edit colours in this stage. + +1. **Confirm the target** directory/component with the user, and the Tailwind + prefix if any. +2. **Run the codemod:** + ```sh + pnpm kaizen-codemod migratePrimitivesToSemanticTokens + ``` + If there is a Tailwind prefix, pass it via the env var: + ```sh + KAIZEN_TW_PREFIX=goals- pnpm kaizen-codemod migratePrimitivesToSemanticTokens + ``` +3. **Tidy rewrites:** run prettier/lint over the changed files (e.g. + `pnpm prettier --write `), since AST/text rewrites may need reformatting. +4. **Surface the report.** The codemod prints a **`✅ Converted N`** count and, + crucially, a **`⚠️ SKIPPED`** list of colours it could not confidently map + (`file:line — detail`). Show this to the user, along with the diff. +5. **STOP and ask the user to verify.** Explicitly ask: + + > Did Stage 1 fully migrate this component's colours, or are there skipped / + > incomplete / ambiguous cases still to resolve? + + Do **not** proceed. Only continue to Stage 2 if the user confirms Stage 1 is + incomplete or failed. If the user says it's complete, verify (below) and stop. + +--- + +## Stage 2 — Guided manual fallback (only after user verification) + +Enter this stage **only** when the user has confirmed Stage 1 left work behind. +Work through the codemod's `SKIPPED` report plus anything the user flagged, and +**report each missed instance back to the user** with the decision you propose. + +1. **Resolve each skipped colour.** For each entry, decide the correct semantic + token using the intent of the surface (background / text / icon / border) and + the mappings in + [`semanticColorTokens.ts`](../../../packages/design-tokens/src/js/semanticColorTokens.ts). + Apply the change by hand (CSS `var(--color-*)` → `var(--)`; SCSS + `$color-*` → `$`, importing `@kaizen/design-tokens/sass/semantic-color` + if the semantic var isn't already available; Tailwind primitive utility → the + semantic utility, preserving any prefix/variant). +2. **Handle what the codemod can't (report, don't guess):** + - **Colliding primitives** — one primitive backing several tokens in a group + (e.g. `gray-200` → `bg-secondary` *or* `bg-secondary_hover`). Pick the token + that matches the **intent** (resting vs hover/`_alt` state) and note why. + - **No direct equivalent** (colours with no mapping, alpha / `rgb()` usages, + raw hex, `null` tokens not yet signed off). These often need a **design + decision** — propose the closest semantic token and flag it for + designer/user sign-off rather than forcing a mapping. + - **Dynamic / computed class names** (template literals, variables) the codemod + skipped. + - **Out-of-scope properties** (`box-shadow`, `outline-color`, gradients) the + codemod does not touch. +3. **Report the missed instances back.** Summarise every skipped case as + `file:line — original → proposed (rationale / needs sign-off)` so the user and + reviewers can check each decision. + +--- + +## Verification (either stage) + +- **Tests:** `pnpm --filter @kaizen/components test` (or scope to the component). +- **Build:** `pnpm build`. +- **Visual:** Storybook + Chromatic to confirm no colour regressions on the + migrated component (check background, text, icon, and border surfaces, and + hover/focus states). +- **Summarise** what was auto-migrated (Stage 1), what was hand-migrated + (Stage 2), and anything deferred for design sign-off. + +## Do / Don't + +- **Do** keep the change scoped to one component/directory and add a changeset if + it ships to consumers. +- **Do** preserve Tailwind prefixes and variant chains exactly. +- **Do** report every skipped instance in Stage 2 with a proposed mapping. +- **Don't** enter Stage 2 without explicit user verification that Stage 1 is + incomplete. +- **Don't** guess a semantic token for a colliding or unmapped colour — surface + it for a design decision. diff --git a/packages/components/codemods/migratePrimitivesToSemanticTokens/README.md b/packages/components/codemods/migratePrimitivesToSemanticTokens/README.md new file mode 100644 index 00000000000..26de35d65a4 --- /dev/null +++ b/packages/components/codemods/migratePrimitivesToSemanticTokens/README.md @@ -0,0 +1,195 @@ +# `migratePrimitivesToSemanticTokens` + +Migrates hard-coded **primitive colors** to the new **semantic colour tokens** +across all four semantic groups — **background**, **text**, **foreground** +(icons / glyphs), and **border** — in CSS, SCSS, and Tailwind. It is the +deterministic first stage of the semantic-colour migration; the companion +[`/semantic-colours-migration`](../../../../.claude/skills/semantic-colours-migration/SKILL.md) +skill runs this codemod and then guides a manual fallback for anything it +deliberately skips. + +> **Borders are included here.** This codemod handles the `border-*` group +> itself, alongside `bg-*`, `text-*`, and `fg-*` — there is no need to also run +> the older border-only +> [`migrateBorderColorsToSemanticTokens`](../migrateBorderColorsToSemanticTokens/README.md) +> codemod. That codemod is **prior art / reference only**: its architecture and +> border mappings are the basis this one was built on and fully supersedes. + +## Prerequisites + +- Install `@kaizen/components` (the `kaizen-codemod` bin ships with the package). + +## Usage + +``` +pnpm kaizen-codemod {DIR} migratePrimitivesToSemanticTokens +``` + +- `{DIR}` — directory to scan (e.g. `src`, or a single component folder to scope + to one component). `node_modules` is excluded. +- After it runs, **run prettier/lint** to tidy any rewritten lines. +- Review the printed **`SKIPPED`** report and resolve the remaining cases with + the `/semantic-colours-migration` skill (stage 2). + +### Tailwind prefix + +If your repo sets a Tailwind `prefix`, tell the codemod so prefixed utilities +are matched and the prefix is **preserved** on rewrite. The codemod resolves the +prefix from (in order): a `--prefix=` arg, the `KAIZEN_TW_PREFIX` env var, or a +`tailwind.config.*` in the current directory. + +``` +# utility prefix (Tailwind `prefix: 'goals-'`) +KAIZEN_TW_PREFIX=goals- pnpm kaizen-codemod src migratePrimitivesToSemanticTokens +# goals-bg-blue-500 → goals-bg-brand-solid + +# colon namespace prefix (e.g. Employee Profile) +KAIZEN_TW_PREFIX=EP: pnpm kaizen-codemod src migratePrimitivesToSemanticTokens +# EP:bg-blue-500 → EP:bg-brand-solid +``` + +Stacked variants (`hover:`, `md:`) are always preserved automatically. + +## How it works + +The codemod walks `{DIR}` (excluding `node_modules`) and dispatches each file to +one of three transformers by extension. They share the confident mapping, +group-context detection, and skip/report rules, but each handles the reference +styles native to its language: + +| Files | Transformer | Reference styles handled | +| --------------- | ------------------------------------ | ----------------------------------------------------------------------- | +| `.css` | `transformCssSemanticColors` | CSS custom property `var(--color-*)` | +| `.scss` | `transformScssSemanticColors` | SCSS variable `$color-*` **and** CSS custom property `var(--color-*)` | +| `.tsx/.jsx/.ts` | `transformTailwindSemanticClasses` | Tailwind color utilities in `className`/`class` and `clsx`-style calls | + +CSS/SCSS use a `postcss` AST (`postcss-scss` for `.scss`); Tailwind uses the +TypeScript compiler API. Only files with at least one conversion are written. + +### The group is chosen by context + +The same primitive maps to a **different** semantic token depending on the +surface it paints. The codemod picks the group from the CSS property or the +Tailwind utility root, then applies that group's map: + +| Group | CSS/SCSS property | Tailwind root | Semantic prefix | +| ------------ | ------------------------------------------------------------ | ------------------- | --------------- | +| `background` | `background`, `background-color`, `--*background*` / `--*bg*` | `bg-` | `bg-*` | +| `text` | `color`, `--*text*` | `text-` | `text-*` | +| `foreground` | `fill`, `stroke`, `--*icon*` / `--*fill*` / `--*stroke*` | `fill-`, `stroke-` | `fg-*` | +| `border` | `border` / per-side / logical / `*-color`, `--*border*` | `border-` | `border-*` | + +So `var(--color-blue-500)` becomes `var(--bg-brand-solid)` on `background`, +`var(--text-brand-primary)` on `color`, `var(--fg-brand-primary)` on `fill`, and +`var(--border-brand)` on a border. Tailwind `fill-`/`stroke-` primitives map to +the `fg-*` utility (the foreground token name is the utility). + +Colour references in properties with **no confident group** (`box-shadow`, +`outline-color`, …) are left untouched and **not** reported — they are out of +scope. + +## What it converts + +Only **confident 1:1 mappings within a group** are rewritten. A primitive is +confident only if it backs exactly **one** semantic token in that group. + +The maps are derived by inverting the four groups in +[`semanticColorTokens.ts`](../../../design-tokens/src/js/semanticColorTokens.ts) +and **dropping collisions** — see [`semanticTokenMap.ts`](./semanticTokenMap.ts). +`semanticTokenMap.spec.ts` asserts the mirror never drifts from that source. + +Selected confident mappings (see the source for the full set): + +| Group | Primitive | Semantic token | +| ------------ | ------------ | --------------------- | +| `background` | `gray-300` | `bg-tertiary` | +| `background` | `blue-500` | `bg-brand-solid` | +| `background` | `red-400` | `bg-error-solid` | +| `text` | `purple-800` | `text-primary` | +| `text` | `gray-700` | `text-secondary` | +| `text` | `blue-500` | `text-brand-primary` | +| `foreground` | `gray-500` | `fg-tertiary` | +| `foreground` | `blue-500` | `fg-brand-primary` | +| `foreground` | `red-500` | `fg-error-primary` | +| `border` | `gray-600` | `border-primary` | +| `border` | `blue-500` | `border-brand` | + +### SCSS specifics + +- Consumer SCSS usually references Kaizen colors as **SCSS variables** + (`$color-gray-500`, imported from `@kaizen/design-tokens/sass/color`), so those + are matched in addition to raw `var(--color-*)`. Solid `$color-*` colours are + rewritten to the semantic SCSS variable (`$text-secondary`, `$bg-brand-solid`, …). +- Because the semantic `$*` variables are defined in + `@kaizen/design-tokens/sass/semantic-color`, the codemod **adds that import** + when it introduces a semantic variable and the file doesn't already import it — + cloning the style (`~` prefix / quotes) of an existing kaizen sass import. +- **Namespaced** refs (`@use` → `color.$color-*`) are left for stage 2 rather + than rewritten with an assumed namespace. + +### What is skipped (reported, never guessed) + +- **Colliding primitives** — a primitive that backs more than one token in a + group (e.g. `gray-200` → `bg-secondary` *and* `bg-secondary_hover`; `white` → + `bg-primary` *and* `bg-overlay`; `purple-800` → four `fg-*` tokens). No + confident 1:1 mapping. +- Primitives with **no mapping** in the group (e.g. an `orange-*` text colour). +- **`null` (unmapped) semantic tokens** — never a target; the primitive is only + reported if used in-group. +- **Alpha / `rgb()` / `rgba()` usages** (e.g. `rgba($color-gray-600-rgb, 0.1)`) — + the semantic tokens are solid colors, so these need a design decision. +- Dynamic/computed Tailwind class names (template literals, variables). + +## Examples + +**CSS** + +```css +/* before */ +.card { + background-color: var(--color-blue-500); + color: var(--color-gray-700); + border: 1px solid var(--color-gray-500); +} +/* after */ +.card { + background-color: var(--bg-brand-solid); + color: var(--text-secondary); + border: 1px solid var(--border-secondary); +} +``` + +**SCSS** (note the injected semantic import) + +```scss +/* before */ +@import '~@kaizen/design-tokens/sass/color'; +.card { + color: $color-gray-700; +} +/* after */ +@import '~@kaizen/design-tokens/sass/color'; +@import '~@kaizen/design-tokens/sass/semantic-color'; +.card { + color: $text-secondary; +} +``` + +**Tailwind** + +```tsx +// before +
+// after +
+``` + +## Source of truth + +Mappings mirror the four groups in +[`packages/design-tokens/src/js/semanticColorTokens.ts`](../../../design-tokens/src/js/semanticColorTokens.ts) +and are derived (inverted, collisions dropped) in +[`semanticTokenMap.ts`](./semanticTokenMap.ts). The CSS and SCSS transformers +share the postcss engine in [`semanticColorPostcss.ts`](./semanticColorPostcss.ts). + +See [`TODO.md`](./TODO.md) for known follow-ups and outliers still to review. diff --git a/packages/components/codemods/migratePrimitivesToSemanticTokens/TODO.md b/packages/components/codemods/migratePrimitivesToSemanticTokens/TODO.md new file mode 100644 index 00000000000..4386d327f2d --- /dev/null +++ b/packages/components/codemods/migratePrimitivesToSemanticTokens/TODO.md @@ -0,0 +1,54 @@ +# `migratePrimitivesToSemanticTokens` — follow-ups + +Known gaps and things to revisit. This codemod only applies **confident 1:1** +mappings today; the items below are deliberately deferred. + +- [ ] **Update once `null` semantic tokens are defined.** Many semantic tokens + are still `null` in + [`semanticColorTokens.ts`](../../../design-tokens/src/js/semanticColorTokens.ts) + (e.g. `bg-primary_alt`, `text-secondary_hover`, `fg-brand-secondary`). + They are intentionally excluded from the maps. When a designer signs off a + value, the mirror in [`semanticTokenMap.ts`](./semanticTokenMap.ts) must be + updated (the drift test in `semanticTokenMap.spec.ts` will flag it) and any + new collisions re-checked. + +- [ ] **Make the codemod runnable across package managers (pnpm / yarn / devbox).** + Usage is currently documented as `pnpm kaizen-codemod …`, and the + `kaizen-codemod` bin shells out via `npx tsx@latest`. Confirm and document + equivalents for `yarn kaizen-codemod …` / `yarn dlx`, and `devbox run …`, + and make sure the `bin/codemod.sh` path resolution and Tailwind-prefix + detection work under each (not just pnpm workspaces). + +- [ ] **Review the Divider component outlier.** Divider uses a hard-coded + primitive in a way that may not fit the `border-*` / `bg-*` group heuristic + cleanly. Confirm what surface its line paints and whether the codemod maps + it correctly (or should skip it). + +- [ ] **Review interaction states (hover / focus / `_alt`).** State-specific + semantic tokens (`bg-secondary_hover`, `text-brand-secondary_hover`, + `bg-brand-solid_hover`, the `_alt` variants) are only auto-applied where + the primitive is unambiguous. Several state pairs collide (e.g. `gray-200` + backs both `bg-secondary` and `bg-secondary_hover`) and are skipped — + confirm the codemod isn't mapping a resting colour where a hover colour was + intended, and vice versa. + +- [ ] **Fix SCSS stripping comments.** Confirm and fix cases where the + `postcss-scss` round-trip drops or mangles comments (inline `//` and block + `/* */`) in rewritten `.scss` files. Rewrites should preserve surrounding + comments verbatim; investigate `toString()` output and add a regression + test in `transformScssSemanticColors.spec.ts`. + +- [ ] **Decide Tailwind foreground scope (`fill-*`/`stroke-*` → `fg-*`).** The + codemod currently maps Tailwind `fill-*` and `stroke-*` primitives to the + `fg-*` semantic utility, and deliberately leaves `text-*` for the text + group (so icon colour expressed via `text-*` on `currentColor` is treated + as text, not foreground). Confirm this matches how consumers actually paint + icons in Tailwind — if icon colour commonly comes through `text-*`, the + foreground group may need a different (or additional) Tailwind path. + +- [ ] **Review behaviour across different JS applications.** Verify parity when + the same styles arrive via different pipelines — e.g. SCSS parsed/inlined + inside JS (CSS-in-JS, `.module.scss` imports) versus plain Tailwind classes + in `.tsx`. The Tailwind transformer only inspects `className`/`class` + attributes and `clsx`-style calls; styles reaching JS by other means may + need a dedicated path. diff --git a/packages/components/codemods/migratePrimitivesToSemanticTokens/index.ts b/packages/components/codemods/migratePrimitivesToSemanticTokens/index.ts new file mode 100644 index 00000000000..ffbb60e359f --- /dev/null +++ b/packages/components/codemods/migratePrimitivesToSemanticTokens/index.ts @@ -0,0 +1,109 @@ +import fs from 'fs' +import path from 'path' +import ts from 'typescript' +import { transformCssSemanticColors } from './transformCssSemanticColors' +import { transformScssSemanticColors } from './transformScssSemanticColors' +import { transformTailwindSemanticClasses } from './transformTailwindSemanticClasses' + +type SkipReport = { file: string; line: number; detail: string } + +/** + * Resolves the consumer's Tailwind prefix. + * + * The `kaizen-codemod` wrapper only forwards the target dir, so the prefix is + * taken from (in priority order): a `--prefix=` CLI arg (when run directly via + * tsx), the `KAIZEN_TW_PREFIX` env var, or a best-effort read of a + * `tailwind.config.*` in the current working directory. + */ +const resolveTailwindPrefix = (): string => { + const argPrefix = process.argv.find((arg) => arg.startsWith('--prefix=')) + if (argPrefix) return argPrefix.slice('--prefix='.length) + if (process.env.KAIZEN_TW_PREFIX) return process.env.KAIZEN_TW_PREFIX + + const configName = [ + 'tailwind.config.ts', + 'tailwind.config.js', + 'tailwind.config.cjs', + 'tailwind.config.mjs', + ].find((name) => fs.existsSync(path.join(process.cwd(), name))) + if (configName) { + try { + const contents = fs.readFileSync(path.join(process.cwd(), configName), 'utf8') + const match = /prefix:\s*['"`]([^'"`]+)['"`]/.exec(contents) + if (match) return match[1] + } catch { + // best effort only — fall through to no prefix + } + } + return '' +} + +const traverseDir = (dir: string, onFile: (filePath: string) => void): void => { + if (dir.includes('node_modules')) return + for (const entry of fs.readdirSync(dir)) { + const fullPath = path.join(dir, entry) + if (fs.statSync(fullPath).isDirectory()) { + traverseDir(fullPath, onFile) + } else { + onFile(fullPath) + } + } +} + +const run = (): void => { + console.log(' ~(-_- ~) Running primitives → semantic tokens transformer (~ -_-)~') + const targetDir = process.argv[2] + if (!targetDir || targetDir.startsWith('--')) { + console.error('Usage: kaizen-codemod migratePrimitivesToSemanticTokens') + process.exit(1) + } + + const prefix = resolveTailwindPrefix() + if (prefix) console.log(`Using Tailwind prefix: "${prefix}"`) + + let convertedCount = 0 + const skips: SkipReport[] = [] + + traverseDir(targetDir, (filePath) => { + const relative = path.relative(process.cwd(), filePath) + + if (filePath.endsWith('.scss') || filePath.endsWith('.css')) { + const source = fs.readFileSync(filePath, 'utf8') + const { code, converted, skipped } = filePath.endsWith('.scss') + ? transformScssSemanticColors(source) + : transformCssSemanticColors(source) + if (converted.length > 0) fs.writeFileSync(filePath, code, 'utf8') + convertedCount += converted.length + skipped.forEach((s) => + skips.push({ file: relative, line: s.line, detail: `${s.property}: ${s.value}` }), + ) + return + } + + if (/\.(tsx|jsx|ts)$/.test(filePath)) { + const source = fs.readFileSync(filePath, 'utf8') + const scriptKind = filePath.endsWith('.ts') ? ts.ScriptKind.TS : ts.ScriptKind.TSX + const { code, converted, skipped } = transformTailwindSemanticClasses(source, { + prefix, + scriptKind, + }) + if (converted.length > 0) fs.writeFileSync(filePath, code, 'utf8') + convertedCount += converted.length + skipped.forEach((s) => skips.push({ file: relative, line: s.line, detail: s.token })) + } + }) + + console.log('') + console.log(`✅ Converted ${convertedCount} primitive color token(s) to semantic tokens.`) + + if (skips.length > 0) { + console.log('') + console.log(`⚠️ SKIPPED ${skips.length} color(s) with no confident semantic mapping.`) + console.log(' Resolve these with the /semantic-colours-migration skill (stage 2):') + skips.forEach((s) => console.log(` - ${s.file}:${s.line} — ${s.detail}`)) + } else { + console.log('No ambiguous colors detected — stage 2 may not be needed.') + } +} + +run() diff --git a/packages/components/codemods/migratePrimitivesToSemanticTokens/semanticColorPostcss.ts b/packages/components/codemods/migratePrimitivesToSemanticTokens/semanticColorPostcss.ts new file mode 100644 index 00000000000..cc048cad06b --- /dev/null +++ b/packages/components/codemods/migratePrimitivesToSemanticTokens/semanticColorPostcss.ts @@ -0,0 +1,145 @@ +import postcss from 'postcss' +import { + COLOR_VAR_REFERENCE, + PRIMITIVE_TO_SEMANTIC, + SCSS_COLOR_VAR_REFERENCE, + groupForProperty, + hasAlphaColorUsage, + referencesPrimitiveColor, +} from './semanticTokenMap' + +/** + * Shared postcss engine for the CSS and SCSS semantic-colour transformers. Both + * public transformers ({@link transformCssSemanticColors}, + * {@link transformScssSemanticColors}) parse with their own syntax and delegate + * declaration rewriting here so the group-context rules, confident mapping, and + * skip/report behaviour stay identical across CSS and SCSS. + */ + +export type ConvertedToken = { + line: number + property: string + from: string + to: string +} + +export type SkippedToken = { + line: number + property: string + value: string +} + +export type SemanticColorResult = { + converted: ConvertedToken[] + skipped: SkippedToken[] +} + +/** Path to the semantic sass partial that defines the `$bg-*`/`$text-*`/`$fg-*`/`$border-*` variables. */ +const SEMANTIC_SASS_MODULE = '@kaizen/design-tokens/sass/semantic-color' + +/** + * Ensures the semantic sass partial is imported once a semantic variable has + * been introduced, otherwise the rewritten SCSS would reference an undefined + * variable and fail to compile. Clones the style (quote + `~` prefix) of an + * existing `@kaizen/design-tokens/sass/*` import so the added line matches the + * file's convention; falls back to a plain `@import` when no kaizen import + * exists. No-op when the semantic partial is already imported/used. + */ +const ensureSemanticImport = (root: postcss.Root): void => { + let kaizenImport: postcss.AtRule | undefined + let alreadyImported = false + + root.walkAtRules((atRule) => { + if (atRule.name !== 'import' && atRule.name !== 'use') return + if (atRule.params.includes('design-tokens/sass/semantic-color')) alreadyImported = true + if (!kaizenImport && atRule.params.includes('design-tokens/sass/')) kaizenImport = atRule + }) + + if (alreadyImported) return + + if (kaizenImport) { + const params = kaizenImport.params.replace( + /(design-tokens\/sass\/)[a-z-]+/i, + `$1semantic-color`, + ) + // Clone the existing import's own-line formatting so the addition sits on its + // own line rather than being appended to the source import. + kaizenImport.cloneAfter({ params, raws: { ...kaizenImport.raws, before: '\n' } }) + return + } + + root.prepend(postcss.atRule({ name: 'import', params: `'${SEMANTIC_SASS_MODULE}'` })) +} + +/** + * Walks every declaration in `root`, rewriting hard-coded primitive colours to + * the new semantic tokens for the group the declaration's property targets + * (background / text / foreground / border — see {@link groupForProperty}). + * When `scss` is true, SCSS `$color-*` variables are also rewritten and the + * semantic sass import is injected if needed. + * + * Only confident 1:1 mappings within a group are rewritten (see + * {@link PRIMITIVE_TO_SEMANTIC}). Unmapped primitives *within a recognised + * group*, and alpha/`rgb()`/`rgba()` usages, are left untouched and returned in + * `skipped` for the stage-2 fallback. Colour references in properties with no + * confident group (e.g. `box-shadow`, `outline-color`) are left untouched and + * NOT reported — they are out of scope for this codemod. + */ +export const rewriteSemanticColors = ( + root: postcss.Root, + { scss = false }: { scss?: boolean } = {}, +): SemanticColorResult => { + const converted: ConvertedToken[] = [] + const skipped: SkippedToken[] = [] + let introducedScssSemantic = false + + root.walkDecls((decl) => { + if (!referencesPrimitiveColor(decl.value)) return + + const group = groupForProperty(decl.prop) + if (!group) return // property has no confident semantic group — out of scope + + const line = decl.source?.start?.line ?? 0 + const map = PRIMITIVE_TO_SEMANTIC[group] + + // Alpha / rgb() usages are solid-color-only in the semantic set — flag for a + // design decision (stage 2) instead of guessing, and don't touch the value. + if (hasAlphaColorUsage(decl.value)) { + skipped.push({ line, property: decl.prop, value: decl.value.trim() }) + return + } + + // CSS custom property references: var(--color-X) → var(--). + let value = decl.value.replace(COLOR_VAR_REFERENCE, (match, primitive: string) => { + const semantic = map[primitive] + if (semantic) { + const replacement = `var(--${semantic})` + converted.push({ line, property: decl.prop, from: match, to: replacement }) + return replacement + } + skipped.push({ line, property: decl.prop, value: match }) + return match + }) + + // SCSS variable references: $color-X → $ (SCSS files only). + if (scss) { + value = value.replace(SCSS_COLOR_VAR_REFERENCE, (match, primitive: string) => { + const semantic = map[primitive] + if (semantic) { + const replacement = `$${semantic}` + converted.push({ line, property: decl.prop, from: match, to: replacement }) + introducedScssSemantic = true + return replacement + } + skipped.push({ line, property: decl.prop, value: match }) + return match + }) + } + + decl.value = value + }) + + if (introducedScssSemantic) ensureSemanticImport(root) + + return { converted, skipped } +} diff --git a/packages/components/codemods/migratePrimitivesToSemanticTokens/semanticTokenMap.spec.ts b/packages/components/codemods/migratePrimitivesToSemanticTokens/semanticTokenMap.spec.ts new file mode 100644 index 00000000000..dffa5b66b0d --- /dev/null +++ b/packages/components/codemods/migratePrimitivesToSemanticTokens/semanticTokenMap.spec.ts @@ -0,0 +1,90 @@ +import { semanticColorTokens } from '../../../design-tokens/src/js/semanticColorTokens' +import { + PRIMITIVE_TO_SEMANTIC, + SEMANTIC_TO_PRIMITIVE, + type SemanticGroup, + groupForProperty, +} from './semanticTokenMap' + +/** Reduce a source token value (`var(--color-gray-600)` | null) to `gray-600` | null. */ +const toPrimitive = (value: string | null): string | null => { + if (value === null) return null + const match = /var\(\s*--color-([a-z0-9-]+)\s*\)/i.exec(value) + return match ? match[1] : null +} + +describe('semanticTokenMap', () => { + describe('SEMANTIC_TO_PRIMITIVE mirror', () => { + // Guards against drift from the design-tokens source of truth. If a token's + // primitive changes (or a token is added/removed/un-nulled), this fails and + // the mirror must be updated. + const groups: SemanticGroup[] = ['background', 'text', 'foreground', 'border'] + + it.each(groups)('matches the non-null %s entries in semanticColorTokens.ts', (group) => { + const expected: Record = {} + for (const [token, value] of Object.entries(semanticColorTokens[group])) { + const primitive = toPrimitive(value) + if (primitive) expected[token] = primitive + } + expect(SEMANTIC_TO_PRIMITIVE[group]).toEqual(expected) + }) + }) + + describe('PRIMITIVE_TO_SEMANTIC (inverted, collisions dropped)', () => { + it('drops primitives that back more than one token in a group', () => { + // gray-200 → bg-secondary AND bg-secondary_hover; white → bg-primary AND bg-overlay. + expect(PRIMITIVE_TO_SEMANTIC.background).not.toHaveProperty('gray-200') + expect(PRIMITIVE_TO_SEMANTIC.background).not.toHaveProperty('white') + // yellow-400 → bg-warning-secondary AND bg-warning-solid. + expect(PRIMITIVE_TO_SEMANTIC.background).not.toHaveProperty('yellow-400') + // gray-550 → text-quaternary AND text-placeholder; white → two on-brand tokens. + expect(PRIMITIVE_TO_SEMANTIC.text).not.toHaveProperty('gray-550') + expect(PRIMITIVE_TO_SEMANTIC.text).not.toHaveProperty('white') + // purple-800 backs four fg-* tokens. + expect(PRIMITIVE_TO_SEMANTIC.foreground).not.toHaveProperty('purple-800') + }) + + it('keeps confident 1:1 mappings per group', () => { + expect(PRIMITIVE_TO_SEMANTIC.background['gray-300']).toBe('bg-tertiary') + expect(PRIMITIVE_TO_SEMANTIC.background['blue-500']).toBe('bg-brand-solid') + expect(PRIMITIVE_TO_SEMANTIC.text['gray-700']).toBe('text-secondary') + expect(PRIMITIVE_TO_SEMANTIC.text['blue-500']).toBe('text-brand-primary') + expect(PRIMITIVE_TO_SEMANTIC.foreground['gray-500']).toBe('fg-tertiary') + expect(PRIMITIVE_TO_SEMANTIC.foreground['blue-500']).toBe('fg-brand-primary') + expect(PRIMITIVE_TO_SEMANTIC.border['gray-500']).toBe('border-secondary') + }) + + it('resolves the same primitive to different tokens across groups by context', () => { + // blue-500 means something different depending on the surface it paints. + expect(PRIMITIVE_TO_SEMANTIC.background['blue-500']).toBe('bg-brand-solid') + expect(PRIMITIVE_TO_SEMANTIC.text['blue-500']).toBe('text-brand-primary') + expect(PRIMITIVE_TO_SEMANTIC.foreground['blue-500']).toBe('fg-brand-primary') + expect(PRIMITIVE_TO_SEMANTIC.border['blue-500']).toBe('border-brand') + }) + }) + + describe('groupForProperty', () => { + it('maps standard properties to their group', () => { + expect(groupForProperty('color')).toBe('text') + expect(groupForProperty('background')).toBe('background') + expect(groupForProperty('background-color')).toBe('background') + expect(groupForProperty('fill')).toBe('foreground') + expect(groupForProperty('stroke')).toBe('foreground') + expect(groupForProperty('border-color')).toBe('border') + expect(groupForProperty('border-inline-start')).toBe('border') + }) + + it('infers a group for custom properties from a keyword', () => { + expect(groupForProperty('--border-color')).toBe('border') + expect(groupForProperty('--background-hover')).toBe('background') + expect(groupForProperty('--text-color')).toBe('text') + expect(groupForProperty('--icon-fill')).toBe('foreground') + }) + + it('returns null for properties with no confident group', () => { + expect(groupForProperty('box-shadow')).toBeNull() + expect(groupForProperty('outline-color')).toBeNull() + expect(groupForProperty('--spacing')).toBeNull() + }) + }) +}) diff --git a/packages/components/codemods/migratePrimitivesToSemanticTokens/semanticTokenMap.ts b/packages/components/codemods/migratePrimitivesToSemanticTokens/semanticTokenMap.ts new file mode 100644 index 00000000000..35c51278dbe --- /dev/null +++ b/packages/components/codemods/migratePrimitivesToSemanticTokens/semanticTokenMap.ts @@ -0,0 +1,246 @@ +/** + * Confident primitive → semantic colour-token mappings for the four semantic + * groups (`background`, `text`, `foreground`, `border`). + * + * Source of truth: `packages/design-tokens/src/js/semanticColorTokens.ts`. That + * file maps a semantic token → the primitive it paints with; here we mirror the + * *mapped* (non-`null`) entries per group and **invert** them (primitive → + * semantic) because the codemod rewrites hard-coded primitives to the new + * semantic token. + * + * The mirror is duplicated here (rather than imported) so the codemod has no + * runtime dependency on `@kaizen/design-tokens` when run in a consumer repo — + * matching the sibling `migrateBorderColorsToSemanticTokens` codemod. + * `semanticTokenMap.spec.ts` asserts this mirror never drifts from the source. + * + * ### Why some primitives are intentionally absent + * A primitive is only a *confident* migration target if it maps to exactly ONE + * semantic token within its group. When a primitive backs several tokens in the + * same group (e.g. `gray-200` → both `bg-secondary` and `bg-secondary_hover`, + * `white` → both `bg-primary` and `bg-overlay`, `purple-800` → four `fg-*` + * tokens) there is no 1:1 mapping, so it is dropped by {@link invertGroup} and + * the codemod skips + reports it for the `/semantic-colours-migration` stage-2 + * fallback rather than guessing. `null` (unmapped) tokens are omitted entirely. + */ + +export type SemanticGroup = 'background' | 'text' | 'foreground' | 'border' + +/** + * semantic token name → primitive colour-token name, mirrored verbatim from the + * non-`null` entries of `semanticColorTokens.ts` (values reduced to the bare + * primitive, e.g. `var(--color-gray-600)` → `gray-600`). + */ +export const SEMANTIC_TO_PRIMITIVE: Record> = { + background: { + 'bg-primary': 'white', + 'bg-secondary': 'gray-200', + 'bg-secondary_hover': 'gray-200', + 'bg-tertiary': 'gray-300', + 'bg-primary-solid': 'purple-800', + 'bg-secondary-solid': 'gray-600', + 'bg-overlay': 'white', + 'bg-brand-primary': 'blue-100', + 'bg-brand-secondary': 'blue-200', + 'bg-brand-solid': 'blue-500', + 'bg-brand-solid_hover': 'blue-700', + 'bg-error-primary': 'red-100', + 'bg-error-secondary': 'red-300', + 'bg-error-solid': 'red-400', + 'bg-success-primary': 'green-100', + 'bg-success-secondary': 'green-300', + 'bg-success-solid': 'green-600', + 'bg-warning-primary': 'yellow-100', + 'bg-warning-secondary': 'yellow-400', + 'bg-warning-solid': 'yellow-400', + }, + text: { + 'text-primary': 'purple-800', + 'text-secondary': 'gray-700', + 'text-tertiary': 'gray-600', + 'text-quaternary': 'gray-550', + 'text-placeholder': 'gray-550', + 'text-secondary_on-brand': 'white', + 'text-quaternary_on-brand': 'white', + 'text-brand-primary': 'blue-500', + 'text-brand-secondary': 'blue-700', + 'text-brand-secondary_hover': 'blue-600', + 'text-error-primary': 'red-600', + 'text-success-primary': 'green-600', + }, + foreground: { + 'fg-primary': 'purple-800', + 'fg-secondary': 'purple-800', + 'fg-secondary_hover': 'purple-800', + 'fg-tertiary': 'gray-500', + 'fg-quaternary': 'purple-800', + 'fg-white': 'white', + 'fg-brand-primary': 'blue-500', + 'fg-error-primary': 'red-500', + 'fg-success-primary': 'green-500', + 'fg-success-secondary': 'green-400', + 'fg-warning-primary': 'yellow-700', + }, + border: { + 'border-primary': 'gray-600', + 'border-secondary': 'gray-500', + 'border-secondary_alt': 'gray-200', + 'border-tertiary': 'gray-300', + 'border-brand': 'blue-500', + 'border-brand_alt': 'blue-300', + 'border-error': 'red-500', + 'border-error_subtle': 'red-300', + }, +} + +/** + * Inverts one group's `semantic → primitive` table into `primitive → semantic`, + * dropping any primitive that backs more than one semantic token in the group + * (no confident 1:1 mapping). Those collisions are handled by stage 2. + */ +const invertGroup = (entries: Record): Record => { + const primitiveCounts = new Map() + for (const primitive of Object.values(entries)) { + primitiveCounts.set(primitive, (primitiveCounts.get(primitive) ?? 0) + 1) + } + + const inverted: Record = {} + for (const [semantic, primitive] of Object.entries(entries)) { + if (primitiveCounts.get(primitive) === 1) inverted[primitive] = semantic + } + return inverted +} + +/** + * Confident `primitive → semantic token name` map per group, derived from + * {@link SEMANTIC_TO_PRIMITIVE}. The semantic token name already carries its + * group prefix (`bg-`, `text-`, `fg-`, `border-`) so it doubles as the CSS var + * name, the SCSS variable, and the Tailwind utility. + */ +export const PRIMITIVE_TO_SEMANTIC: Record> = { + background: invertGroup(SEMANTIC_TO_PRIMITIVE.background), + text: invertGroup(SEMANTIC_TO_PRIMITIVE.text), + foreground: invertGroup(SEMANTIC_TO_PRIMITIVE.foreground), + border: invertGroup(SEMANTIC_TO_PRIMITIVE.border), +} + +/** + * Matches CSS properties that can carry a border *color*: the `border` + * shorthand, per-side/logical shorthands, and the explicit `*-color` longhands. + * Excludes `border-width`/`border-style`/`border-radius`/`border-image`, which + * never hold a color. + */ +const BORDER_COLOR_PROPERTY = + /^border(-(top|right|bottom|left|block|inline)(-(start|end))?)?(-color)?$/ + +/** + * Resolves the semantic group a *custom property* (`--foo`) targets from a + * keyword in its name (e.g. `--icon-fill-color` → foreground). Returns `null` + * when no group can be inferred, so the codemod leaves it for stage 2 rather + * than guessing. + */ +const groupForCustomProperty = (prop: string): SemanticGroup | null => { + if (prop.includes('border')) return 'border' + if (prop.includes('background') || /(^|--|-)bg(-|$)/.test(prop)) return 'background' + if (prop.includes('text')) return 'text' + if ( + prop.includes('icon') || + prop.includes('fill') || + prop.includes('stroke') || + /(^|--|-)fg(-|$)/.test(prop) + ) { + return 'foreground' + } + return null +} + +/** + * Resolves which semantic group a CSS/SCSS declaration property targets: + * - `color` → text + * - `background` / `background-color` → background + * - `fill` / `stroke` → foreground (icons / glyphs) + * - border color properties → border + * - custom properties → inferred from the name (see {@link groupForCustomProperty}) + * + * Returns `null` for properties with no confident group (e.g. `box-shadow`, + * `outline-color`); the codemod then leaves the declaration untouched. + */ +export const groupForProperty = (property: string): SemanticGroup | null => { + const prop = property.trim().toLowerCase() + if (prop.startsWith('--')) return groupForCustomProperty(prop) + if (BORDER_COLOR_PROPERTY.test(prop)) return 'border' + if (prop === 'color') return 'text' + if (prop === 'background' || prop === 'background-color') return 'background' + if (prop === 'fill' || prop === 'stroke') return 'foreground' + return null +} + +/** Matches a `var(--color-)` reference and captures the primitive name. */ +export const COLOR_VAR_REFERENCE = /var\(\s*--color-([a-z0-9-]+)\s*\)/gi + +/** + * Matches a solid `$color-` SCSS variable reference (the form consumers + * get from `@import '@kaizen/design-tokens/sass/color'`) and captures the + * primitive name. Matches shade-less primitives (`$color-white`) as well as + * `$color-gray-600`. Deliberately does NOT match the `-rgb`/`-id` companions + * (`$color-gray-600-rgb`) — the trailing `(?![\w-])` stops before the `-rgb`. + * A leading `\w`/`.`/`-` is disallowed so namespaced (`color.$color-…`) refs are + * left for stage 2 rather than mis-rewritten. + */ +export const SCSS_COLOR_VAR_REFERENCE = /(? + /var\(\s*--color-/i.test(value) || /(? + /\brgba?\(/i.test(value) || /\$color-[a-z0-9-]+-rgb\b/i.test(value) + +/** Tailwind utility roots and the semantic group each targets. */ +export const UTILITY_ROOT_GROUP: Record = { + bg: 'background', + text: 'text', + fill: 'foreground', + stroke: 'foreground', + border: 'border', +} + +/** Primitive colour families used to recognise a Tailwind *color* utility. */ +const COLOR_FAMILIES = 'gray|blue|red|green|yellow|orange|purple|teal|pink|white|black' + +/** Tailwind utility roots, alternation-ready. */ +const UTILITY_ROOTS = Object.keys(UTILITY_ROOT_GROUP).join('|') + +/** + * Matches a named color utility and captures `[root, primitive]`, e.g. + * `bg-gray-600` → `['bg', 'gray-600']`, `fill-white` → `['fill', 'white']`. + */ +export const NAMED_COLOR_UTILITY = new RegExp( + `^(${UTILITY_ROOTS})-((?:${COLOR_FAMILIES})(?:-\\d+)?)$`, + 'i', +) + +/** + * Matches an arbitrary-value color utility and captures `[root, primitive]`, + * e.g. `bg-[var(--color-gray-600)]` → `['bg', 'gray-600']`. + */ +export const ARBITRARY_COLOR_UTILITY = new RegExp( + `^(${UTILITY_ROOTS})-\\[var\\(\\s*--color-([a-z0-9-]+)\\s*\\)\\]$`, + 'i', +) + +/** + * Heuristic for *any* Tailwind color utility (named or arbitrary) so unmapped + * ones can be reported (skipped) rather than silently ignored. Excludes + * structural utilities (`border-2`, `bg-cover`, `text-sm`, `stroke-2`) and + * already-semantic classes (`bg-secondary-solid`). + */ +export const COLOR_UTILITY = new RegExp( + `^(${UTILITY_ROOTS})-(?:${COLOR_FAMILIES})(?:-\\d+)?$|^(${UTILITY_ROOTS})-\\[.+\\]$`, + 'i', +) diff --git a/packages/components/codemods/migratePrimitivesToSemanticTokens/transformCssSemanticColors.spec.ts b/packages/components/codemods/migratePrimitivesToSemanticTokens/transformCssSemanticColors.spec.ts new file mode 100644 index 00000000000..2be742f0704 --- /dev/null +++ b/packages/components/codemods/migratePrimitivesToSemanticTokens/transformCssSemanticColors.spec.ts @@ -0,0 +1,80 @@ +import { transformCssSemanticColors } from './transformCssSemanticColors' + +describe('transformCssSemanticColors()', () => { + it('rewrites a text color (color → text-*)', () => { + const { code, converted } = transformCssSemanticColors('.a { color: var(--color-gray-700); }') + expect(code).toContain('color: var(--text-secondary);') + expect(converted).toHaveLength(1) + expect(converted[0]).toMatchObject({ to: 'var(--text-secondary)' }) + }) + + it('rewrites a background color (background / background-color → bg-*)', () => { + const { code } = transformCssSemanticColors( + '.a { background: var(--color-blue-500); } .b { background-color: var(--color-gray-300); }', + ) + expect(code).toContain('background: var(--bg-brand-solid);') + expect(code).toContain('background-color: var(--bg-tertiary);') + }) + + it('rewrites a foreground color (fill / stroke → fg-*)', () => { + const { code } = transformCssSemanticColors( + '.a { fill: var(--color-red-500); stroke: var(--color-blue-500); }', + ) + expect(code).toContain('fill: var(--fg-error-primary);') + expect(code).toContain('stroke: var(--fg-brand-primary);') + }) + + it('rewrites a border color (border → border-*)', () => { + const { code } = transformCssSemanticColors( + '.a { border: 1px solid var(--color-gray-500); }', + ) + expect(code).toContain('border: 1px solid var(--border-secondary);') + }) + + it('maps the same primitive to a different token per property (context)', () => { + // blue-500 → bg-brand-solid on background, text-brand-primary on color. + const { code } = transformCssSemanticColors( + '.a { background: var(--color-blue-500); color: var(--color-blue-500); }', + ) + expect(code).toContain('background: var(--bg-brand-solid);') + expect(code).toContain('color: var(--text-brand-primary);') + }) + + it('rewrites a group-inferred custom property', () => { + const { code } = transformCssSemanticColors('.a { --text-color: var(--color-purple-800); }') + expect(code).toContain('--text-color: var(--text-primary);') + }) + + it('skips and reports colliding primitives (no confident 1:1 mapping)', () => { + // gray-200 backs both bg-secondary and bg-secondary_hover. + const { code, converted, skipped } = transformCssSemanticColors( + '.a { background: var(--color-gray-200); }', + ) + expect(code).toContain('background: var(--color-gray-200);') + expect(converted).toHaveLength(0) + expect(skipped).toHaveLength(1) + expect(skipped[0]).toMatchObject({ property: 'background', value: 'var(--color-gray-200)' }) + }) + + it('skips and reports primitives with no mapping in the group', () => { + const { skipped } = transformCssSemanticColors('.a { color: var(--color-orange-500); }') + expect(skipped).toHaveLength(1) + }) + + it('skips and reports alpha / rgb() usages for a design decision', () => { + const { code, converted, skipped } = transformCssSemanticColors( + '.a { background: rgba(var(--color-blue-500), 0.5); }', + ) + expect(code).toContain('rgba(var(--color-blue-500), 0.5)') + expect(converted).toHaveLength(0) + expect(skipped).toHaveLength(1) + }) + + it('leaves colors in out-of-scope properties untouched and unreported', () => { + const input = '.a { box-shadow: 0 0 0 1px var(--color-gray-500); outline-color: var(--color-red-500); }' + const { code, converted, skipped } = transformCssSemanticColors(input) + expect(code).toBe(input) + expect(converted).toHaveLength(0) + expect(skipped).toHaveLength(0) + }) +}) diff --git a/packages/components/codemods/migratePrimitivesToSemanticTokens/transformCssSemanticColors.ts b/packages/components/codemods/migratePrimitivesToSemanticTokens/transformCssSemanticColors.ts new file mode 100644 index 00000000000..55aa601cea6 --- /dev/null +++ b/packages/components/codemods/migratePrimitivesToSemanticTokens/transformCssSemanticColors.ts @@ -0,0 +1,31 @@ +import postcss from 'postcss' +import { + rewriteSemanticColors, + type ConvertedToken, + type SemanticColorResult, + type SkippedToken, +} from './semanticColorPostcss' + +export type { ConvertedToken, SkippedToken } + +export type CssTransformResult = SemanticColorResult & { code: string } + +/** + * Rewrites hard-coded primitive colours to the new semantic tokens in plain + * **CSS**, matching CSS custom property references and selecting the semantic + * group from the declaration property: + * `color: var(--color-gray-700)` → `color: var(--text-secondary)` + * `background-color: var(--color-blue-500)` → `background-color: var(--bg-brand-solid)` + * `fill: var(--color-red-500)` → `fill: var(--fg-error-primary)` + * `border-color: var(--color-gray-500)` → `border-color: var(--border-secondary)` + * + * SCSS `$variable` references are handled by {@link transformScssSemanticColors}. + * Only confident 1:1 mappings within a group are rewritten; unmapped and + * alpha/`rgb()` colours are left untouched and returned in `skipped` for the + * stage-2 fallback. + */ +export const transformCssSemanticColors = (source: string): CssTransformResult => { + const root = postcss.parse(source) + const { converted, skipped } = rewriteSemanticColors(root, { scss: false }) + return { code: root.toString(), converted, skipped } +} diff --git a/packages/components/codemods/migratePrimitivesToSemanticTokens/transformScssSemanticColors.spec.ts b/packages/components/codemods/migratePrimitivesToSemanticTokens/transformScssSemanticColors.spec.ts new file mode 100644 index 00000000000..47eda9eb0c1 --- /dev/null +++ b/packages/components/codemods/migratePrimitivesToSemanticTokens/transformScssSemanticColors.spec.ts @@ -0,0 +1,82 @@ +import { transformScssSemanticColors } from './transformScssSemanticColors' + +describe('transformScssSemanticColors()', () => { + it('rewrites SCSS $color-* variables to the semantic variable per group', () => { + const input = `@import "~@kaizen/design-tokens/sass/color"; +.a { + color: $color-gray-700; + background: $color-blue-500; +}` + const { code, converted } = transformScssSemanticColors(input) + expect(code).toContain('color: $text-secondary;') + expect(code).toContain('background: $bg-brand-solid;') + expect(converted).toHaveLength(2) + }) + + it('rewrites CSS custom property references inside SCSS too', () => { + const input = `.a { + &:hover { color: var(--color-gray-700); } +}` + const { code } = transformScssSemanticColors(input) + expect(code).toContain('color: var(--text-secondary);') + }) + + it('rewrites shade-less primitives ($color-white → fg-white in a fill context)', () => { + const { code } = transformScssSemanticColors('.a { fill: $color-white; }') + expect(code).toContain('fill: $fg-white;') + }) + + it('adds the semantic-color sass import (matching existing style) when introducing a semantic var', () => { + const input = `@import "~@kaizen/design-tokens/sass/color"; +.a { + color: $color-gray-700; +}` + const { code } = transformScssSemanticColors(input) + expect(code).toContain('@import "~@kaizen/design-tokens/sass/semantic-color";') + expect(code).toContain('color: $text-secondary;') + }) + + it('prepends a plain semantic-color import when no kaizen sass import exists', () => { + const { code } = transformScssSemanticColors('.a { background: $color-blue-500; }') + expect(code).toContain("@import '@kaizen/design-tokens/sass/semantic-color';") + expect(code).toContain('background: $bg-brand-solid;') + }) + + it('does not duplicate the semantic-color import when already present', () => { + const input = `@import "~@kaizen/design-tokens/sass/color"; +@import "~@kaizen/design-tokens/sass/semantic-color"; +.a { + color: $color-gray-700; +}` + const { code } = transformScssSemanticColors(input) + expect(code.match(/sass\/semantic-color/g)).toHaveLength(1) + }) + + it('skips and reports rgba()/alpha usages for a design decision', () => { + const input = `@import "~@kaizen/design-tokens/sass/color"; +.footer { + background: rgba($color-gray-600-rgb, 0.1); +}` + const { code, converted, skipped } = transformScssSemanticColors(input) + expect(code).toContain('background: rgba($color-gray-600-rgb, 0.1);') + expect(converted).toHaveLength(0) + expect(skipped).toHaveLength(1) + expect(skipped[0]).toMatchObject({ property: 'background' }) + }) + + it('skips and reports colliding / unmapped $color-* variables', () => { + const input = '.a { background: $color-gray-200; color: $color-gray-400; }' + const { code, converted, skipped } = transformScssSemanticColors(input) + expect(code).toContain('background: $color-gray-200;') + expect(code).toContain('color: $color-gray-400;') + expect(converted).toHaveLength(0) + expect(skipped).toHaveLength(2) + }) + + it('leaves out-of-scope $color-* usages untouched', () => { + const input = '.a { box-shadow: 0 0 1px $color-gray-500; }' + const { code, converted } = transformScssSemanticColors(input) + expect(code).toBe(input) + expect(converted).toHaveLength(0) + }) +}) diff --git a/packages/components/codemods/migratePrimitivesToSemanticTokens/transformScssSemanticColors.ts b/packages/components/codemods/migratePrimitivesToSemanticTokens/transformScssSemanticColors.ts new file mode 100644 index 00000000000..a3bc4ad3586 --- /dev/null +++ b/packages/components/codemods/migratePrimitivesToSemanticTokens/transformScssSemanticColors.ts @@ -0,0 +1,32 @@ +import scssSyntax from 'postcss-scss' +import { + rewriteSemanticColors, + type ConvertedToken, + type SemanticColorResult, + type SkippedToken, +} from './semanticColorPostcss' + +export type { ConvertedToken, SkippedToken } + +export type ScssTransformResult = SemanticColorResult & { code: string } + +/** + * Rewrites hard-coded primitive colours to the new semantic tokens in **SCSS**, + * covering both reference styles a `.scss` file can use and selecting the + * semantic group from the declaration property: + * - SCSS variable (Kaizen sass): `color: $color-gray-700` → `$text-secondary` + * - CSS custom property: `background-color: var(--color-blue-500)` → `var(--bg-brand-solid)` + * + * When a semantic `$*` variable is introduced, the + * `@kaizen/design-tokens/sass/semantic-color` import is added (matching the + * file's existing import style) so the output still compiles. Only confident + * 1:1 mappings within a group are rewritten; unmapped colours and + * alpha/`rgb()`/`rgba()` usages such as `rgba($color-gray-600-rgb, 0.1)` are + * left untouched and returned in `skipped` for the stage-2 fallback. Nested + * rules, `@layer`, and other SCSS constructs are preserved by the SCSS parser. + */ +export const transformScssSemanticColors = (source: string): ScssTransformResult => { + const root = scssSyntax.parse(source) + const { converted, skipped } = rewriteSemanticColors(root, { scss: true }) + return { code: root.toString(), converted, skipped } +} diff --git a/packages/components/codemods/migratePrimitivesToSemanticTokens/transformTailwindSemanticClasses.spec.ts b/packages/components/codemods/migratePrimitivesToSemanticTokens/transformTailwindSemanticClasses.spec.ts new file mode 100644 index 00000000000..0ff65a06b8c --- /dev/null +++ b/packages/components/codemods/migratePrimitivesToSemanticTokens/transformTailwindSemanticClasses.spec.ts @@ -0,0 +1,78 @@ +import { transformTailwindSemanticClasses } from './transformTailwindSemanticClasses' + +describe('transformTailwindSemanticClasses()', () => { + it('rewrites bg / text / border color utilities in a className attribute', () => { + const input = `const A = () =>
` + const { code, converted } = transformTailwindSemanticClasses(input) + expect(code).toContain('className="bg-brand-solid text-secondary border-secondary p-2"') + expect(converted).toHaveLength(3) + }) + + it('maps fill / stroke utilities to the fg-* semantic utility', () => { + const input = `const A = () =>
` + const { code } = transformTailwindSemanticClasses(input) + expect(code).toContain('className="fg-error-primary fg-brand-primary"') + }) + + it('maps the same primitive to a different utility per root (context)', () => { + const input = `const A = () =>
` + const { code } = transformTailwindSemanticClasses(input) + expect(code).toContain('bg-brand-solid') + expect(code).toContain('text-brand-primary') + expect(code).toContain('border-brand') + }) + + it('rewrites an arbitrary-value utility', () => { + const input = `const A = () =>
` + const { code } = transformTailwindSemanticClasses(input) + expect(code).toContain('className="bg-brand-solid"') + }) + + it('rewrites classes inside a clsx call, including object keys', () => { + const input = `const A = () =>
` + const { code } = transformTailwindSemanticClasses(input) + expect(code).toContain("'text-secondary'") + expect(code).toContain("'bg-brand-solid'") + }) + + it('preserves a Tailwind utility prefix (goals-)', () => { + const input = `const A = () =>
` + const { code, converted } = transformTailwindSemanticClasses(input, { prefix: 'goals-' }) + expect(code).toContain('className="goals-bg-brand-solid"') + expect(converted[0]).toMatchObject({ to: 'goals-bg-brand-solid' }) + }) + + it('preserves a colon namespace prefix (EP:) and stacked variants', () => { + const input = `const A = () =>
` + const { code } = transformTailwindSemanticClasses(input) + expect(code).toContain('EP:bg-brand-solid') + expect(code).toContain('hover:text-secondary') + }) + + it('skips dynamic class names and reports unmapped / colliding color utilities', () => { + const input = `const A = () =>
` + const { code, converted, skipped } = transformTailwindSemanticClasses(input) + expect(converted).toHaveLength(0) + expect(code).toContain('bg-gray-200') + expect(code).toContain('text-white') + expect(skipped).toEqual([ + { line: 1, token: 'bg-gray-200' }, + { line: 1, token: 'text-white' }, + ]) + }) + + it('leaves structural and already-semantic utilities untouched', () => { + const input = `const A = () =>
` + const { code, converted, skipped } = transformTailwindSemanticClasses(input) + expect(code).toBe(input) + expect(converted).toHaveLength(0) + expect(skipped).toHaveLength(0) + }) + + it('leaves non-className strings untouched', () => { + const input = `const label = "bg-blue-500"` + const { code, converted } = transformTailwindSemanticClasses(input) + expect(code).toBe(input) + expect(converted).toHaveLength(0) + }) +}) diff --git a/packages/components/codemods/migratePrimitivesToSemanticTokens/transformTailwindSemanticClasses.ts b/packages/components/codemods/migratePrimitivesToSemanticTokens/transformTailwindSemanticClasses.ts new file mode 100644 index 00000000000..5741de3e811 --- /dev/null +++ b/packages/components/codemods/migratePrimitivesToSemanticTokens/transformTailwindSemanticClasses.ts @@ -0,0 +1,182 @@ +import ts from 'typescript' +import { + ARBITRARY_COLOR_UTILITY, + COLOR_UTILITY, + NAMED_COLOR_UTILITY, + PRIMITIVE_TO_SEMANTIC, + UTILITY_ROOT_GROUP, +} from './semanticTokenMap' + +export type ConvertedClass = { line: number; from: string; to: string } +export type SkippedClass = { line: number; token: string } + +export type TailwindTransformResult = { + code: string + converted: ConvertedClass[] + skipped: SkippedClass[] +} + +/** JSX attributes whose string value is a class list. */ +const CLASSNAME_ATTRIBUTES = new Set(['className', 'class']) +/** Call expressions whose string arguments are class names. */ +const CLASSNAME_FUNCTIONS = new Set(['clsx', 'classnames', 'classNames', 'cx', 'cn']) + +type TokenResult = + | { status: 'converted'; token: string } + | { status: 'skipped' } + | { status: 'unchanged' } + +/** + * Resolves the semantic utility for a bare Tailwind color utility (variant / + * prefix already stripped), or `null` if it isn't a color utility we recognise. + * The semantic token name already carries its group prefix (`bg-`, `text-`, + * `fg-`, `border-`) so it doubles as the replacement utility — a `fill-`/ + * `stroke-` primitive therefore maps to an `fg-*` utility. + */ +const mapUtility = (utility: string): { mapped: string } | 'skip' | null => { + const named = NAMED_COLOR_UTILITY.exec(utility) + const arbitrary = named ? null : ARBITRARY_COLOR_UTILITY.exec(utility) + const match = named ?? arbitrary + if (match) { + const root = match[1].toLowerCase() + const primitive = match[2].toLowerCase() + const group = UTILITY_ROOT_GROUP[root] + const semantic = group && PRIMITIVE_TO_SEMANTIC[group][primitive] + if (semantic) return { mapped: semantic } + return 'skip' + } + // A color utility we can't confidently map (unmapped family / arbitrary) — + // report for stage 2. + if (COLOR_UTILITY.test(utility)) return 'skip' + return null +} + +/** + * Transforms a single class token, preserving any variant chain (`hover:`, + * `md:`, or a namespace prefix like `EP:`) and any configured utility prefix + * (Tailwind `prefix`, like `goals-`). Only the utility portion is matched + * against the color maps; the prefix/variant is re-attached verbatim. + */ +const transformToken = (token: string, prefix: string): TokenResult => { + // Split off the variant chain: everything up to and including the last colon. + // This handles stacked variants (`hover:md:`) and colon-style prefixes (`EP:`). + const lastColon = token.lastIndexOf(':') + const variant = lastColon >= 0 ? token.slice(0, lastColon + 1) : '' + let utility = lastColon >= 0 ? token.slice(lastColon + 1) : token + + // Strip a configured dash-style utility prefix (e.g. `goals-`) so we can match + // the bare utility, then re-apply it. Colon-style prefixes are already handled + // by the variant split above. + let utilityPrefix = '' + if (prefix && !prefix.endsWith(':') && utility.startsWith(prefix)) { + utilityPrefix = prefix + utility = utility.slice(prefix.length) + } + + const result = mapUtility(utility) + if (result === null) return { status: 'unchanged' } + if (result === 'skip') return { status: 'skipped' } + return { status: 'converted', token: `${variant}${utilityPrefix}${result.mapped}` } +} + +const transformClassValue = ( + text: string, + prefix: string, + line: number, + converted: ConvertedClass[], + skipped: SkippedClass[], +): { value: string; changed: boolean } => { + let changed = false + const value = text + .split(/(\s+)/) // keep whitespace separators so spacing is preserved + .map((part) => { + if (part.trim() === '') return part + const result = transformToken(part, prefix) + if (result.status === 'converted') { + converted.push({ line, from: part, to: result.token }) + changed = true + return result.token + } + if (result.status === 'skipped') skipped.push({ line, token: part }) + return part + }) + .join('') + return { value, changed } +} + +/** + * Rewrites Tailwind color utilities (`bg-*`, `text-*`, `fill-*`, `stroke-*`, + * `border-*`) in `className`/`class` attributes and `clsx`-style calls to the + * new semantic utilities, honouring a consumer Tailwind `prefix` (e.g. `goals-` + * or `EP:`). + * + * Edits are spliced back into the original source by node position, so file + * formatting is otherwise preserved (run prettier afterwards regardless). + * Dynamic/computed class names and unmapped color utilities are left untouched; + * unmapped color utilities are returned in `skipped` for the stage-2 fallback. + */ +export const transformTailwindSemanticClasses = ( + source: string, + { + prefix = '', + scriptKind = ts.ScriptKind.TSX, + }: { prefix?: string; scriptKind?: ts.ScriptKind } = {}, +): TailwindTransformResult => { + const sourceFile = ts.createSourceFile( + 'temp.tsx', + source, + ts.ScriptTarget.Latest, + true, + scriptKind, + ) + + const converted: ConvertedClass[] = [] + const skipped: SkippedClass[] = [] + // Inner-text edits keyed by start position to avoid processing a literal twice + // (e.g. a clsx call that also lives inside a className attribute). + const edits = new Map() + + const collectFromStringLiteral = (node: ts.StringLiteralLike): void => { + const start = node.getStart(sourceFile) + if (edits.has(start)) return + const line = sourceFile.getLineAndCharacterOfPosition(start).line + 1 + const { value, changed } = transformClassValue(node.text, prefix, line, converted, skipped) + if (changed) { + // Replace the inner text only, leaving the surrounding quotes/backticks intact. + edits.set(start, { start: start + 1, end: node.getEnd() - 1, text: value }) + } else { + edits.set(start, { start, end: start, text: '' }) // mark as seen, no-op + } + } + + const collectStrings = (node: ts.Node): void => { + if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) { + collectFromStringLiteral(node) + return + } + ts.forEachChild(node, collectStrings) + } + + const visit = (node: ts.Node): void => { + if (ts.isJsxAttribute(node) && CLASSNAME_ATTRIBUTES.has(node.name.getText(sourceFile))) { + if (node.initializer) collectStrings(node.initializer) + } + if (ts.isCallExpression(node) && CLASSNAME_FUNCTIONS.has(node.expression.getText(sourceFile))) { + node.arguments.forEach(collectStrings) + } + ts.forEachChild(node, visit) + } + visit(sourceFile) + + // Apply edits back-to-front so earlier offsets stay valid. + const realEdits = Array.from(edits.values()) + .filter((edit) => edit.end > edit.start) + .sort((a, b) => b.start - a.start) + + let code = source + for (const edit of realEdits) { + code = code.slice(0, edit.start) + edit.text + code.slice(edit.end) + } + + return { code, converted, skipped } +} From 36d5105642ba48337d659c22371927709f393200 Mon Sep 17 00:00:00 2001 From: AliceMenzie Date: Thu, 2 Jul 2026 14:19:06 +1000 Subject: [PATCH 23/25] stage 1 colour migration --- .../components/src/Avatar/Avatar.module.css | 6 +- .../src/AvatarGroup/AvatarGroup.module.css | 2 +- .../components/src/Badge/Badge.module.css | 16 ++--- .../src/BrandMoment/BrandMoment.module.css | 10 +-- .../components/src/Button/Button.module.css | 36 +++++----- .../src/ButtonGroup/ButtonGroup.module.css | 2 +- .../src/ButtonGroup/ButtonGroup.module.scss | 3 +- .../src/ButtonV1/Button/Button.module.scss | 29 +++++---- .../CalendarRange/CalendarRange.module.scss | 13 ++-- .../CalendarSingle/CalendarSingle.module.scss | 3 +- .../LegacyCalendarRange.module.scss | 11 ++-- .../baseCalendarClassNames.module.scss | 37 ++++++----- packages/components/src/Card/Card.module.css | 18 ++--- .../src/ClearButton/ClearButton.module.css | 2 +- .../Collapsible/Collapsible.module.scss | 18 ++--- .../CollapsibleGroup.module.scss | 6 +- .../ExpertAdviceCollapsible.module.scss | 5 +- .../DateInputWithIconButton.module.css | 8 +-- .../src/DatePicker/DatePicker.module.css | 2 +- .../DateRangePicker.module.scss | 17 ++--- .../src/EmptyState/EmptyState.module.css | 10 +-- .../_docs/FieldGroup.stickersheet.stories.tsx | 4 +- .../FieldGroup/_docs/FieldGroup.stories.tsx | 10 +-- .../src/FieldMessage/FieldMessage.module.css | 10 +-- .../FilterButtonBase.module.scss | 11 ++-- .../MenuPopup/MenuPopup.module.css | 2 +- .../MultiSelectOption.module.scss | 23 +++---- .../SelectionControlButton.module.scss | 9 +-- .../GuidanceBlock/GuidanceBlock.module.css | 14 ++-- .../components/src/Heading/Heading.module.css | 8 +-- .../src/Icon/_docs/Icon.docs.module.css | 2 +- .../src/Icon/_docs/Icon.docs.stories.tsx | 8 +-- .../Icon/_docs/Icon.stickersheet.stories.tsx | 2 +- .../src/IconV1/_docs/Icon.docs.stories.tsx | 2 +- .../subcomponents/Base/Base.module.scss | 13 ++-- .../src/Input/Input/Input.module.scss | 37 ++++++----- .../Input/InputSearch/InputSearch.module.scss | 35 +++++----- .../components/src/Label/Label.module.css | 2 +- .../src/LikertScale/LikertScale.module.scss | 7 +- packages/components/src/Link/Link.module.css | 12 ++-- .../LoadingParagraph.module.scss | 5 +- packages/components/src/Menu/Menu.module.css | 2 +- .../components/src/Menu/MenuItem.module.css | 6 +- .../MenuDropdown/MenuDropdown.module.scss | 3 +- .../MenuHeading/MenuHeading.module.scss | 3 +- .../MenuItem/MenuItem.module.scss | 23 +++---- .../ConfirmationModal.module.scss | 29 +++++---- .../_docs/ConfirmationModal.stories.tsx | 2 +- .../ContextModal/ContextModal.module.scss | 3 +- .../_docs/ContextModal.stories.tsx | 2 +- .../GenericModal/GenericModal.module.scss | 15 +++-- .../_docs/GenericModal.spec.stories.tsx | 2 +- .../_docs/GenericModal.stories.tsx | 2 +- .../InputEditModal/InputEditModal.module.scss | 3 +- .../_docs/InputEditModal.stories.tsx | 4 +- .../Checkbox/Checkbox.module.scss | 15 +++-- .../MultiSelectOptionField.module.scss | 17 ++--- ...SelectOptionField.stickersheet.stories.tsx | 2 +- .../MultiSelectToggle.module.scss | 13 ++-- .../subcomponents/Popover/Popover.module.scss | 3 +- .../_docs/Popover.stickersheet.stories.tsx | 2 +- .../GenericNotification.module.css | 36 +++++----- .../src/Pagination/Pagination.module.scss | 13 ++-- .../DirectionalLink.module.scss | 5 +- .../PaginationLink/PaginationLink.module.scss | 7 +- .../src/Popover/Popover.module.scss | 23 +++---- .../src/ProgressBar/ProgressBar.module.css | 6 +- .../subcomponents/Label/Label.module.css | 2 +- .../src/Radio/Radio/Radio.module.css | 9 +-- .../Radio/RadioField/RadioField.module.css | 2 +- .../EditableRichTextContent.module.scss | 5 +- .../RichTextEditor/RichTextEditor.module.scss | 11 ++-- .../ToggleIconButton.module.scss | 23 +++---- .../src/RichTextEditor/_mixins.scss | 9 +-- .../components/src/Select/Select.module.scss | 65 ++++++++++--------- .../_docs/SingleSelect.stories.tsx | 2 +- .../subcomponents/Option/Option.module.scss | 17 ++--- .../SelectToggle/SelectToggle.module.scss | 17 ++--- .../components/src/Table/Table.module.scss | 47 +++++++------- .../src/Tabs/subcomponents/Tab/Tab.module.css | 14 ++-- .../subcomponents/TabList/TabList.module.css | 14 ++-- .../TabPanel/TabPanel.module.css | 2 +- packages/components/src/Tag/Tag.module.css | 42 ++++++------ packages/components/src/Text/Text.module.css | 8 +-- .../src/TextArea/TextArea.module.css | 16 +++-- .../GenericTile/GenericTile.module.css | 4 +- .../src/TimeField/TimeField.module.css | 13 ++-- .../TimeSegment/TimeSegment.module.css | 6 +- .../src/TitleBlock/TitleBlock.module.scss | 57 ++++++++-------- .../subcomponents/NavigationTabs.module.scss | 11 ++-- .../TitleBlockMenuItem.module.scss | 25 +++---- .../ToggleSwitch/ToggleSwitch.module.css | 8 +-- .../src/Tooltip/OverlayArrow.module.css | 2 +- .../components/src/Tooltip/Tooltip.module.css | 4 +- .../src/TooltipV1/Tooltip.module.scss | 37 ++++++----- packages/components/src/Well/Well.module.css | 18 ++--- .../ProgressStepper.module.css | 8 +-- .../ComboBoxTrigger.module.css | 12 ++-- .../ListItem/ListItem.module.css | 12 ++-- .../SelectTrigger/SelectTrigger.module.css | 12 ++-- .../subcomponents/RemoveButton.module.scss | 3 +- .../src/__next__/Tag/Tag/Tag.module.scss | 17 ++--- 102 files changed, 657 insertions(+), 608 deletions(-) diff --git a/packages/components/src/Avatar/Avatar.module.css b/packages/components/src/Avatar/Avatar.module.css index b4a5849c2a9..28646f04352 100644 --- a/packages/components/src/Avatar/Avatar.module.css +++ b/packages/components/src/Avatar/Avatar.module.css @@ -2,7 +2,7 @@ .wrapper { --avatar-x-y: 1.5rem; - background: var(--color-gray-300); + background: var(--bg-tertiary); border-radius: 100%; box-sizing: border-box; overflow: hidden; @@ -44,7 +44,7 @@ } .otherUser { - background: var(--color-gray-300); + background: var(--bg-tertiary); } .company { @@ -86,7 +86,7 @@ .initials { box-sizing: border-box; - color: var(--color-purple-800); + color: var(--text-primary); padding-left: 5px; padding-right: 5px; text-align: center; diff --git a/packages/components/src/AvatarGroup/AvatarGroup.module.css b/packages/components/src/AvatarGroup/AvatarGroup.module.css index 81a7a76d128..b7c41fe42b3 100644 --- a/packages/components/src/AvatarGroup/AvatarGroup.module.css +++ b/packages/components/src/AvatarGroup/AvatarGroup.module.css @@ -9,7 +9,7 @@ .AvatarCounter { direction: ltr; align-items: center; - background: var(--color-gray-300); + background: var(--bg-tertiary); border: 3px solid var(--color-white); border-radius: 100%; box-sizing: border-box; diff --git a/packages/components/src/Badge/Badge.module.css b/packages/components/src/Badge/Badge.module.css index a133f73b62a..61e6afe5322 100644 --- a/packages/components/src/Badge/Badge.module.css +++ b/packages/components/src/Badge/Badge.module.css @@ -1,7 +1,7 @@ @layer kz-components { .badge { border-radius: var(--spacing-12); - color: var(--color-purple-800); + color: var(--text-primary); display: inline-block; position: relative; font-family: var(--typography-paragraph-extra-small-font-family); @@ -12,7 +12,7 @@ padding: 1px var(--spacing-6); min-width: 8px; text-align: center; - background-color: var(--badge-background-color, var(--color-gray-300)); + background-color: var(--badge-background-color, var(--bg-tertiary)); } .reversed { @@ -22,9 +22,9 @@ } .reversed.active { - --badge-background-color: var(--color-green-300); + --badge-background-color: var(--bg-success-secondary); - color: var(--color-purple-800); + color: var(--text-primary); } .reversed.dark { @@ -45,7 +45,7 @@ } .active { - --badge-background-color: var(--color-blue-500); + --badge-background-color: var(--bg-brand-solid); color: var(--color-white); } @@ -53,11 +53,11 @@ .dark { --badge-background-color: rgb(var(--color-purple-700-rgb), 0.1); - color: var(--color-purple-800); + color: var(--text-primary); } .dot { - --badge-background-color: var(--color-green-300); + --badge-background-color: var(--bg-success-secondary); padding: var(--spacing-6); min-width: unset; @@ -92,7 +92,7 @@ } .animationOn .badge.active { - --badge-background-color: var(--color-blue-500); + --badge-background-color: var(--bg-brand-solid); color: var(--color-white); } diff --git a/packages/components/src/BrandMoment/BrandMoment.module.css b/packages/components/src/BrandMoment/BrandMoment.module.css index 1490f5d1894..c4ac3795cae 100644 --- a/packages/components/src/BrandMoment/BrandMoment.module.css +++ b/packages/components/src/BrandMoment/BrandMoment.module.css @@ -10,24 +10,24 @@ /** @deprecated */ .positive { - --brand-moment-background-color: var(--color-green-100); + --brand-moment-background-color: var(--bg-success-primary); } .negative { - --brand-moment-background-color: var(--color-red-100); + --brand-moment-background-color: var(--bg-error-primary); } /** end @deprecated */ .informative { - --brand-moment-background-color: var(--color-blue-100); + --brand-moment-background-color: var(--bg-brand-primary); } .success { - --brand-moment-background-color: var(--color-green-100); + --brand-moment-background-color: var(--bg-success-primary); } .warning { - --brand-moment-background-color: var(--color-red-100); + --brand-moment-background-color: var(--bg-error-primary); } .container { diff --git a/packages/components/src/Button/Button.module.css b/packages/components/src/Button/Button.module.css index 9e915131270..7c668b3d477 100644 --- a/packages/components/src/Button/Button.module.css +++ b/packages/components/src/Button/Button.module.css @@ -14,10 +14,10 @@ --button-padding-y: calc(var(--spacing-8) - var(--button-border-width)); --button-padding-x: calc(var(--spacing-16) - var(--button-border-width)); - background-color: var(--button-bg-color, var(--color-blue-500)); + background-color: var(--button-bg-color, var(--bg-brand-solid)); border: var(--button-border-width) solid; border-radius: var(--border-solid-border-radius); - border-color: var(--button-border-color, var(--color-blue-500)); + border-color: var(--button-border-color, var(--border-brand)); box-sizing: border-box; color: var(--button-text-color, var(--color-white)); display: inline-flex; @@ -39,12 +39,12 @@ } &[data-pressed] { - --button-bg-color: var(--color-blue-700); + --button-bg-color: var(--bg-brand-solid_hover); --button-border-color: var(--color-blue-700); } &[data-pending] { - --button-bg-color: var(--color-blue-700); + --button-bg-color: var(--bg-brand-solid_hover); --button-border-color: var(--color-blue-700); } @@ -99,21 +99,21 @@ .secondary { --button-bg-color: var(--color-white); - --button-border-color: var(--color-gray-500); - --button-text-color: var(--color-purple-800); + --button-border-color: var(--border-secondary); + --button-text-color: var(--text-primary); &[data-hovered] { --button-bg-color: var(--color-gray-200); - --button-border-color: var(--color-gray-600); + --button-border-color: var(--border-primary); } &[data-pressed] { - --button-bg-color: var(--color-gray-300); + --button-bg-color: var(--bg-tertiary); --button-border-color: var(--color-black); } &[data-pending] { - --button-bg-color: var(--color-gray-300); + --button-bg-color: var(--bg-tertiary); --button-border-color: var(--color-black); } @@ -127,26 +127,26 @@ .tertiary { --button-bg-color: transparent; --button-border-color: transparent; - --button-text-color: var(--color-purple-800); + --button-text-color: var(--text-primary); &[data-hovered], &[data-pressed], &[data-pending] { - --button-text-color: var(--color-blue-500); + --button-text-color: var(--text-brand-primary); } &[data-hovered] { - --button-bg-color: var(--color-blue-200); + --button-bg-color: var(--bg-brand-secondary); --button-border-color: var(--color-blue-200); } &[data-pressed] { - --button-bg-color: var(--color-blue-100); + --button-bg-color: var(--bg-brand-primary); --button-border-color: var(--color-blue-100); } &[data-pending] { - --button-bg-color: var(--color-blue-100); + --button-bg-color: var(--bg-brand-primary); --button-border-color: var(--color-blue-100); } @@ -168,16 +168,16 @@ .primaryReversed { --button-bg-color: var(--color-white); --button-border-color: var(--color-white); - --button-text-color: var(--color-purple-800); + --button-text-color: var(--text-primary); &[data-hovered] { --button-bg-color: var(--color-gray-200); - --button-border-color: var(--color-gray-200); + --button-border-color: var(--border-secondary_alt); } &[data-pressed] { - --button-bg-color: var(--color-gray-300); - --button-border-color: var(--color-gray-300); + --button-bg-color: var(--bg-tertiary); + --button-border-color: var(--border-tertiary); } &[data-pending] { diff --git a/packages/components/src/ButtonGroup/ButtonGroup.module.css b/packages/components/src/ButtonGroup/ButtonGroup.module.css index d918d6f3768..bd08c214a2e 100644 --- a/packages/components/src/ButtonGroup/ButtonGroup.module.css +++ b/packages/components/src/ButtonGroup/ButtonGroup.module.css @@ -15,7 +15,7 @@ } .child:not(.firstChild) { - border-inline-start: 1px solid var(--color-blue-300); + border-inline-start: 1px solid var(--border-brand_alt); } .child:not(.firstChild, .lastChild) { diff --git a/packages/components/src/ButtonGroup/ButtonGroup.module.scss b/packages/components/src/ButtonGroup/ButtonGroup.module.scss index c9abf4089d1..7612b8523c8 100644 --- a/packages/components/src/ButtonGroup/ButtonGroup.module.scss +++ b/packages/components/src/ButtonGroup/ButtonGroup.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/border'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/color'; @layer kz-components { @@ -28,7 +29,7 @@ } &:not(.firstChild) { - border-inline-start: 1px solid $color-blue-300; + border-inline-start: 1px solid $border-brand_alt; } &:not(.firstChild, .lastChild) { diff --git a/packages/components/src/ButtonV1/Button/Button.module.scss b/packages/components/src/ButtonV1/Button/Button.module.scss index 18b10f54c20..b5270ebba89 100644 --- a/packages/components/src/ButtonV1/Button/Button.module.scss +++ b/packages/components/src/ButtonV1/Button/Button.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/spacing'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/color'; @import '~@kaizen/design-tokens/sass/border'; @import '~@kaizen/design-tokens/sass/typography'; @@ -18,8 +19,8 @@ line-height: $typography-button-primary-line-height; letter-spacing: $typography-button-primary-letter-spacing; display: inline-flex; - // ^inline-flex is used over (block) flex here to fix an edge case where the parent element is display:grid - // and this element is an , causing the element to be full width. + /* ^inline-flex is used over (block) flex here to fix an edge case where the parent element is display:grid*/ + /* and this element is an , causing the element to be full width.*/ align-items: center; box-sizing: border-box; min-height: $button-height; @@ -28,7 +29,7 @@ position: relative; text-align: left; cursor: pointer; - overflow: visible; // Required for the focus ring on IE11 + overflow: visible; /* Required for the focus ring on IE11*/ &[href] { text-decoration: none; @@ -51,7 +52,7 @@ content: ''; position: absolute; background: transparent; - border-color: $color-blue-500; + border-color: $border-brand; border-radius: $border-focus-ring-border-radius; border-width: $border-focus-ring-border-width; border-style: $border-focus-ring-border-style; @@ -62,7 +63,7 @@ &.reversed { &:focus-visible { &::after { - border-color: $color-blue-300; + border-color: $border-brand_alt; } &.disabled, @@ -96,8 +97,8 @@ %variant-default { background-color: $color-white; - border-color: $color-gray-500; - color: $color-purple-800; + border-color: $border-secondary; + color: $text-primary; @include enabled-pseudo-states-variant($color-gray-200, $color-gray-600); @@ -111,16 +112,16 @@ } %variant-primary { - background-color: $color-blue-500; + background-color: $bg-brand-solid; border-color: $border-borderless-border-color; color: $color-white; @include enabled-pseudo-states-variant($color-blue-600, $border-borderless-border-color); &.reversed { - background-color: $color-green-300; + background-color: $bg-success-secondary; border-color: $border-borderless-border-color; - color: $color-purple-800; + color: $text-primary; @include enabled-pseudo-states-variant($color-green-400, $border-borderless-border-color); } @@ -134,9 +135,9 @@ @include enabled-pseudo-states-variant($color-red-600, $border-borderless-border-color); &.reversed { - background-color: $color-red-300; + background-color: $bg-error-secondary; border-color: $border-borderless-border-color; - color: $color-purple-800; + color: $text-primary; @include enabled-pseudo-states-variant($color-red-400, $border-borderless-border-color); } @@ -150,7 +151,7 @@ letter-spacing: $typography-button-secondary-letter-spacing; background-color: transparent; border-color: $border-borderless-border-color; - color: $color-blue-500; + color: $text-brand-primary; @include enabled-pseudo-states-variant($color-blue-100, $border-borderless-border-color); @@ -171,7 +172,7 @@ } %variant-secondary-destructive { - color: $color-red-600; + color: $text-error-primary; @include enabled-pseudo-states-variant($color-red-100, $border-borderless-border-color); } diff --git a/packages/components/src/Calendar/CalendarRange/CalendarRange.module.scss b/packages/components/src/Calendar/CalendarRange/CalendarRange.module.scss index 6d11074b519..5b94badbdce 100644 --- a/packages/components/src/Calendar/CalendarRange/CalendarRange.module.scss +++ b/packages/components/src/Calendar/CalendarRange/CalendarRange.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/color'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/spacing'; @layer kz-components { @@ -25,7 +26,7 @@ position: absolute; content: ''; inset: calc(-1 * #{$spacing-md}) 0; - border-inline-start: 1px solid $color-gray-300; + border-inline-start: 1px solid $border-tertiary; } } @@ -43,22 +44,22 @@ display: flex; justify-content: space-between; width: 100%; - color: $color-purple-800; + color: $text-primary; top: -0.25rem; } .dayRangeStart, .dayRangeEnd { - background-color: $color-blue-500; + background-color: $bg-brand-solid; color: $color-white; } .dayRangeMiddle { - background-color: $color-blue-100; - color: $color-blue-500; + background-color: $bg-brand-primary; + color: $text-brand-primary; & [class*='_button_'] { - color: $color-blue-500; + color: $text-brand-primary; } } diff --git a/packages/components/src/Calendar/CalendarSingle/CalendarSingle.module.scss b/packages/components/src/Calendar/CalendarSingle/CalendarSingle.module.scss index f9ecddd555f..e57bba774ad 100644 --- a/packages/components/src/Calendar/CalendarSingle/CalendarSingle.module.scss +++ b/packages/components/src/Calendar/CalendarSingle/CalendarSingle.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/color'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @layer kz-components { .nav { @@ -6,7 +7,7 @@ display: flex; justify-content: space-between; width: 100%; - color: $color-purple-800; + color: $text-primary; top: -0.25rem; } diff --git a/packages/components/src/Calendar/LegacyCalendarRange/LegacyCalendarRange.module.scss b/packages/components/src/Calendar/LegacyCalendarRange/LegacyCalendarRange.module.scss index c3be26611b4..8159feb7d7f 100644 --- a/packages/components/src/Calendar/LegacyCalendarRange/LegacyCalendarRange.module.scss +++ b/packages/components/src/Calendar/LegacyCalendarRange/LegacyCalendarRange.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/color'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @layer kz-components { .nav { @@ -6,22 +7,22 @@ display: flex; justify-content: space-between; width: 100%; - color: $color-purple-800; + color: $text-primary; top: -0.25rem; } .dayRangeStart, .dayRangeEnd { - background-color: $color-blue-500; + background-color: $bg-brand-solid; color: $color-white; } .dayRangeMiddle { - background-color: $color-blue-100; - color: $color-blue-500; + background-color: $bg-brand-primary; + color: $text-brand-primary; & [class*='_button_'] { - color: $color-blue-500; + color: $text-brand-primary; } } diff --git a/packages/components/src/Calendar/baseCalendarClassNames.module.scss b/packages/components/src/Calendar/baseCalendarClassNames.module.scss index 458373e0523..a5e0ee99511 100644 --- a/packages/components/src/Calendar/baseCalendarClassNames.module.scss +++ b/packages/components/src/Calendar/baseCalendarClassNames.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/typography'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/color'; @import '~@kaizen/design-tokens/sass/spacing'; @import '~@kaizen/design-tokens/sass/border'; @@ -35,7 +36,7 @@ &:focus-visible { &::after { - border: $border-focus-ring-border-width $border-focus-ring-border-style $color-blue-500; + border: $border-focus-ring-border-width $border-focus-ring-border-style $border-brand; } } } @@ -77,7 +78,7 @@ font-weight: $typography-heading-5-font-weight; line-height: $typography-heading-4-line-height; letter-spacing: $typography-heading-4-letter-spacing; - color: $color-purple-800; + color: $text-primary; } .navButton { @@ -89,13 +90,13 @@ border-radius: $button-border-radius; &:hover { - background-color: $color-blue-100; - color: $color-blue-500; + background-color: $bg-brand-primary; + color: $text-brand-primary; } &:focus-visible { - background-color: $color-blue-100; - color: $color-blue-500; + background-color: $bg-brand-primary; + color: $text-brand-primary; } } @@ -122,7 +123,7 @@ letter-spacing: $typography-paragraph-body-letter-spacing; font-weight: $typography-paragraph-body-font-weight; line-height: $typography-paragraph-body-line-height; - color: $color-purple-800; + color: $text-primary; } .cell { @@ -147,26 +148,26 @@ $border-borderless-border-color; border-radius: $button-border-radius; padding: calc(#{$spacing-md} / 3) 0.625rem; - color: $color-purple-800; + color: $text-primary; &:hover { - background-color: $color-blue-100; - color: $color-blue-500; + background-color: $bg-brand-primary; + color: $text-brand-primary; } &:focus-visible { - background-color: $color-blue-100; - color: $color-blue-500; + background-color: $bg-brand-primary; + color: $text-brand-primary; } } .dayToday { - color: $color-blue-500; + color: $text-brand-primary; font-weight: bold; } .daySelected { - background-color: $color-blue-500; + background-color: $bg-brand-solid; border-radius: $button-border-radius; color: $color-white; @@ -182,10 +183,10 @@ } .dayDisabled { - // Focus ring styles have been removed as react-day-picker has been updated such that - // disabled days do not receive focus, and keyboard navigation only lands on available days. - // https://github.com/gpbl/react-day-picker/pull/1519 - // https://github.com/gpbl/react-day-picker/issues/1449#issuecomment-1149942033 + /* Focus ring styles have been removed as react-day-picker has been updated such that*/ + /* disabled days do not receive focus, and keyboard navigation only lands on available days.*/ + /* https://github.com/gpbl/react-day-picker/pull/1519*/ + /* https://github.com/gpbl/react-day-picker/issues/1449#issuecomment-1149942033*/ background: none; pointer-events: none; diff --git a/packages/components/src/Card/Card.module.css b/packages/components/src/Card/Card.module.css index ab67b81fa29..4751db2c239 100644 --- a/packages/components/src/Card/Card.module.css +++ b/packages/components/src/Card/Card.module.css @@ -1,12 +1,12 @@ @layer kz-components { .wrapper { - color: var(--color-purple-800); + color: var(--text-primary); border: var(--border-width-1) solid var(--card-border-color); background-color: var(--card-background-color); border-radius: var(--border-solid-border-radius); box-shadow: var(--card-box-shadow); - --card-border-color: var(--color-gray-500); + --card-border-color: var(--border-secondary); --card-background-color: var(--color-white); --card-box-shadow: var(--shadow-small-box-shadow); } @@ -16,17 +16,17 @@ } .blue { - --card-background-color: var(--color-blue-100); + --card-background-color: var(--bg-brand-primary); --card-border-color: var(--color-blue-400); } .gray { --card-background-color: var(--color-gray-200); - --card-border-color: var(--color-gray-500); + --card-border-color: var(--border-secondary); } .green { - --card-background-color: var(--color-green-100); + --card-background-color: var(--bg-success-primary); --card-border-color: var(--color-green-500); } @@ -41,17 +41,17 @@ } .red { - --card-background-color: var(--color-red-100); - --card-border-color: var(--color-red-500); + --card-background-color: var(--bg-error-primary); + --card-border-color: var(--border-error); } .white { --card-background-color: var(--color-white); - --card-border-color: var(--color-gray-500); + --card-border-color: var(--border-secondary); } .yellow { - --card-background-color: var(--color-yellow-100); + --card-background-color: var(--bg-warning-primary); --card-border-color: var(--color-yellow-700); } } diff --git a/packages/components/src/ClearButton/ClearButton.module.css b/packages/components/src/ClearButton/ClearButton.module.css index 90f5f1f4fcb..f4e641f423f 100644 --- a/packages/components/src/ClearButton/ClearButton.module.css +++ b/packages/components/src/ClearButton/ClearButton.module.css @@ -28,7 +28,7 @@ &:hover, &:focus-visible { - color: var(--color-purple-800); + color: var(--text-primary); } } diff --git a/packages/components/src/Collapsible/Collapsible/Collapsible.module.scss b/packages/components/src/Collapsible/Collapsible/Collapsible.module.scss index 3d1c74be9c6..52c83c90c38 100644 --- a/packages/components/src/Collapsible/Collapsible/Collapsible.module.scss +++ b/packages/components/src/Collapsible/Collapsible/Collapsible.module.scss @@ -9,12 +9,12 @@ $divider-color: rgba($color-gray-600-rgb, 0.2); $container-border-width: var(--border-width-1); - // We need a full border radius on this container element, then have classes - // beneath to toggle nested borders off and on for different use cases. + /* We need a full border radius on this container element, then have classes*/ + /* beneath to toggle nested borders off and on for different use cases.*/ .container { background-color: $color-white; box-shadow: $shadow-small-box-shadow; - border: $container-border-width var(--border-solid-border-style) var(--color-gray-500); + border: $container-border-width var(--border-solid-border-style) var(--border-secondary); border-radius: $border-borderless-border-radius; } @@ -33,8 +33,8 @@ background-color: $heading-active-color; } - // Round the bottom corners of the header so when the container is open, the - // header background is not rounded on the corners and flush with the content beneath. + /* Round the bottom corners of the header so when the container is open, the*/ + /* header background is not rounded on the corners and flush with the content beneath.*/ &.open { border-bottom-left-radius: 0; border-bottom-right-radius: 0; @@ -49,9 +49,9 @@ } } - // When a collapsible group is rendered, we need the first group to have a rounded - // on top and the last group to have a rounded bottom edge. Then when the last group - // is open we remove the rounded edge as the content sits beneath and needs to be straight. + /* When a collapsible group is rendered, we need the first group to have a rounded*/ + /* on top and the last group to have a rounded bottom edge. Then when the last group*/ + /* is open we remove the rounded edge as the content sits beneath and needs to be straight.*/ .groupItem { & + .groupItem { border-top: 1px $border-solid-border-style $divider-color; @@ -76,7 +76,7 @@ } .chevronButton:hover { - // hack to get rid of the IconButton hover styling because it clashes with the hover styling on the Collapsible header + /* hack to get rid of the IconButton hover styling because it clashes with the hover styling on the Collapsible header*/ background-color: transparent !important; /* stylelint-disable-line declaration-no-important */ } diff --git a/packages/components/src/Collapsible/CollapsibleGroup/CollapsibleGroup.module.scss b/packages/components/src/Collapsible/CollapsibleGroup/CollapsibleGroup.module.scss index ca1af8149e1..021c58a1a9b 100644 --- a/packages/components/src/Collapsible/CollapsibleGroup/CollapsibleGroup.module.scss +++ b/packages/components/src/Collapsible/CollapsibleGroup/CollapsibleGroup.module.scss @@ -2,12 +2,12 @@ @import '~@kaizen/design-tokens/sass/shadow'; @layer kz-components { - // We need a full border radius on this container element, then have classes - // beneath to toggle nested borders off and on for different use cases. + /* We need a full border radius on this container element, then have classes*/ + /* beneath to toggle nested borders off and on for different use cases.*/ .container { background-color: white; box-shadow: $shadow-small-box-shadow; - border: var(--border-width-1) var(--border-solid-border-style) var(--color-gray-500); + border: var(--border-width-1) var(--border-solid-border-style) var(--border-secondary); border-radius: $border-borderless-border-radius; } } diff --git a/packages/components/src/Collapsible/ExpertAdviceCollapsible/ExpertAdviceCollapsible.module.scss b/packages/components/src/Collapsible/ExpertAdviceCollapsible/ExpertAdviceCollapsible.module.scss index 31dd8c5df59..9b6e153da65 100644 --- a/packages/components/src/Collapsible/ExpertAdviceCollapsible/ExpertAdviceCollapsible.module.scss +++ b/packages/components/src/Collapsible/ExpertAdviceCollapsible/ExpertAdviceCollapsible.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/border'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/color'; @import '~@kaizen/design-tokens/sass/spacing'; @@ -7,14 +8,14 @@ background-color: $color-purple-100; border: var(--border-width-1) var(--border-solid-border-style) var(--color-purple-400); box-shadow: none; - color: $color-purple-800; + color: $text-primary; &:hover { border-color: $color-purple-500; } } - // Override Collapsible header + /* Override Collapsible header*/ .expertAdviceContainer > div { &:first-of-type { background-color: $color-purple-100; diff --git a/packages/components/src/DateInput/DateInputWithIconButton/DateInputWithIconButton.module.css b/packages/components/src/DateInput/DateInputWithIconButton/DateInputWithIconButton.module.css index 0707bac1d99..104f23e9817 100644 --- a/packages/components/src/DateInput/DateInputWithIconButton/DateInputWithIconButton.module.css +++ b/packages/components/src/DateInput/DateInputWithIconButton/DateInputWithIconButton.module.css @@ -27,14 +27,14 @@ } &:hover:not([disabled]) { - background-color: var(--color-blue-100); - color: var(--color-blue-500); + background-color: var(--bg-brand-primary); + color: var(--text-brand-primary); } } .calendarActive { - color: var(--color-blue-500); - background-color: var(--color-blue-100); + color: var(--text-brand-primary); + background-color: var(--bg-brand-primary); } .disabled { diff --git a/packages/components/src/DatePicker/DatePicker.module.css b/packages/components/src/DatePicker/DatePicker.module.css index 622eb25ba22..e38d2031162 100644 --- a/packages/components/src/DatePicker/DatePicker.module.css +++ b/packages/components/src/DatePicker/DatePicker.module.css @@ -1,6 +1,6 @@ @layer kz-components { .datePicker { - color: var(--color-purple-800); + color: var(--text-primary); } .isReversed { diff --git a/packages/components/src/DateRangePicker/DateRangePicker.module.scss b/packages/components/src/DateRangePicker/DateRangePicker.module.scss index c5736d3fba7..630158584f9 100644 --- a/packages/components/src/DateRangePicker/DateRangePicker.module.scss +++ b/packages/components/src/DateRangePicker/DateRangePicker.module.scss @@ -1,14 +1,15 @@ @import '~@kaizen/design-tokens/sass/typography'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/color'; @import '~@kaizen/design-tokens/sass/spacing'; @import '~@kaizen/design-tokens/sass/border'; @import '../../styles/utils/button-reset'; @layer kz-components { - // Vars + /* Vars*/ $button-height: 48px; $button-base-padding-horizontal: $spacing-sm; - $button-icon-size: 1.25rem; // 20px + $button-icon-size: 1.25rem; /* 20px*/ $disabled-opacity: 0.5; $placeholder-opacity: 0.7; @@ -21,7 +22,7 @@ align-items: center; height: $button-height; width: 100%; - color: $color-purple-800; + color: $text-primary; font-family: $typography-paragraph-body-font-family; font-size: $typography-paragraph-body-font-size; font-weight: $typography-paragraph-body-font-weight; @@ -30,7 +31,7 @@ text-align: start; background-color: $color-white; background-clip: padding-box; - border: $border-solid-border-width $border-solid-border-style $color-gray-500; + border: $border-solid-border-width $border-solid-border-style $border-secondary; border-radius: $border-solid-border-radius; margin-top: $spacing-6; padding: 0 $button-base-padding-horizontal; @@ -38,8 +39,8 @@ &:focus-visible:not([disabled]), &:hover:not([disabled]) { background-color: $color-gray-200; - border-color: $color-gray-600; - color: $color-purple-800; + border-color: $border-primary; + color: $text-primary; } &:focus-visible:not([disabled]) { @@ -67,7 +68,7 @@ margin-top: -1px; } - // Icon adornment styles + /* Icon adornment styles*/ @mixin vertically-center-icon { position: absolute; height: $button-icon-size; @@ -80,7 +81,7 @@ .startIconAdornment { @include vertically-center-icon; - color: $color-purple-800; + color: $text-primary; opacity: $disabled-opacity; inset-inline: $spacing-sm auto; } diff --git a/packages/components/src/EmptyState/EmptyState.module.css b/packages/components/src/EmptyState/EmptyState.module.css index d165991beb7..3e3f7712726 100644 --- a/packages/components/src/EmptyState/EmptyState.module.css +++ b/packages/components/src/EmptyState/EmptyState.module.css @@ -10,7 +10,7 @@ border: var(--empty-state-border-width) solid var(--empty-state-border-color); border-radius: var(--border-solid-border-radius); background-color: var(--empty-state-background-color); - color: var(--color-purple-800); + color: var(--text-primary); } .straightCorners { @@ -19,17 +19,17 @@ .success { --empty-state-border-color: var(--color-green-500); - --empty-state-background-color: var(--color-green-100); + --empty-state-background-color: var(--bg-success-primary); } .warning { - --empty-state-border-color: var(--color-red-500); - --empty-state-background-color: var(--color-red-100); + --empty-state-border-color: var(--border-error); + --empty-state-background-color: var(--bg-error-primary); } .informative { --empty-state-border-color: var(--color-blue-400); - --empty-state-background-color: var(--color-blue-100); + --empty-state-background-color: var(--bg-brand-primary); } .expert-advice { diff --git a/packages/components/src/FieldGroup/_docs/FieldGroup.stickersheet.stories.tsx b/packages/components/src/FieldGroup/_docs/FieldGroup.stickersheet.stories.tsx index 49d5a977a9e..c64e5d39eed 100644 --- a/packages/components/src/FieldGroup/_docs/FieldGroup.stickersheet.stories.tsx +++ b/packages/components/src/FieldGroup/_docs/FieldGroup.stickersheet.stories.tsx @@ -22,11 +22,11 @@ const FieldGroupTemplate = ({
- + - +
) diff --git a/packages/components/src/FieldGroup/_docs/FieldGroup.stories.tsx b/packages/components/src/FieldGroup/_docs/FieldGroup.stories.tsx index a47100c0b91..f98e6f3dc99 100644 --- a/packages/components/src/FieldGroup/_docs/FieldGroup.stories.tsx +++ b/packages/components/src/FieldGroup/_docs/FieldGroup.stories.tsx @@ -10,7 +10,7 @@ const meta = { children: ( <> - + ), }, @@ -35,11 +35,11 @@ export const Inline: Story = { <> - + - + ), @@ -50,11 +50,11 @@ export const Default: Story = { <> - + - + ), diff --git a/packages/components/src/FieldMessage/FieldMessage.module.css b/packages/components/src/FieldMessage/FieldMessage.module.css index 932ed19ecf6..bd127fdafed 100644 --- a/packages/components/src/FieldMessage/FieldMessage.module.css +++ b/packages/components/src/FieldMessage/FieldMessage.module.css @@ -25,20 +25,20 @@ .caution { border-radius: var(--border-solid-border-radius); padding: var(--validation-message-padding); - color: var(--color-purple-800); + color: var(--text-primary); } .error { - background: var(--color-red-100); + background: var(--bg-error-primary); opacity: 1; &.reversed { - background: var(--color-red-300); + background: var(--bg-error-secondary); } } .caution { - background: var(--color-yellow-100); + background: var(--bg-warning-primary); opacity: 1; &.reversed { @@ -68,7 +68,7 @@ } .reversed & { - color: var(--color-purple-800); + color: var(--text-primary); } } } diff --git a/packages/components/src/Filter/FilterButton/subcomponents/FilterButtonBase/FilterButtonBase.module.scss b/packages/components/src/Filter/FilterButton/subcomponents/FilterButtonBase/FilterButtonBase.module.scss index d7dfe4a2d64..edfed6b7d6d 100644 --- a/packages/components/src/Filter/FilterButton/subcomponents/FilterButtonBase/FilterButtonBase.module.scss +++ b/packages/components/src/Filter/FilterButton/subcomponents/FilterButtonBase/FilterButtonBase.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/border'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/color'; @import '~@kaizen/design-tokens/sass/typography'; @import '~@kaizen/design-tokens/sass/spacing'; @@ -14,17 +15,17 @@ position: relative; display: inline-flex; align-items: center; - min-height: 3rem; // 48px + min-height: 3rem; /* 48px*/ padding: $spacing-sm; border-width: 0; border-radius: $border-solid-border-radius; - background-color: $color-blue-100; + background-color: $bg-brand-primary; font-family: $typography-button-secondary-font-family; font-weight: $typography-button-secondary-font-weight; font-size: $typography-button-secondary-font-size; line-height: $typography-button-secondary-line-height; letter-spacing: $typography-button-secondary-letter-spacing; - color: $color-blue-500; + color: $text-brand-primary; text-align: start; &:hover, @@ -35,7 +36,7 @@ &:hover, &:active, &:focus-visible { - background-color: $color-blue-200; + background-color: $bg-brand-secondary; } &:focus { @@ -51,7 +52,7 @@ position: absolute; inset: $focus-ring-offset-outer; border-radius: $border-focus-ring-border-radius; - border: $border-focus-ring-border-width $border-focus-ring-border-style $color-blue-500; + border: $border-focus-ring-border-width $border-focus-ring-border-style $border-brand; } } } diff --git a/packages/components/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/MenuPopup.module.css b/packages/components/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/MenuPopup.module.css index 4fffecaf878..fb9315abb52 100644 --- a/packages/components/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/MenuPopup.module.css +++ b/packages/components/src/Filter/FilterMultiSelect/subcomponents/MenuPopup/MenuPopup.module.css @@ -5,7 +5,7 @@ z-index: 1000; box-sizing: border-box; background: var(--color-white); - color: var(--color-purple-800); + color: var(--text-primary); border-radius: var(--border-solid-border-radius); box-shadow: var(--shadow-large-box-shadow); padding: var(--spacing-12) 0; diff --git a/packages/components/src/Filter/FilterMultiSelect/subcomponents/MultiSelectOption/MultiSelectOption.module.scss b/packages/components/src/Filter/FilterMultiSelect/subcomponents/MultiSelectOption/MultiSelectOption.module.scss index ec094935dfd..56c9baa5464 100644 --- a/packages/components/src/Filter/FilterMultiSelect/subcomponents/MultiSelectOption/MultiSelectOption.module.scss +++ b/packages/components/src/Filter/FilterMultiSelect/subcomponents/MultiSelectOption/MultiSelectOption.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/border'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/color'; @import '~@kaizen/design-tokens/sass/typography'; @import '~@kaizen/design-tokens/sass/spacing'; @@ -11,7 +12,7 @@ height: calc(#{$iconAndBadgeHeight} - #{$border-solid-border-width} * 2); width: calc(#{$iconAndBadgeHeight} - #{$border-solid-border-width} * 2); border: $border-solid-border-width $border-solid-border-style; - border-color: $color-gray-500; + border-color: $border-secondary; border-radius: $border-solid-border-radius; display: inline-flex; justify-content: center; @@ -39,21 +40,21 @@ &:hover, &:active, &:focus { - background-color: $color-blue-100; + background-color: $bg-brand-primary; .badge { background-color: $color-white; } .icon { - border-color: $color-gray-600; + border-color: $border-primary; background-color: $color-gray-200; } } &.isFocused, &:focus-visible { - background-color: $color-blue-100; + background-color: $bg-brand-primary; &::after { $focus-ring-offset: calc((#{$border-focus-ring-border-width} * 2) + 1px); @@ -61,15 +62,15 @@ content: ''; position: absolute; background: transparent; - border: $border-focus-ring-border-width $border-focus-ring-border-style $color-blue-500; + border: $border-focus-ring-border-width $border-focus-ring-border-style $border-brand; border-radius: $border-focus-ring-border-radius; inset: calc(-1 * #{$focus-ring-offset}); - z-index: 1; // show border when sibling option is hovered + z-index: 1; /* show border when sibling option is hovered*/ } } &:focus { - outline: none; // cancel browser style + outline: none; /* cancel browser style*/ } } @@ -79,17 +80,17 @@ &:hover { .icon { - border-color: $color-gray-500; + border-color: $border-secondary; } .badge { - background-color: $color-gray-300; + background-color: $bg-tertiary; } } } .badgeContainer { - // Must be the same height as .icon, so they align vertically + /* Must be the same height as .icon, so they align vertically*/ height: $iconAndBadgeHeight; display: flex; align-items: center; @@ -107,7 +108,7 @@ &:active, &:focus { .icon { - background-color: $color-gray-600; + background-color: $bg-secondary-solid; } } } diff --git a/packages/components/src/Filter/FilterMultiSelect/subcomponents/SelectionControlButton/SelectionControlButton.module.scss b/packages/components/src/Filter/FilterMultiSelect/subcomponents/SelectionControlButton/SelectionControlButton.module.scss index e6bf397dbb8..08f3486c161 100644 --- a/packages/components/src/Filter/FilterMultiSelect/subcomponents/SelectionControlButton/SelectionControlButton.module.scss +++ b/packages/components/src/Filter/FilterMultiSelect/subcomponents/SelectionControlButton/SelectionControlButton.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/border'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/color'; @import '~@kaizen/design-tokens/sass/typography'; @import '~@kaizen/design-tokens/sass/spacing'; @@ -25,7 +26,7 @@ font-size: $typography-button-secondary-font-size; line-height: $typography-button-secondary-line-height; letter-spacing: $typography-button-secondary-letter-spacing; - color: $color-blue-500; + color: $text-brand-primary; &:focus { outline: none; @@ -35,7 +36,7 @@ &:active, &:focus { &:not(.isDisabled) { - background-color: $color-blue-100; + background-color: $bg-brand-primary; } } @@ -48,11 +49,11 @@ border-radius: $border-focus-ring-border-radius; border-width: $border-focus-ring-border-width; border-style: $border-focus-ring-border-style; - border-color: $color-blue-500; + border-color: $border-brand; inset: calc(-1 * #{$focus-ring-offset}); } - // TODO: copied from Calendar button since the design is not settled + /* TODO: copied from Calendar button since the design is not settled*/ &.isDisabled { pointer-events: none; color: rgba($color-purple-800-rgb, 0.3); diff --git a/packages/components/src/GuidanceBlock/GuidanceBlock.module.css b/packages/components/src/GuidanceBlock/GuidanceBlock.module.css index c46cb82e3c2..b38c05b9ca3 100644 --- a/packages/components/src/GuidanceBlock/GuidanceBlock.module.css +++ b/packages/components/src/GuidanceBlock/GuidanceBlock.module.css @@ -18,7 +18,7 @@ box-shadow: var(--shadow-small-box-shadow); position: relative; top: -1px; - color: var(--color-purple-800); + color: var(--text-primary); @media (width >= 1024px) { min-height: calc(12rem - calc(var(--banner-padding) * 2)); @@ -132,29 +132,29 @@ } .default { - border-color: var(--color-gray-500); + border-color: var(--border-secondary); background: var(--color-white); } .positive { border-color: var(--color-green-500); - background: var(--color-green-100); + background: var(--bg-success-primary); } .negative, .assertive { - border-color: var(--color-red-500); - background: var(--color-red-100); + border-color: var(--border-error); + background: var(--bg-error-primary); } .informative { border-color: var(--color-blue-400); - background: var(--color-blue-100); + background: var(--bg-brand-primary); } .cautionary { border-color: var(--color-yellow-700); - background: var(--color-yellow-100); + background: var(--bg-warning-primary); } .prominent { diff --git a/packages/components/src/Heading/Heading.module.css b/packages/components/src/Heading/Heading.module.css index 1a866b95c32..45b311d9fcb 100644 --- a/packages/components/src/Heading/Heading.module.css +++ b/packages/components/src/Heading/Heading.module.css @@ -70,12 +70,12 @@ } .dark { - color: var(--color-purple-800); + color: var(--text-primary); opacity: 1; } .dark-reduced-opacity { - color: var(--color-purple-800); + color: var(--text-primary); opacity: 0.7; } @@ -91,7 +91,7 @@ .positive { &.small { - color: var(--color-green-600); + color: var(--text-success-primary); } &.large { @@ -101,7 +101,7 @@ .negative { &.small { - color: var(--color-red-600); + color: var(--text-error-primary); } &.large { diff --git a/packages/components/src/Icon/_docs/Icon.docs.module.css b/packages/components/src/Icon/_docs/Icon.docs.module.css index 98e2aaf857d..2cdf17423c9 100644 --- a/packages/components/src/Icon/_docs/Icon.docs.module.css +++ b/packages/components/src/Icon/_docs/Icon.docs.module.css @@ -3,7 +3,7 @@ position: relative; background: none; padding: 0; - color: var(--color-blue-500); + color: var(--text-brand-primary); &:hover { color: var(--color-blue-400); diff --git a/packages/components/src/Icon/_docs/Icon.docs.stories.tsx b/packages/components/src/Icon/_docs/Icon.docs.stories.tsx index f6279bd0862..89c76b8cc47 100644 --- a/packages/components/src/Icon/_docs/Icon.docs.stories.tsx +++ b/packages/components/src/Icon/_docs/Icon.docs.stories.tsx @@ -101,7 +101,7 @@ export const Color: Story = {
- +
), } @@ -297,7 +297,7 @@ export const AlignmentDont: Story = { export const ContrastDo: Story = { render: () => ( -
+
), @@ -305,7 +305,7 @@ export const ContrastDo: Story = { export const ContrastDont: Story = { render: () => ( -
+
), @@ -346,7 +346,7 @@ export const DistinguishDont: Story = {
Selected - +
), diff --git a/packages/components/src/Icon/_docs/Icon.stickersheet.stories.tsx b/packages/components/src/Icon/_docs/Icon.stickersheet.stories.tsx index 5d5f94682fa..9cb4c1fd752 100644 --- a/packages/components/src/Icon/_docs/Icon.stickersheet.stories.tsx +++ b/packages/components/src/Icon/_docs/Icon.stickersheet.stories.tsx @@ -40,7 +40,7 @@ const StickerSheetTemplate: StickerSheetStory = { - + ))} diff --git a/packages/components/src/IconV1/_docs/Icon.docs.stories.tsx b/packages/components/src/IconV1/_docs/Icon.docs.stories.tsx index 9a65f571e4a..045be516dac 100644 --- a/packages/components/src/IconV1/_docs/Icon.docs.stories.tsx +++ b/packages/components/src/IconV1/_docs/Icon.docs.stories.tsx @@ -38,7 +38,7 @@ export const Playground: Story = { export const ApplyColour: Story = { render: (args) => ( -
+
), diff --git a/packages/components/src/Illustration/subcomponents/Base/Base.module.scss b/packages/components/src/Illustration/subcomponents/Base/Base.module.scss index 5693317ae38..b8bc984595b 100644 --- a/packages/components/src/Illustration/subcomponents/Base/Base.module.scss +++ b/packages/components/src/Illustration/subcomponents/Base/Base.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/color'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/animation'; @layer kz-components { @@ -12,7 +13,7 @@ position: relative; } - // nested to get more specificity, beat out the generic button styles + /* nested to get more specificity, beat out the generic button styles*/ .figure .pausePlayButton { opacity: 0%; position: absolute; @@ -28,7 +29,7 @@ } svg { - color: $color-purple-800; + color: $text-primary; opacity: 70%; } @@ -109,10 +110,10 @@ } } - // If the .visually-hidden class is applied to natively focusable elements - // (such as a, button, input, etc) they must become visible when they receive - // keyboard focus. Otherwise, a sighted keyboard user would have to try and - // figure out where their visible focus indicator had gone to. + /* If the .visually-hidden class is applied to natively focusable elements*/ + /* (such as a, button, input, etc) they must become visible when they receive*/ + /* keyboard focus. Otherwise, a sighted keyboard user would have to try and*/ + /* figure out where their visible focus indicator had gone to.*/ .visuallyHidden:not(:focus, :active) { clip-path: rect(0 0 0 0); position: absolute; diff --git a/packages/components/src/Input/Input/Input.module.scss b/packages/components/src/Input/Input/Input.module.scss index d54f58e7221..74a428bb05f 100644 --- a/packages/components/src/Input/Input/Input.module.scss +++ b/packages/components/src/Input/Input/Input.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/border'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/color'; @import '~@kaizen/design-tokens/sass/spacing'; @import '../../../styles/utils/form-variables'; @@ -7,7 +8,7 @@ @layer kz-components { $input-height: 48px; $input-base-padding-horizontal: $spacing-sm; - $input-icon-size: 1.25rem; // 20px + $input-icon-size: 1.25rem; /* 20px*/ $input-disabled-background: $color-gray-300; $input-disabled-opacity: 0.3; $input-disabled-border-alpha: 50%; @@ -59,9 +60,9 @@ } /* stylelint-disable no-descending-specificity */ - /////////////////////////////////////////////////// - // ICON ADORNMENT STYLES - /////////////////////////////////////////////////// + /*/////////////////////////////////////////////////*/ + /* ICON ADORNMENT STYLES*/ + /*/////////////////////////////////////////////////*/ @mixin vertically-center-icon { position: absolute; @@ -113,12 +114,12 @@ } } - // Default theme + /* Default theme*/ /* stylelint-disable-next-line no-duplicate-selectors */ .withStartIconAdornment { /* stylelint-disable-next-line no-duplicate-selectors */ .startIconAdornment { - color: $color-purple-800; + color: $text-primary; opacity: 50%; } @@ -139,7 +140,7 @@ } } - // Reversed + /* Reversed*/ .withStartIconAdornment.withReversed { .startIconAdornment { color: $color-white; @@ -180,14 +181,14 @@ } } - /////////////////////////////////////////////////// - // THEMES - /////////////////////////////////////////////////// + /*/////////////////////////////////////////////////*/ + /* THEMES*/ + /*/////////////////////////////////////////////////*/ - // Default + /* Default*/ .input.default { background-color: $color-white; - color: $color-purple-800; + color: $text-primary; display: flex; align-items: center; @@ -196,7 +197,7 @@ } &:focus + .focusRing { - border-color: $color-blue-500; + border-color: $border-brand; } &.disabled { @@ -206,19 +207,19 @@ } &:not(.error, .caution) { - border-color: $color-gray-500; + border-color: $border-secondary; &:disabled { border-color: rgba($color-gray-500-rgb, $input-disabled-opacity); } @include form-input-focus-state { - border-color: $color-gray-600; + border-color: $border-primary; } } &.error { - border-color: $color-red-500; + border-color: $border-error; &.disabled { border-color: rgba($color-red-500-rgb, $input-disabled-opacity); @@ -234,7 +235,7 @@ } } - // Reversed (Dark Backgrounds) + /* Reversed (Dark Backgrounds)*/ .input.reversed { background: transparent; color: $color-white; @@ -265,7 +266,7 @@ } &.error { - border-color: $color-red-300; + border-color: $border-error_subtle; &.disabled { border-color: rgba($color-red-300-rgb, $input-disabled-opacity); diff --git a/packages/components/src/Input/InputSearch/InputSearch.module.scss b/packages/components/src/Input/InputSearch/InputSearch.module.scss index 5b6619d307e..fd58ec7fd89 100644 --- a/packages/components/src/Input/InputSearch/InputSearch.module.scss +++ b/packages/components/src/Input/InputSearch/InputSearch.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/border'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/color'; @import '~@kaizen/design-tokens/sass/spacing'; @import '../../../styles/utils/forms'; @@ -8,7 +9,7 @@ $input-padding-before-start-icon: 1rem; $input-padding-between-icon-input: $spacing-sm; $input-padding-after-end-icon: $spacing-sm; - $input-icon-size: 1.25rem; // 20px + $input-icon-size: 1.25rem; /* 20px*/ $input-padding-with-icon: calc( #{$input-padding-before-start-icon} + #{$input-icon-size} + #{$input-padding-between-icon-input} ); @@ -20,7 +21,7 @@ $input-placeholder-opacity--reversed: 0.8; $start-icon-opacity--reversed: $input-placeholder-opacity--reversed; - // [type="search"] is required to override performance-ui global materialize CSS >:| + /* [type="search"] is required to override performance-ui global materialize CSS >:|*/ $classname--input: '.input[type="search"]'; .wrapper { @@ -100,32 +101,32 @@ } /* stylelint-disable no-descending-specificity */ - /////////////////////////////////////////////////// - // THEMES - /////////////////////////////////////////////////// + /*/////////////////////////////////////////////////*/ + /* THEMES*/ + /*/////////////////////////////////////////////////*/ - // Default + /* Default*/ .default { #{$classname--input} { - border-color: $color-gray-500; + border-color: $border-secondary; background-color: $color-white; - color: $color-purple-800; + color: $text-primary; @include form-input-placeholder { - color: $color-purple-800; + color: $text-primary; opacity: $input-placeholder-opacity--default; } } .startIconAdornment { - color: $color-purple-800; + color: $text-primary; opacity: $start-icon-opacity--default; } &:hover, &:focus-within { #{$classname--input} { - border-color: $color-gray-600; + border-color: $border-primary; background-color: $color-gray-200; @include form-input-placeholder { @@ -139,21 +140,21 @@ } } - // Secondary + /* Secondary*/ .secondary { #{$classname--input} { border-color: transparent; background-color: $color-gray-200; - color: $color-purple-800; + color: $text-primary; @include form-input-placeholder { - color: $color-purple-800; + color: $text-primary; opacity: $input-placeholder-opacity--default; } } .startIconAdornment { - color: $color-purple-800; + color: $text-primary; opacity: $start-icon-opacity--default; } @@ -161,7 +162,7 @@ &:focus-within { #{$classname--input} { border-color: transparent; - background-color: $color-gray-300; + background-color: $bg-tertiary; @include form-input-placeholder { opacity: 100%; @@ -174,7 +175,7 @@ } } - // Reversed + /* Reversed*/ .reversed { #{$classname--input} { background: rgba($color-white-rgb, 0.1); diff --git a/packages/components/src/Label/Label.module.css b/packages/components/src/Label/Label.module.css index ac9ea643dd8..93cfc5810c7 100644 --- a/packages/components/src/Label/Label.module.css +++ b/packages/components/src/Label/Label.module.css @@ -1,7 +1,7 @@ @layer kz-components { :root { --label-start-margin: var(--spacing-xs); - --dt-color-form-text-color: var(--color-purple-800); + --dt-color-form-text-color: var(--text-primary); } .label { diff --git a/packages/components/src/LikertScale/LikertScale.module.scss b/packages/components/src/LikertScale/LikertScale.module.scss index 4454bb5741f..d8e89f53a78 100644 --- a/packages/components/src/LikertScale/LikertScale.module.scss +++ b/packages/components/src/LikertScale/LikertScale.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/border'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/color'; @import '~@kaizen/design-tokens/sass/spacing'; @@ -124,7 +125,7 @@ padding: 0; overflow-x: visible; display: inline-block; - width: 18.5%; // 5 columns + width: 18.5%; /* 5 columns*/ position: relative; @include fill($block-height); @@ -137,7 +138,7 @@ margin-inline-end: 0; } - // Hack to bridge the gaps between items so mouse always hovers on something + /* Hack to bridge the gaps between items so mouse always hovers on something*/ &::before, &::after { content: ''; @@ -245,7 +246,7 @@ background 0.1s, border-color 0.1s; height: $block-height; - border: $border-solid-border-width $border-solid-border-style $color-gray-500; + border: $border-solid-border-width $border-solid-border-style $border-secondary; &:hover { transition: diff --git a/packages/components/src/Link/Link.module.css b/packages/components/src/Link/Link.module.css index 9953dee9692..4d84cbbbdd0 100644 --- a/packages/components/src/Link/Link.module.css +++ b/packages/components/src/Link/Link.module.css @@ -1,6 +1,6 @@ @layer kz-components { .link { - color: var(--link-text-color, var(--color-blue-500)); + color: var(--link-text-color, var(--text-brand-primary)); font-family: var(--typography-paragraph-body-font-family); font-size: var(--link-font-size, inherit); line-height: var(--link-line-height, inherit); @@ -18,7 +18,7 @@ } .isUnderlined { - border-bottom: var(--spacing-1) solid var(--link-text-color, var(--color-blue-500)); + border-bottom: var(--spacing-1) solid var(--link-text-color, var(--border-brand)); } .link .icon > * { @@ -35,19 +35,19 @@ } .primary[data-hovered] { - --link-text-color: var(--color-blue-600); + --link-text-color: var(--text-brand-secondary_hover); } .primary[data-pressed] { - --link-text-color: var(--color-blue-700); + --link-text-color: var(--text-brand-secondary); } .secondary { - --link-text-color: var(--color-purple-800); + --link-text-color: var(--text-primary); } .secondary[data-hovered] { - --link-text-color: var(--color-gray-600); + --link-text-color: var(--text-tertiary); } .secondary[data-pressed] { diff --git a/packages/components/src/Loading/LoadingParagraph/LoadingParagraph.module.scss b/packages/components/src/Loading/LoadingParagraph/LoadingParagraph.module.scss index cb9e3fc3002..6c1edb2cd9a 100644 --- a/packages/components/src/Loading/LoadingParagraph/LoadingParagraph.module.scss +++ b/packages/components/src/Loading/LoadingParagraph/LoadingParagraph.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/color'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/spacing'; @import '../mixins'; @@ -6,7 +7,7 @@ .loadingParagraph { @extend %loadingBase; - background-color: $color-gray-300; + background-color: $bg-tertiary; height: calc(#{$spacing-md} * 0.625); margin-bottom: calc(#{$spacing-md} * 0.5); } @@ -45,7 +46,7 @@ margin-bottom: 0; } - // We double the class selector to increase specificity above rules like `h1.default-style` + /* We double the class selector to increase specificity above rules like `h1.default-style`*/ .inheritBaseline.inheritBaseline { position: static; } diff --git a/packages/components/src/Menu/Menu.module.css b/packages/components/src/Menu/Menu.module.css index 9053a445224..8e1db934a1d 100644 --- a/packages/components/src/Menu/Menu.module.css +++ b/packages/components/src/Menu/Menu.module.css @@ -1,6 +1,6 @@ @layer kz-components { .menu { - color: var(--color-purple-800); + color: var(--text-primary); width: 248px; flex: 1 1 auto; min-height: 0; diff --git a/packages/components/src/Menu/MenuItem.module.css b/packages/components/src/Menu/MenuItem.module.css index 729cba9e6c5..acc1fede0fa 100644 --- a/packages/components/src/Menu/MenuItem.module.css +++ b/packages/components/src/Menu/MenuItem.module.css @@ -6,7 +6,7 @@ letter-spacing: var(--typography-paragraph-body-letter-spacing); font-weight: var(--typography-paragraph-body-font-weight); line-height: var(--typography-paragraph-body-line-height); - color: var(--color-purple-800); + color: var(--text-primary); padding: var(--spacing-6) var(--spacing-8); border: var(--border-focus-ring-border-width) var(--border-focus-ring-border-style) transparent; border-radius: 4px; @@ -33,8 +33,8 @@ .item[data-hovered], .item[data-focus-visible] { - background-color: var(--color-blue-100); - color: var(--color-blue-500); + background-color: var(--bg-brand-primary); + color: var(--text-brand-primary); } .item[data-focus-visible] { diff --git a/packages/components/src/MenuV1/subcomponents/MenuDropdown/MenuDropdown.module.scss b/packages/components/src/MenuV1/subcomponents/MenuDropdown/MenuDropdown.module.scss index de3d03e9c0f..64e78e594f9 100644 --- a/packages/components/src/MenuV1/subcomponents/MenuDropdown/MenuDropdown.module.scss +++ b/packages/components/src/MenuV1/subcomponents/MenuDropdown/MenuDropdown.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/border'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/color'; @import '~@kaizen/design-tokens/sass/shadow'; @import '~@kaizen/design-tokens/sass/spacing'; @@ -11,7 +12,7 @@ z-index: $dropdown-index; box-sizing: border-box; background: $color-white; - color: $color-purple-800; + color: $text-primary; border-radius: $border-solid-border-radius; box-shadow: $shadow-large-box-shadow; max-height: 22rem; diff --git a/packages/components/src/MenuV1/subcomponents/MenuHeading/MenuHeading.module.scss b/packages/components/src/MenuV1/subcomponents/MenuHeading/MenuHeading.module.scss index b413fefd2f5..98724696f24 100644 --- a/packages/components/src/MenuV1/subcomponents/MenuHeading/MenuHeading.module.scss +++ b/packages/components/src/MenuV1/subcomponents/MenuHeading/MenuHeading.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/color'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/spacing'; @layer kz-components { @@ -6,7 +7,7 @@ .heading { padding: 10px $spacing-sm 5px; - color: $color-purple-800; + color: $text-primary; margin: 0 $gutter; display: block; } diff --git a/packages/components/src/MenuV1/subcomponents/MenuItem/MenuItem.module.scss b/packages/components/src/MenuV1/subcomponents/MenuItem/MenuItem.module.scss index 137624b1c4a..32600d9dbd2 100644 --- a/packages/components/src/MenuV1/subcomponents/MenuItem/MenuItem.module.scss +++ b/packages/components/src/MenuV1/subcomponents/MenuItem/MenuItem.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/color'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/spacing'; @import '~@kaizen/design-tokens/sass/typography'; @@ -26,7 +27,7 @@ line-height: $typography-paragraph-body-line-height; letter-spacing: $typography-paragraph-body-letter-spacing; text-decoration: none; - color: $color-purple-800; + color: $text-primary; &:hover { text-decoration: none; @@ -34,19 +35,19 @@ &:not(.menuItem--disabled):hover, &:focus { - background: $color-blue-100; - color: $color-blue-500; + background: $bg-brand-primary; + color: $text-brand-primary; .menuItem__Icon { - color: $color-blue-500; + color: $text-brand-primary; } &.menuItem--destructive { - background: $color-red-100; - color: $color-red-600; + background: $bg-error-primary; + color: $text-error-primary; .menuItem__Icon { - color: $color-red-600; + color: $text-error-primary; } } } @@ -56,7 +57,7 @@ } &:focus-visible { - border-color: $color-blue-500; + border-color: $border-brand; } } @@ -69,15 +70,15 @@ } .menuItem--active { - color: $color-blue-500; + color: $text-brand-primary; font-weight: $typography-paragraph-bold-font-weight; } .menuItem--destructive { - color: $color-red-600; + color: $text-error-primary; .menuItem__Icon { - color: $color-red-600; + color: $text-error-primary; } } diff --git a/packages/components/src/Modal/ConfirmationModal/ConfirmationModal.module.scss b/packages/components/src/Modal/ConfirmationModal/ConfirmationModal.module.scss index 5d28d3f7b1b..2c2400cfb02 100644 --- a/packages/components/src/Modal/ConfirmationModal/ConfirmationModal.module.scss +++ b/packages/components/src/Modal/ConfirmationModal/ConfirmationModal.module.scss @@ -1,4 +1,5 @@ @import '~@kaizen/design-tokens/sass/border'; +@import '~@kaizen/design-tokens/sass/semantic-color'; @import '~@kaizen/design-tokens/sass/color'; @import '~@kaizen/design-tokens/sass/spacing'; @import '~@kaizen/design-tokens/sass/layout'; @@ -33,7 +34,7 @@ } } - // override Murmur global styles :( + /* override Murmur global styles :(*/ h1 { color: var(color-purple-800); } @@ -89,7 +90,7 @@ width: 155px; height: 155px; margin: 0 auto; - color: $color-purple-800; + color: $text-primary; @media (max-width: $layout-breakpoints-medium) { width: 86px; @@ -106,32 +107,32 @@ } } - // -------------------------------- - // variant styles - // -------------------------------- + /* --------------------------------*/ + /* variant styles*/ + /* --------------------------------*/ .success { - background-color: var(--color-green-100); + background-color: var(--bg-success-primary); - --spot-icon-color: var(--color-green-500); + --spot-icon-color: var(--fg-success-primary); } .informative { - background-color: var(--color-blue-100); + background-color: var(--bg-brand-primary); - --spot-icon-color: var(--color-blue-500); + --spot-icon-color: var(--fg-brand-primary); } .warning { - background-color: var(--color-red-100); + background-color: var(--bg-error-primary); - --spot-icon-color: var(--color-red-500); + --spot-icon-color: var(--fg-error-primary); } .cautionary { - background-color: var(--color-yellow-100); + background-color: var(--bg-warning-primary); - --spot-icon-color: var(--color-yellow-700); + --spot-icon-color: var(--fg-warning-primary); } - // -------------------------------- + /* --------------------------------*/ } diff --git a/packages/components/src/Modal/ConfirmationModal/_docs/ConfirmationModal.stories.tsx b/packages/components/src/Modal/ConfirmationModal/_docs/ConfirmationModal.stories.tsx index a8dde5d8586..43c6fdf602c 100644 --- a/packages/components/src/Modal/ConfirmationModal/_docs/ConfirmationModal.stories.tsx +++ b/packages/components/src/Modal/ConfirmationModal/_docs/ConfirmationModal.stories.tsx @@ -46,7 +46,7 @@ const ConfirmationModalTemplate: Story = { return ( <> - - - @@ -99,7 +99,7 @@ export const OnAfterEnter: Story = { return ( <> - -
+
>): JSX.Element , causing the element to be full width.*/ + + /* ^inline-flex is used over (block) flex here to fix an edge case where the parent element is display:grid */ + /* and this element is an , causing the element to be full width. */ align-items: center; box-sizing: border-box; min-height: $button-height; @@ -29,7 +30,7 @@ position: relative; text-align: left; cursor: pointer; - overflow: visible; /* Required for the focus ring on IE11*/ + overflow: visible; /* Required for the focus ring on IE11 */ &[href] { text-decoration: none; diff --git a/packages/components/src/Calendar/baseCalendarClassNames.module.scss b/packages/components/src/Calendar/baseCalendarClassNames.module.scss index a5e0ee99511..011708f45fd 100644 --- a/packages/components/src/Calendar/baseCalendarClassNames.module.scss +++ b/packages/components/src/Calendar/baseCalendarClassNames.module.scss @@ -183,10 +183,10 @@ } .dayDisabled { - /* Focus ring styles have been removed as react-day-picker has been updated such that*/ - /* disabled days do not receive focus, and keyboard navigation only lands on available days.*/ - /* https://github.com/gpbl/react-day-picker/pull/1519*/ - /* https://github.com/gpbl/react-day-picker/issues/1449#issuecomment-1149942033*/ + /* Focus ring styles have been removed as react-day-picker has been updated such that */ + /* disabled days do not receive focus, and keyboard navigation only lands on available days. */ + /* https://github.com/gpbl/react-day-picker/pull/1519 */ + /* https://github.com/gpbl/react-day-picker/issues/1449#issuecomment-1149942033 */ background: none; pointer-events: none; diff --git a/packages/components/src/Collapsible/Collapsible/Collapsible.module.scss b/packages/components/src/Collapsible/Collapsible/Collapsible.module.scss index 52c83c90c38..f934b1559a1 100644 --- a/packages/components/src/Collapsible/Collapsible/Collapsible.module.scss +++ b/packages/components/src/Collapsible/Collapsible/Collapsible.module.scss @@ -9,8 +9,8 @@ $divider-color: rgba($color-gray-600-rgb, 0.2); $container-border-width: var(--border-width-1); - /* We need a full border radius on this container element, then have classes*/ - /* beneath to toggle nested borders off and on for different use cases.*/ + /* We need a full border radius on this container element, then have classes */ + /* beneath to toggle nested borders off and on for different use cases. */ .container { background-color: $color-white; box-shadow: $shadow-small-box-shadow; @@ -33,8 +33,8 @@ background-color: $heading-active-color; } - /* Round the bottom corners of the header so when the container is open, the*/ - /* header background is not rounded on the corners and flush with the content beneath.*/ + /* Round the bottom corners of the header so when the container is open, the */ + /* header background is not rounded on the corners and flush with the content beneath. */ &.open { border-bottom-left-radius: 0; border-bottom-right-radius: 0; @@ -49,9 +49,9 @@ } } - /* When a collapsible group is rendered, we need the first group to have a rounded*/ - /* on top and the last group to have a rounded bottom edge. Then when the last group*/ - /* is open we remove the rounded edge as the content sits beneath and needs to be straight.*/ + /* When a collapsible group is rendered, we need the first group to have a rounded */ + /* on top and the last group to have a rounded bottom edge. Then when the last group */ + /* is open we remove the rounded edge as the content sits beneath and needs to be straight. */ .groupItem { & + .groupItem { border-top: 1px $border-solid-border-style $divider-color; @@ -76,7 +76,7 @@ } .chevronButton:hover { - /* hack to get rid of the IconButton hover styling because it clashes with the hover styling on the Collapsible header*/ + /* hack to get rid of the IconButton hover styling because it clashes with the hover styling on the Collapsible header */ background-color: transparent !important; /* stylelint-disable-line declaration-no-important */ } diff --git a/packages/components/src/Collapsible/CollapsibleGroup/CollapsibleGroup.module.scss b/packages/components/src/Collapsible/CollapsibleGroup/CollapsibleGroup.module.scss index 021c58a1a9b..b521723ed75 100644 --- a/packages/components/src/Collapsible/CollapsibleGroup/CollapsibleGroup.module.scss +++ b/packages/components/src/Collapsible/CollapsibleGroup/CollapsibleGroup.module.scss @@ -2,8 +2,8 @@ @import '~@kaizen/design-tokens/sass/shadow'; @layer kz-components { - /* We need a full border radius on this container element, then have classes*/ - /* beneath to toggle nested borders off and on for different use cases.*/ + /* We need a full border radius on this container element, then have classes */ + /* beneath to toggle nested borders off and on for different use cases. */ .container { background-color: white; box-shadow: $shadow-small-box-shadow; diff --git a/packages/components/src/Collapsible/ExpertAdviceCollapsible/ExpertAdviceCollapsible.module.scss b/packages/components/src/Collapsible/ExpertAdviceCollapsible/ExpertAdviceCollapsible.module.scss index 9b6e153da65..9c86cb85d02 100644 --- a/packages/components/src/Collapsible/ExpertAdviceCollapsible/ExpertAdviceCollapsible.module.scss +++ b/packages/components/src/Collapsible/ExpertAdviceCollapsible/ExpertAdviceCollapsible.module.scss @@ -15,7 +15,7 @@ } } - /* Override Collapsible header*/ + /* Override Collapsible header */ .expertAdviceContainer > div { &:first-of-type { background-color: $color-purple-100; diff --git a/packages/components/src/DateRangePicker/DateRangePicker.module.scss b/packages/components/src/DateRangePicker/DateRangePicker.module.scss index 630158584f9..bfb76aa611f 100644 --- a/packages/components/src/DateRangePicker/DateRangePicker.module.scss +++ b/packages/components/src/DateRangePicker/DateRangePicker.module.scss @@ -6,10 +6,10 @@ @import '../../styles/utils/button-reset'; @layer kz-components { - /* Vars*/ + /* Vars */ $button-height: 48px; $button-base-padding-horizontal: $spacing-sm; - $button-icon-size: 1.25rem; /* 20px*/ + $button-icon-size: 1.25rem; /* 20px */ $disabled-opacity: 0.5; $placeholder-opacity: 0.7; @@ -68,7 +68,7 @@ margin-top: -1px; } - /* Icon adornment styles*/ + /* Icon adornment styles */ @mixin vertically-center-icon { position: absolute; height: $button-icon-size; diff --git a/packages/components/src/Filter/FilterButton/subcomponents/FilterButtonBase/FilterButtonBase.module.scss b/packages/components/src/Filter/FilterButton/subcomponents/FilterButtonBase/FilterButtonBase.module.scss index edfed6b7d6d..8dd0c45e443 100644 --- a/packages/components/src/Filter/FilterButton/subcomponents/FilterButtonBase/FilterButtonBase.module.scss +++ b/packages/components/src/Filter/FilterButton/subcomponents/FilterButtonBase/FilterButtonBase.module.scss @@ -15,7 +15,7 @@ position: relative; display: inline-flex; align-items: center; - min-height: 3rem; /* 48px*/ + min-height: 3rem; /* 48px */ padding: $spacing-sm; border-width: 0; border-radius: $border-solid-border-radius; diff --git a/packages/components/src/Filter/FilterMultiSelect/subcomponents/MultiSelectOption/MultiSelectOption.module.scss b/packages/components/src/Filter/FilterMultiSelect/subcomponents/MultiSelectOption/MultiSelectOption.module.scss index 56c9baa5464..5b3d779516a 100644 --- a/packages/components/src/Filter/FilterMultiSelect/subcomponents/MultiSelectOption/MultiSelectOption.module.scss +++ b/packages/components/src/Filter/FilterMultiSelect/subcomponents/MultiSelectOption/MultiSelectOption.module.scss @@ -65,12 +65,12 @@ border: $border-focus-ring-border-width $border-focus-ring-border-style $border-brand; border-radius: $border-focus-ring-border-radius; inset: calc(-1 * #{$focus-ring-offset}); - z-index: 1; /* show border when sibling option is hovered*/ + z-index: 1; /* show border when sibling option is hovered */ } } &:focus { - outline: none; /* cancel browser style*/ + outline: none; /* cancel browser style */ } } @@ -90,7 +90,7 @@ } .badgeContainer { - /* Must be the same height as .icon, so they align vertically*/ + /* Must be the same height as .icon, so they align vertically */ height: $iconAndBadgeHeight; display: flex; align-items: center; diff --git a/packages/components/src/Filter/FilterMultiSelect/subcomponents/SelectionControlButton/SelectionControlButton.module.scss b/packages/components/src/Filter/FilterMultiSelect/subcomponents/SelectionControlButton/SelectionControlButton.module.scss index 08f3486c161..c5c31b4b9a2 100644 --- a/packages/components/src/Filter/FilterMultiSelect/subcomponents/SelectionControlButton/SelectionControlButton.module.scss +++ b/packages/components/src/Filter/FilterMultiSelect/subcomponents/SelectionControlButton/SelectionControlButton.module.scss @@ -53,7 +53,7 @@ inset: calc(-1 * #{$focus-ring-offset}); } - /* TODO: copied from Calendar button since the design is not settled*/ + /* TODO: copied from Calendar button since the design is not settled */ &.isDisabled { pointer-events: none; color: rgba($color-purple-800-rgb, 0.3); diff --git a/packages/components/src/Illustration/subcomponents/Base/Base.module.scss b/packages/components/src/Illustration/subcomponents/Base/Base.module.scss index b8bc984595b..5a79be035bd 100644 --- a/packages/components/src/Illustration/subcomponents/Base/Base.module.scss +++ b/packages/components/src/Illustration/subcomponents/Base/Base.module.scss @@ -13,7 +13,7 @@ position: relative; } - /* nested to get more specificity, beat out the generic button styles*/ + /* nested to get more specificity, beat out the generic button styles */ .figure .pausePlayButton { opacity: 0%; position: absolute; @@ -110,10 +110,10 @@ } } - /* If the .visually-hidden class is applied to natively focusable elements*/ - /* (such as a, button, input, etc) they must become visible when they receive*/ - /* keyboard focus. Otherwise, a sighted keyboard user would have to try and*/ - /* figure out where their visible focus indicator had gone to.*/ + /* If the .visually-hidden class is applied to natively focusable elements */ + /* (such as a, button, input, etc) they must become visible when they receive */ + /* keyboard focus. Otherwise, a sighted keyboard user would have to try and */ + /* figure out where their visible focus indicator had gone to. */ .visuallyHidden:not(:focus, :active) { clip-path: rect(0 0 0 0); position: absolute; diff --git a/packages/components/src/Input/Input/Input.module.scss b/packages/components/src/Input/Input/Input.module.scss index 74a428bb05f..3906b42f167 100644 --- a/packages/components/src/Input/Input/Input.module.scss +++ b/packages/components/src/Input/Input/Input.module.scss @@ -8,7 +8,7 @@ @layer kz-components { $input-height: 48px; $input-base-padding-horizontal: $spacing-sm; - $input-icon-size: 1.25rem; /* 20px*/ + $input-icon-size: 1.25rem; /* 20px */ $input-disabled-background: $color-gray-300; $input-disabled-opacity: 0.3; $input-disabled-border-alpha: 50%; @@ -60,9 +60,9 @@ } /* stylelint-disable no-descending-specificity */ - /*/////////////////////////////////////////////////*/ - /* ICON ADORNMENT STYLES*/ - /*/////////////////////////////////////////////////*/ + /* ///////////////////////////////////////////////// */ + /* ICON ADORNMENT STYLES */ + /* ///////////////////////////////////////////////// */ @mixin vertically-center-icon { position: absolute; @@ -114,7 +114,7 @@ } } - /* Default theme*/ + /* Default theme */ /* stylelint-disable-next-line no-duplicate-selectors */ .withStartIconAdornment { /* stylelint-disable-next-line no-duplicate-selectors */ @@ -140,7 +140,7 @@ } } - /* Reversed*/ + /* Reversed */ .withStartIconAdornment.withReversed { .startIconAdornment { color: $color-white; @@ -181,11 +181,11 @@ } } - /*/////////////////////////////////////////////////*/ - /* THEMES*/ - /*/////////////////////////////////////////////////*/ + /* ///////////////////////////////////////////////// */ + /* THEMES */ + /* ///////////////////////////////////////////////// */ - /* Default*/ + /* Default */ .input.default { background-color: $color-white; color: $text-primary; @@ -235,7 +235,7 @@ } } - /* Reversed (Dark Backgrounds)*/ + /* Reversed (Dark Backgrounds) */ .input.reversed { background: transparent; color: $color-white; diff --git a/packages/components/src/Input/InputSearch/InputSearch.module.scss b/packages/components/src/Input/InputSearch/InputSearch.module.scss index fd58ec7fd89..edf19dae661 100644 --- a/packages/components/src/Input/InputSearch/InputSearch.module.scss +++ b/packages/components/src/Input/InputSearch/InputSearch.module.scss @@ -9,7 +9,7 @@ $input-padding-before-start-icon: 1rem; $input-padding-between-icon-input: $spacing-sm; $input-padding-after-end-icon: $spacing-sm; - $input-icon-size: 1.25rem; /* 20px*/ + $input-icon-size: 1.25rem; /* 20px */ $input-padding-with-icon: calc( #{$input-padding-before-start-icon} + #{$input-icon-size} + #{$input-padding-between-icon-input} ); @@ -21,7 +21,7 @@ $input-placeholder-opacity--reversed: 0.8; $start-icon-opacity--reversed: $input-placeholder-opacity--reversed; - /* [type="search"] is required to override performance-ui global materialize CSS >:|*/ + /* [type="search"] is required to override performance-ui global materialize CSS >:| */ $classname--input: '.input[type="search"]'; .wrapper { @@ -101,11 +101,11 @@ } /* stylelint-disable no-descending-specificity */ - /*/////////////////////////////////////////////////*/ - /* THEMES*/ - /*/////////////////////////////////////////////////*/ + /* ///////////////////////////////////////////////// */ + /* THEMES */ + /* ///////////////////////////////////////////////// */ - /* Default*/ + /* Default */ .default { #{$classname--input} { border-color: $border-secondary; @@ -140,7 +140,7 @@ } } - /* Secondary*/ + /* Secondary */ .secondary { #{$classname--input} { border-color: transparent; @@ -175,7 +175,7 @@ } } - /* Reversed*/ + /* Reversed */ .reversed { #{$classname--input} { background: rgba($color-white-rgb, 0.1); diff --git a/packages/components/src/LikertScale/LikertScale.module.scss b/packages/components/src/LikertScale/LikertScale.module.scss index d8e89f53a78..07971df0505 100644 --- a/packages/components/src/LikertScale/LikertScale.module.scss +++ b/packages/components/src/LikertScale/LikertScale.module.scss @@ -125,7 +125,7 @@ padding: 0; overflow-x: visible; display: inline-block; - width: 18.5%; /* 5 columns*/ + width: 18.5%; /* 5 columns */ position: relative; @include fill($block-height); @@ -138,7 +138,7 @@ margin-inline-end: 0; } - /* Hack to bridge the gaps between items so mouse always hovers on something*/ + /* Hack to bridge the gaps between items so mouse always hovers on something */ &::before, &::after { content: ''; diff --git a/packages/components/src/Loading/LoadingParagraph/LoadingParagraph.module.scss b/packages/components/src/Loading/LoadingParagraph/LoadingParagraph.module.scss index 6c1edb2cd9a..c6851a13da5 100644 --- a/packages/components/src/Loading/LoadingParagraph/LoadingParagraph.module.scss +++ b/packages/components/src/Loading/LoadingParagraph/LoadingParagraph.module.scss @@ -46,7 +46,7 @@ margin-bottom: 0; } - /* We double the class selector to increase specificity above rules like `h1.default-style`*/ + /* We double the class selector to increase specificity above rules like `h1.default-style` */ .inheritBaseline.inheritBaseline { position: static; } diff --git a/packages/components/src/Modal/ConfirmationModal/ConfirmationModal.module.scss b/packages/components/src/Modal/ConfirmationModal/ConfirmationModal.module.scss index 2c2400cfb02..41535d3c881 100644 --- a/packages/components/src/Modal/ConfirmationModal/ConfirmationModal.module.scss +++ b/packages/components/src/Modal/ConfirmationModal/ConfirmationModal.module.scss @@ -34,7 +34,7 @@ } } - /* override Murmur global styles :(*/ + /* override Murmur global styles :( */ h1 { color: var(color-purple-800); } @@ -107,9 +107,9 @@ } } - /* --------------------------------*/ - /* variant styles*/ - /* --------------------------------*/ + /* -------------------------------- */ + /* variant styles */ + /* -------------------------------- */ .success { background-color: var(--bg-success-primary); @@ -134,5 +134,5 @@ --spot-icon-color: var(--fg-warning-primary); } - /* --------------------------------*/ + /* -------------------------------- */ } diff --git a/packages/components/src/Modal/GenericModal/GenericModal.module.scss b/packages/components/src/Modal/GenericModal/GenericModal.module.scss index 3a5f32bdd24..44a96da7d1e 100644 --- a/packages/components/src/Modal/GenericModal/GenericModal.module.scss +++ b/packages/components/src/Modal/GenericModal/GenericModal.module.scss @@ -35,9 +35,9 @@ } .modalLayer { - /* use flexbox auto margins to horizontally and vertically centre the modal*/ - /* because in IE11, `align-items: center` and `justify-content: center` cause*/ - /* long modal content to become unreachable if they go off-screen*/ + /* use flexbox auto margins to horizontally and vertically centre the modal */ + /* because in IE11, `align-items: center` and `justify-content: center` cause */ + /* long modal content to become unreachable if they go off-screen */ margin: auto; padding: $ca-grid 0; width: 100%; @@ -57,8 +57,8 @@ width: 100%; } - /* wrap the modal container with a focus ring when the title has focus*/ - /* for the rebuild: rather than putting the focus on the title, put it on the role=dialog element itself*/ + /* wrap the modal container with a focus ring when the title has focus */ + /* for the rebuild: rather than putting the focus on the title, put it on the role=dialog element itself */ &:has(:global([class*='modalLabel']):focus-visible) { outline: var(--border-focus-ring-border-width) var(--border-focus-ring-border-style) var(--color-blue-300); @@ -90,7 +90,7 @@ } } - /* WAITING FOR TEXTFIELD*/ + /* WAITING FOR TEXTFIELD */ .animatingEnter { [data-modal] { animation-duration: $ca-duration-fast; diff --git a/packages/components/src/MultiSelect/subcomponents/Checkbox/Checkbox.module.scss b/packages/components/src/MultiSelect/subcomponents/Checkbox/Checkbox.module.scss index db542e3d1a3..9ba25f183d7 100644 --- a/packages/components/src/MultiSelect/subcomponents/Checkbox/Checkbox.module.scss +++ b/packages/components/src/MultiSelect/subcomponents/Checkbox/Checkbox.module.scss @@ -42,10 +42,11 @@ } } - /* Selected = Checked or Indeterminate*/ + /* Selected = Checked or Indeterminate */ .selected { background: $color-gray-500; - /* To do: fix this in the CSS uplift*/ + + /* To do: fix this in the CSS uplift */ /* stylelint-disable-next-line declaration-block-no-redundant-longhand-properties */ background-color: $color-gray-500; diff --git a/packages/components/src/MultiSelect/subcomponents/MultiSelectOptionField/MultiSelectOptionField.module.scss b/packages/components/src/MultiSelect/subcomponents/MultiSelectOptionField/MultiSelectOptionField.module.scss index dd055b31bb5..24df77fbe05 100644 --- a/packages/components/src/MultiSelect/subcomponents/MultiSelectOptionField/MultiSelectOptionField.module.scss +++ b/packages/components/src/MultiSelect/subcomponents/MultiSelectOptionField/MultiSelectOptionField.module.scss @@ -44,7 +44,7 @@ border-color: $border-brand; } - /* removes default checkbox focus ring*/ + /* removes default checkbox focus ring */ .checkbox::after { display: none; } @@ -60,8 +60,8 @@ letter-spacing: $typography-paragraph-body-letter-spacing; overflow-wrap: anywhere; - /* Increases the hit area of the checkbox label to the size of*/ - /* the surrounding div for better mouse user experience*/ + /* Increases the hit area of the checkbox label to the size of */ + /* the surrounding div for better mouse user experience */ &::before { content: ''; width: 100%; diff --git a/packages/components/src/Pagination/Pagination.module.scss b/packages/components/src/Pagination/Pagination.module.scss index 6a010443ce1..76649073fb3 100644 --- a/packages/components/src/Pagination/Pagination.module.scss +++ b/packages/components/src/Pagination/Pagination.module.scss @@ -4,7 +4,7 @@ @import '~@kaizen/design-tokens/sass/border'; @layer kz-components { - /* Pagination*/ + /* Pagination */ .container { display: flex; align-items: center; diff --git a/packages/components/src/Popover/Popover.module.scss b/packages/components/src/Popover/Popover.module.scss index f8b2bbd364e..3058add281c 100644 --- a/packages/components/src/Popover/Popover.module.scss +++ b/packages/components/src/Popover/Popover.module.scss @@ -4,16 +4,16 @@ @import '../../styles/utils/button-reset'; @layer kz-components { - /* Sync with PopoverModern.tsx*/ + /* Sync with PopoverModern.tsx */ $arrow-width: 14px; $arrow-height: 7px; $large-width: 450px; - /* Suggestion: with this implementation, the anchor point of the popover is at the base of the triangle. But,*/ - /* we would ideally want it at the tip of the triangle. Otherwise, when using the popover, the consumer needs to manually*/ - /* add something like a `margin-top: 8px` to get the popover properly positioned.*/ - /* I didn't update this, as I didn't want to introduce a breaking change.*/ + /* Suggestion: with this implementation, the anchor point of the popover is at the base of the triangle. But, */ + /* we would ideally want it at the tip of the triangle. Otherwise, when using the popover, the consumer needs to manually */ + /* add something like a `margin-top: 8px` to get the popover properly positioned. */ + /* I didn't update this, as I didn't want to introduce a breaking change. */ @mixin arrow($background-color, $border-color) { &::before, &::after { @@ -41,7 +41,8 @@ width: 220px; position: absolute; left: 50%; - /* also see the component file under getRootStyle, which will transform the element*/ + + /* also see the component file under getRootStyle, which will transform the element */ } %box { @@ -111,13 +112,14 @@ .arrowWrapper { position: absolute; - /* Needed by popper, so it measures the size of the arrow correctly*/ + + /* Needed by popper, so it measures the size of the arrow correctly */ width: $arrow-width; height: $arrow-height; } .arrow { - /* Needed by popper, so it measures the size of the arrow correctly*/ + /* Needed by popper, so it measures the size of the arrow correctly */ width: $arrow-width; height: $arrow-height; } diff --git a/packages/components/src/RichTextEditor/_mixins.scss b/packages/components/src/RichTextEditor/_mixins.scss index d29e53e982d..12e0b02e631 100644 --- a/packages/components/src/RichTextEditor/_mixins.scss +++ b/packages/components/src/RichTextEditor/_mixins.scss @@ -11,7 +11,7 @@ letter-spacing: $typography-paragraph-body-letter-spacing; position: relative; /* stylelint-disable-next-line declaration-no-important */ - white-space: pre-wrap !important; /* Override unlayered TipTap styles from within kz-components layer*/ + white-space: pre-wrap !important; /* Override unlayered TipTap styles from within kz-components layer */ box-sizing: content-box; color: $text-primary; @@ -55,7 +55,7 @@ @mixin nested-list-styles { ul, ol { - padding-inline-start: $spacing-40; /* default browser styling*/ + padding-inline-start: $spacing-40; /* default browser styling */ } ol { diff --git a/packages/components/src/Select/Select.module.scss b/packages/components/src/Select/Select.module.scss index 7c19b9526c4..c983db4f1a0 100644 --- a/packages/components/src/Select/Select.module.scss +++ b/packages/components/src/Select/Select.module.scss @@ -21,7 +21,7 @@ layer to the React Select styles. */ -/* Should match the values for the Input component*/ +/* Should match the values for the Input component */ $input-height: 48px; $focus-border-color: $color-blue-500; @@ -106,14 +106,14 @@ $focus-border-color: $color-blue-500; } .menu { - /* Temporary 6px until we redesign this component with Inter*/ + /* Temporary 6px until we redesign this component with Inter */ border: 6px $border-solid-border-style transparent; border-radius: $border-solid-border-radius; box-shadow: $shadow-large-box-shadow; z-index: 3; - /* built-in class of React Select that is not easily styled any other way in CSS*/ - /* (This is the "MenuList" div that wraps all the options)*/ + /* built-in class of React Select that is not easily styled any other way in CSS */ + /* (This is the "MenuList" div that wraps all the options) */ > div { padding-top: 0; padding-bottom: 0; @@ -315,7 +315,7 @@ $focus-border-color: $color-blue-500; height: auto; > div { - /* see note on > div within .notFullWidth below for explanation*/ + /* see note on > div within .notFullWidth below for explanation */ height: $secondary-small-select-height; padding-left: 0; padding-right: 0; @@ -350,10 +350,10 @@ $focus-border-color: $color-blue-500; padding-bottom: 0; transform: translateY(1px); - /* Usually reaching into the Icon component like this is a no-no, but*/ - /* in this case we don't have access to the component in the middle which is*/ - /* part of react-select. I thought this would be better than hacking the*/ - /* structure of that component to allow one custom prop to trickle through.*/ + /* Usually reaching into the Icon component like this is a no-no, but */ + /* in this case we don't have access to the component in the middle which is */ + /* part of react-select. I thought this would be better than hacking the */ + /* structure of that component to allow one custom prop to trickle through. */ > svg { height: 14px; width: 14px; @@ -367,14 +367,14 @@ $focus-border-color: $color-blue-500; max-width: 100%; > div { - /* If this CSS is removed, then the control becomes too tall when*/ - /* it ellipsizes. It's strange, as the parent element is*/ - /* display: inline-block, so you wouldn't expect it to have any affect,*/ - /* but it works and was honesty a fluke from some unintentionally*/ - /* leftover code when refactoring to support IE11 :shrug*/ - /* I don't like the descendent selector, but there doesn't seem to be*/ - /* a way to customise this element in react-select.*/ - height: 44px; /* fixed height required for vertical centering, due to IE11 hack*/ + /* If this CSS is removed, then the control becomes too tall when */ + /* it ellipsizes. It's strange, as the parent element is */ + /* display: inline-block, so you wouldn't expect it to have any affect, */ + /* but it works and was honesty a fluke from some unintentionally */ + /* leftover code when refactoring to support IE11 :shrug */ + /* I don't like the descendent selector, but there doesn't seem to be */ + /* a way to customise this element in react-select. */ + height: 44px; /* fixed height required for vertical centering, due to IE11 hack */ flex-wrap: nowrap; display: flex; } diff --git a/packages/components/src/Table/Table.module.scss b/packages/components/src/Table/Table.module.scss index 22cd0b896e1..6aa86c0a03d 100644 --- a/packages/components/src/Table/Table.module.scss +++ b/packages/components/src/Table/Table.module.scss @@ -6,8 +6,8 @@ @import '~@kaizen/design-tokens/sass/color'; @layer kz-components { - /* Taken from design-tokens/sass/shadow*/ - /* we need control of the x and y offset in this component*/ + /* Taken from design-tokens/sass/shadow */ + /* we need control of the x and y offset in this component */ $box-shadow-color-sm: rgb(53, 55, 74, 0.09); $row-height: 60px; $row-height-data-variant: 48px; @@ -26,7 +26,7 @@ } } - /* Special Table-only button reset*/ + /* Special Table-only button reset */ @mixin button-reset { appearance: none; background: transparent; @@ -34,7 +34,7 @@ font: inherit; margin: 0; padding: 0; - transition: none; /* override Murmur global styles :(*/ + transition: none; /* override Murmur global styles :( */ outline: none; } @@ -48,9 +48,11 @@ align-items: stretch; text-align: start; justify-content: flex-start; - /* The 8px usually makes the height of the header cell 40px*/ + + /* The 8px usually makes the height of the header cell 40px */ padding: 8px $spacing-md; - /* This is required as so the tooltip will display directly above the header cell*/ + + /* This is required as so the tooltip will display directly above the header cell */ position: relative; } @@ -76,8 +78,8 @@ margin-inline-end: 10px; } - /* The .headerRowCell wrapper is required to increase the specificity, as so*/ - /* we can override the `Tooltip` component's styling.*/ + /* The .headerRowCell wrapper is required to increase the specificity, as so */ + /* we can override the `Tooltip` component's styling. */ .headerRowCell .headerRowCellTooltip { display: flex; align-items: stretch; @@ -95,7 +97,8 @@ display: flex; align-items: stretch; width: 100%; - /* Ensures that the 100% doesn't go outside of the `headerRowCell` width*/ + + /* Ensures that the 100% doesn't go outside of the `headerRowCell` width */ box-sizing: border-box; @include anchor-reset-pseudo-states; @@ -105,7 +108,7 @@ position: relative; &::after { - /* This offset provide enough gap on reverse for contrast ratios*/ + /* This offset provide enough gap on reverse for contrast ratios */ $focus-ring-offset: calc((#{$border-focus-ring-border-width} * 2) + 1px); top: 50%; @@ -136,7 +139,8 @@ display: flex; align-items: stretch; width: 100%; - /* Ensures that the 100% doesn't go outside of the `headerRowCell` width*/ + + /* Ensures that the 100% doesn't go outside of the `headerRowCell` width */ box-sizing: border-box; } @@ -167,11 +171,12 @@ .card { @include button-reset; - /* These css properties are required for when the rows are anchor elements*/ + + /* These css properties are required for when the rows are anchor elements */ @include anchor-reset; - /* This is an optical hack to stop the card shadow from overlapping over*/ - /* the proceeding cards*/ + /* This is an optical hack to stop the card shadow from overlapping over */ + /* the proceeding cards */ box-shadow: 0 4px 6px rgb(53, 55, 74, 0.04); border: solid 1px rgb($color-purple-700-rgb, 0.1); transition: @@ -202,7 +207,7 @@ position: relative; &::after { - /* This offset provide enough gap on on reverse for contrast ratios*/ + /* This offset provide enough gap on on reverse for contrast ratios */ $focus-ring-offset: calc(#{$border-focus-ring-border-width} + 2px); top: 50%; @@ -225,7 +230,7 @@ } } - /* target the first child card when there is a heading present*/ + /* target the first child card when there is a heading present */ [role='rowgroup'] + .card { border-top-left-radius: $border-solid-border-radius; border-top-right-radius: $border-solid-border-radius; @@ -279,7 +284,7 @@ } .rowCell { - /* These css properties are required for when the cells are anchor elements*/ + /* These css properties are required for when the cells are anchor elements */ @include anchor-reset; min-height: $row-height; diff --git a/packages/components/src/TitleBlock/TitleBlock.module.scss b/packages/components/src/TitleBlock/TitleBlock.module.scss index eee7baa7433..96eb2e3b57e 100644 --- a/packages/components/src/TitleBlock/TitleBlock.module.scss +++ b/packages/components/src/TitleBlock/TitleBlock.module.scss @@ -78,7 +78,7 @@ display: flex; flex-direction: column; width: 100%; - min-width: 0; /* this is an important trick to prevent flexbox items from overflowing*/ + min-width: 0; /* this is an important trick to prevent flexbox items from overflowing */ padding: 0 $title-block-spacing-default 0 0; @include title-block-min-media-1080 { @@ -148,9 +148,9 @@ .title { align-items: center; - min-width: 0; /* this is an important trick to prevent flexbox items from overflowing*/ + min-width: 0; /* this is an important trick to prevent flexbox items from overflowing */ - /* truncation*/ + /* truncation */ overflow: hidden; text-overflow: ellipsis; display: -webkit-box; @@ -158,8 +158,8 @@ -webkit-line-clamp: 3; -webkit-box-orient: vertical; - /* Applying width 100% when the title is *not* long and is followed by a subtitle*/ - /* causes misalignment of both.*/ + /* Applying width 100% when the title is *not* long and is followed by a subtitle */ + /* causes misalignment of both. */ @include title-block-under-1366 { width: 100%; } @@ -168,7 +168,7 @@ .titleAndSubtitle { display: flex; align-items: center; - min-width: 0; /* this is an important trick to prevent flexbox items from overflowing*/ + min-width: 0; /* this is an important trick to prevent flexbox items from overflowing */ transform: translateY(-0.0833em); .hasSubtitle & { @@ -180,9 +180,9 @@ .titleAndSubtitleInner { display: flex; - min-width: 0; /* this is an important trick to prevent flexbox items from overflowing*/ + min-width: 0; /* this is an important trick to prevent flexbox items from overflowing */ - /* TODO: removing .hasLongTitle here fixes the alignment on Performance story, but we should be able to not wrap subtitle.*/ + /* TODO: removing .hasLongTitle here fixes the alignment on Performance story, but we should be able to not wrap subtitle. */ .hasSubtitle.hasLongTitle.hasLongSubtitle & { align-items: center; @@ -365,7 +365,7 @@ display: flex; align-items: center; padding-block: 9px; - padding-inline-end: 8px; /* 20 take 12 result in 8 extra padding needed in section versus tabs UI*/ + padding-inline-end: 8px; /* 20 take 12 result in 8 extra padding needed in section versus tabs UI */ @include title-block-min-container-1080 { padding-block: 17px; @@ -435,13 +435,13 @@ .titleAndAdjacent { display: flex; - min-width: 0; /* this is an important trick to prevent flexbox items from overflowing*/ + min-width: 0; /* this is an important trick to prevent flexbox items from overflowing */ } .titleAndAdjacentNotBreadcrumb { display: flex; transition: opacity 0.3s ease; - min-width: 0; /* this is an important trick to prevent flexbox items from overflowing*/ + min-width: 0; /* this is an important trick to prevent flexbox items from overflowing */ align-items: center; .breadcrumb:hover ~ &, @@ -582,14 +582,14 @@ } } - /* This should be in SecondaryAction.module.scss,*/ - /* but the variants prevent us from breaking this out.*/ + /* This should be in SecondaryAction.module.scss, */ + /* but the variants prevent us from breaking this out. */ .secondaryActionsContainer { display: flex; - /* To be removed eventually – the Dropdown does not*/ - /* currently set its own color, and we want it*/ - /* to be Cluny like the default secondary buttons*/ + /* To be removed eventually – the Dropdown does not */ + /* currently set its own color, and we want it */ + /* to be Cluny like the default secondary buttons */ .lightVariant &, .educationVariant &, .adminVariant & { @@ -689,8 +689,8 @@ } .breadcrumbTextLink { - /* We are using visually hidden here instead of display:none so that a screen reader*/ - /* navigating via 'read mode' (which doesn't trigger hover/focus) will still hear this link name*/ + /* We are using visually hidden here instead of display:none so that a screen reader */ + /* navigating via 'read mode' (which doesn't trigger hover/focus) will still hear this link name */ @include visually-hidden; @include ca-position($start: -2 * $ca-grid); @@ -711,8 +711,9 @@ .breadcrumb:hover &, .breadcrumb:focus & { @include visually-hidden-reset; - /* ^be careful of this mixin unsetting values you need*/ - /* e.g. I needed to set position:absolute again below*/ + + /* ^be careful of this mixin unsetting values you need */ + /* e.g. I needed to set position:absolute again below */ position: absolute; display: block; animation: slide-fade 0.4s; diff --git a/packages/components/src/TitleBlock/subcomponents/NavigationTabs.module.scss b/packages/components/src/TitleBlock/subcomponents/NavigationTabs.module.scss index 09b02dcd69f..a8ce21b55fc 100644 --- a/packages/components/src/TitleBlock/subcomponents/NavigationTabs.module.scss +++ b/packages/components/src/TitleBlock/subcomponents/NavigationTabs.module.scss @@ -106,7 +106,8 @@ &:focus { &::before { background: transparent; - /* instead of height we're using the border to create a active tab mark to make it friendlier for Windows High Contrast Mode.*/ + + /* instead of height we're using the border to create a active tab mark to make it friendlier for Windows High Contrast Mode. */ border: $active-tab-marker-height solid transparent; height: 0; } diff --git a/packages/components/src/TitleBlock/subcomponents/TitleBlockMenuItem.module.scss b/packages/components/src/TitleBlock/subcomponents/TitleBlockMenuItem.module.scss index 8200b69b3e7..2349888b3db 100644 --- a/packages/components/src/TitleBlock/subcomponents/TitleBlockMenuItem.module.scss +++ b/packages/components/src/TitleBlock/subcomponents/TitleBlockMenuItem.module.scss @@ -6,7 +6,7 @@ /* stylelint-disable no-descending-specificity */ @layer kz-components { - /* We're duplicating the CSS instead of manipulating the Menu package to accept the alternate props*/ + /* We're duplicating the CSS instead of manipulating the Menu package to accept the alternate props */ .menuListItem { display: flex; } diff --git a/packages/components/src/TooltipV1/Tooltip.module.scss b/packages/components/src/TooltipV1/Tooltip.module.scss index 62ab38638ac..85bbc265345 100644 --- a/packages/components/src/TooltipV1/Tooltip.module.scss +++ b/packages/components/src/TooltipV1/Tooltip.module.scss @@ -9,14 +9,14 @@ @layer kz-components { .tooltip { - position: relative; /* Make this a positioned element so z-index works. (Note: Popper overrides this to absolute.)*/ + position: relative; /* Make this a positioned element so z-index works. (Note: Popper overrides this to absolute.) */ pointer-events: none; z-index: $ca-z-index-tooltip; } .tooltipContent { max-width: 400px; - padding: var(--spacing-8) calc(9rem / 16); /* 8px 9px*/ + padding: var(--spacing-8) calc(9rem / 16); /* 8px 9px */ color: $text-primary; text-align: center; font-family: $typography-paragraph-body-font-family; @@ -58,11 +58,11 @@ } .arrow { - /* Ensure the arrow always sits on top of the tooltipContent*/ + /* Ensure the arrow always sits on top of the tooltipContent */ z-index: 1; - /* This is required by popper, otherwise positioning issues will exist.*/ - /* https://github.com/popperjs/react-popper/issues/354#issuecomment-616540651*/ + /* This is required by popper, otherwise positioning issues will exist. */ + /* https://github.com/popperjs/react-popper/issues/354#issuecomment-616540651 */ position: absolute; [data-popper-placement^='top'] & { @@ -72,9 +72,9 @@ [data-popper-placement^='bottom'] & { top: 0; - /* There is a conflict with the popper arrow styling, which also*/ - /* adds a transform to the arrow. Hence, we need this additional*/ - /* wrapper, just to rotate it.*/ + /* There is a conflict with the popper arrow styling, which also */ + /* adds a transform to the arrow. Hence, we need this additional */ + /* wrapper, just to rotate it. */ .arrowInner { transform: rotate(180deg); } @@ -108,7 +108,7 @@ } .arrowMain { - /* before styles*/ + /* before styles */ &.default::before { border-top: $arrow-height solid var(--border-secondary); } @@ -128,7 +128,8 @@ &.cautionary::before { border-top: $arrow-height solid var(--color-yellow-700); } - /* after styles*/ + + /* after styles */ &::after { margin-top: -1.5px; } @@ -158,7 +159,7 @@ border-top: 0 solid $border-tertiary; } - /* Triangle portion is a little darker to bring out shadow*/ + /* Triangle portion is a little darker to bring out shadow */ .arrowShadow::after { border-top: $arrow-height solid rgba($color-purple-800-rgb, 0.09); margin-top: 1px; From b665ce3925ee984297538a1738197bb1308455ae Mon Sep 17 00:00:00 2001 From: AliceMenzie Date: Thu, 2 Jul 2026 15:06:50 +1000 Subject: [PATCH 25/25] changeset --- .changeset/green-planes-shine.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/green-planes-shine.md diff --git a/.changeset/green-planes-shine.md b/.changeset/green-planes-shine.md new file mode 100644 index 00000000000..9c6f0665cf3 --- /dev/null +++ b/.changeset/green-planes-shine.md @@ -0,0 +1,5 @@ +--- +'@kaizen/components': patch +--- + +add semantic colours