From 5e3915b955049594c8b5a5ee311069c8474cb912 Mon Sep 17 00:00:00 2001 From: Frankie Yan Date: Tue, 14 Jul 2026 17:41:48 -0700 Subject: [PATCH 01/12] build: add @doist/product-libraries-tokens as a pinned devDependency --- package-lock.json | 11 +++++++++++ package.json | 1 + 2 files changed, 12 insertions(+) diff --git a/package-lock.json b/package-lock.json index 9bb6c444..6b3b4b85 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "@babel/register": "7.29.3", "@doist/eslint-config": "12.0.1", "@doist/prettier-config": "4.0.1", + "@doist/product-libraries-tokens": "1.0.0", "@doist/react-compiler-tracker": "2.3.6", "@doist/tsconfig": "2.0.1", "@rollup/plugin-babel": "6.1.0", @@ -2384,6 +2385,16 @@ "prettier": "^3.0.0" } }, + "node_modules/@doist/product-libraries-tokens": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@doist/product-libraries-tokens/-/product-libraries-tokens-1.0.0.tgz", + "integrity": "sha512-Xx8lOvgkNGQZM5hYHslif9fodElQpB/aFFqnCgE7dgRA0KdGQ5QhBoGk4X9+m0CDVEu851DLz6U+OascBSeXCw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^22.14.0 || >=24.10.0" + } + }, "node_modules/@doist/react-compiler-tracker": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/@doist/react-compiler-tracker/-/react-compiler-tracker-2.3.6.tgz", diff --git a/package.json b/package.json index b25d5f55..3e1a46f2 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "@babel/register": "7.29.3", "@doist/eslint-config": "12.0.1", "@doist/prettier-config": "4.0.1", + "@doist/product-libraries-tokens": "1.0.0", "@doist/react-compiler-tracker": "2.3.6", "@doist/tsconfig": "2.0.1", "@rollup/plugin-babel": "6.1.0", From 70ff18acddaf016e65e7ae8c98b0aa54ae215075 Mon Sep 17 00:00:00 2001 From: Frankie Yan Date: Tue, 14 Jul 2026 17:41:53 -0700 Subject: [PATCH 02/12] feat: re-export product-library theme files from styles/tokens --- scripts/build.sh | 2 ++ scripts/copy-token-themes.sh | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100755 scripts/copy-token-themes.sh diff --git a/scripts/build.sh b/scripts/build.sh index d52ea29a..87d8621c 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -10,3 +10,5 @@ rimraf dist/assets # We delete duplicate styles in dist/ & lib/ ./scripts/organize-styles.sh +# Copy the product-library theme CSS into styles/tokens/ +./scripts/copy-token-themes.sh diff --git a/scripts/copy-token-themes.sh b/scripts/copy-token-themes.sh new file mode 100755 index 00000000..8f08816e --- /dev/null +++ b/scripts/copy-token-themes.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env sh + +# Copy the product library's generated theme CSS into styles/tokens/. As it is a devDependency, +# consumers do not install the token package themselves, Each file is stamped with the token +# package version for record. + +set -e + +SRC="node_modules/@doist/product-libraries-tokens/dist/colors/css" +DEST="styles/tokens" +VERSION=$(node -p "require('@doist/product-libraries-tokens/package.json').version") + +if [ ! -d "$SRC" ]; then + echo "āŒ $SRC not found — is @doist/product-libraries-tokens installed?" >&2 + exit 1 +fi + +mkdir -p "$DEST" +count=0 +for f in "$SRC"/*.css; do + name=$(basename "$f") + { + printf '/* @doist/product-libraries-tokens@%s — generated theme, do not edit. Copied at Reactist build time. */\n' "$VERSION" + cat "$f" + } >"$DEST/$name" + count=$((count + 1)) +done + +printf "\nšŸŽØ Copied %s token theme file(s) into %s (v%s).\n\n" "$count" "$DEST" "$VERSION" From 7b57f80e725f976493bb3642e03744f5eaf71c0f Mon Sep 17 00:00:00 2001 From: Frankie Yan Date: Tue, 14 Jul 2026 17:41:54 -0700 Subject: [PATCH 03/12] feat!: source Reactist color tokens from @doist/product-libraries-tokens --- .storybook/preview.ts | 1 + src/badge/badge.module.css | 16 +- src/banner/banner.module.css | 10 +- src/button/button.module.css | 42 ----- src/icons/banner-icon.module.css | 12 +- src/index.ts | 6 + src/modal/modal.module.css | 2 +- src/prose/prose.module.css | 20 +-- src/spinner/spinner.module.css | 4 +- src/styles/design-tokens.css | 214 ++++++++++++++--------- src/switch-field/switch-field.module.css | 6 +- src/tabs/tabs.module.css | 26 ++- src/text-link/text-link.module.css | 4 +- 13 files changed, 196 insertions(+), 167 deletions(-) diff --git a/.storybook/preview.ts b/.storybook/preview.ts index a026f414..62d8ba80 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -1,3 +1,4 @@ +import '@doist/product-libraries-tokens/css/td-light.css' import '../src/styles/design-tokens.css' import '../stories/components/styles/story.css' diff --git a/src/badge/badge.module.css b/src/badge/badge.module.css index 35c56731..b3193460 100644 --- a/src/badge/badge.module.css +++ b/src/badge/badge.module.css @@ -1,17 +1,17 @@ :root { --reactist-badge-font-size: 10px; - --reactist-badge-info-tint: #666666; - --reactist-badge-info-fill: #eeeeee; + --reactist-badge-info-tint: var(--product-library-info-neutral-tertiary-on-idle-tint); + --reactist-badge-info-fill: var(--product-library-info-neutral-tertiary-idle-fill); - --reactist-badge-positive-tint: #058527; - --reactist-badge-positive-fill: #e0f0e3; + --reactist-badge-positive-tint: var(--product-library-info-positive-secondary-on-idle-tint); + --reactist-badge-positive-fill: var(--product-library-info-positive-secondary-idle-fill); - --reactist-badge-promote-tint: #8f4700; - --reactist-badge-promote-fill: #faead1; + --reactist-badge-promote-tint: var(--product-library-info-promote-tertiary-on-idle-tint); + --reactist-badge-promote-fill: var(--product-library-info-promote-tertiary-idle-fill); - --reactist-badge-attention-tint: #cf473a; - --reactist-badge-attention-fill: #f9e3e2; + --reactist-badge-attention-tint: var(--product-library-info-attention-secondary-on-idle-tint); + --reactist-badge-attention-fill: var(--product-library-info-attention-secondary-idle-fill); } .badge { diff --git a/src/banner/banner.module.css b/src/banner/banner.module.css index 344294ec..2ed5c227 100644 --- a/src/banner/banner.module.css +++ b/src/banner/banner.module.css @@ -1,16 +1,16 @@ :root { - --reactist-banner-background-color: #fcfaf8; - --reactist-banner-border-color: #e6e6e6; - --reactist-banner-divider-color: var(--reactist-divider-secondary); + --reactist-banner-background-color: var(--product-library-background-base-secondary); + --reactist-banner-border-color: var(--product-library-border-idle-tint); + --reactist-banner-divider-color: var(--product-library-divider-secondary); --reactist-banner-main-copy-font-size: 14px; --reactist-banner-main-copy-line-height: 21px; --reactist-banner-main-copy-spacing: -0.15px; - --reactist-banner-main-copy-color: #202020; + --reactist-banner-main-copy-color: var(--product-library-display-primary-idle-tint); --reactist-banner-secondary-copy-font-size: 12px; --reactist-banner-secondary-copy-line-height: 20px; - --reactist-banner-secondary-copy-color: #666666; + --reactist-banner-secondary-copy-color: var(--product-library-display-secondary-idle-tint); --reactist-banner-min-width: 0; } diff --git a/src/button/button.module.css b/src/button/button.module.css index 9cf0c25e..66df51e0 100644 --- a/src/button/button.module.css +++ b/src/button/button.module.css @@ -13,48 +13,6 @@ --reactist-button-large-font-size: var(--reactist-font-size-body); --reactist-button-large-spacing: var(--reactist-spacing-large); --reactist-button-large-height: 36px; - - /* variant="primary" */ - --reactist-actionable-primary-idle-tint: #ffffff; - --reactist-actionable-primary-idle-fill: #008aa6; - --reactist-actionable-primary-hover-tint: #ffffff; - --reactist-actionable-primary-hover-fill: #007992; - --reactist-actionable-primary-disabled-tint: #ffffff; - --reactist-actionable-primary-disabled-fill: #99d0db; - - /* variant="secondary" */ - --reactist-actionable-secondary-idle-tint: #282f30; - --reactist-actionable-secondary-idle-fill: #f2f6f7; - --reactist-actionable-secondary-hover-tint: #282f30; - --reactist-actionable-secondary-hover-fill: #e3e7e8; - --reactist-actionable-secondary-disabled-tint: #a9acac; - --reactist-actionable-secondary-disabled-fill: #f2f6f7; - - /* variant="tertiary" (only has fill when hovered) */ - --reactist-actionable-tertiary-idle-tint: #006f85; - --reactist-actionable-tertiary-hover-tint: #006f85; - --reactist-actionable-tertiary-hover-fill: #f2f6f7; - --reactist-actionable-tertiary-disabled-tint: #99c5ce; - - /* variant="quaternary" (only has fill when hovered) */ - --reactist-actionable-quaternary-idle-tint: #6c777a; - --reactist-actionable-quaternary-hover-tint: #282f30; - --reactist-actionable-quaternary-hover-fill: #e0e7e8; - --reactist-actionable-quaternary-disabled-tint: #c4c9ca; - - /* variant="primary" tone="destructive" */ - --reactist-actionable-primary-destructive-idle-tint: #ffffff; - --reactist-actionable-primary-destructive-idle-fill: #dc4c3e; - --reactist-actionable-primary-destructive-hover-tint: #ffffff; - --reactist-actionable-primary-destructive-hover-fill: #b03d32; - --reactist-actionable-primary-destructive-disabled-tint: #ffffff; - --reactist-actionable-primary-destructive-disabled-fill: #f1b7b2; - - /* variant="secondary" tone="destructive" (optionally filled only when hovered) */ - --reactist-actionable-secondary-destructive-idle-tint: #dc4c3e; - --reactist-actionable-secondary-destructive-hover-tint: #b03d32; - --reactist-actionable-secondary-destructive-hover-fill: transparent; - --reactist-actionable-secondary-destructive-disabled-tint: #f1b7b2; } /* general styles for all buttons */ diff --git a/src/icons/banner-icon.module.css b/src/icons/banner-icon.module.css index 216ab064..27ece6fb 100644 --- a/src/icons/banner-icon.module.css +++ b/src/icons/banner-icon.module.css @@ -1,10 +1,10 @@ :root { - --reactist-banner-info-icon-color: #316fea; - --reactist-banner-upgrade-icon-color: #f48318; - --reactist-banner-experiment-icon-color: #f48318; - --reactist-banner-warning-icon-color: #eb8909; - --reactist-banner-error-icon-color: #dc4c3e; - --reactist-banner-success-icon-color: #058527; + --reactist-banner-info-icon-color: var(--product-library-info-neutral-primary-idle-fill); + --reactist-banner-upgrade-icon-color: var(--product-library-info-promote-primary-idle-fill); + --reactist-banner-experiment-icon-color: var(--product-library-info-promote-primary-idle-fill); + --reactist-banner-warning-icon-color: var(--product-library-info-warning-primary-on-idle-fill); + --reactist-banner-error-icon-color: var(--product-library-info-attention-primary-idle-fill); + --reactist-banner-success-icon-color: var(--product-library-info-positive-primary-idle-fill); } .info { diff --git a/src/index.ts b/src/index.ts index a2747233..6df21637 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,12 @@ /// /// +// Bundle the product library's light palette. Following package `exports` +// maps requires `eslint-import-resolver-typescript` on a newer version of +// eslint, so we are disabling the rule for now +// eslint-disable-next-line import/no-unresolved +import '@doist/product-libraries-tokens/css/td-light.css' + import './styles/design-tokens.css' // layout components diff --git a/src/modal/modal.module.css b/src/modal/modal.module.css index b0f4200e..77ab393b 100644 --- a/src/modal/modal.module.css +++ b/src/modal/modal.module.css @@ -8,7 +8,7 @@ } :root { - --reactist-modal-overlay-fill: rgba(0, 0, 0, 0.5); + --reactist-modal-overlay-fill: var(--product-library-background-overlay); --reactist-modal-padding-top: 13vh; } diff --git a/src/prose/prose.module.css b/src/prose/prose.module.css index a9ba8c2a..8362700f 100644 --- a/src/prose/prose.module.css +++ b/src/prose/prose.module.css @@ -1,17 +1,17 @@ :root { - --reactist-prose-code-fill: rgb(247, 250, 251); - --reactist-prose-code-tint: var(--reactist-content-primary); - --reactist-prose-code-border: var(--reactist-divider-primary); - --reactist-prose-quote-tint: #4a6368; + --reactist-prose-code-fill: var(--product-library-background-base-secondary); + --reactist-prose-code-tint: var(--product-library-display-primary-idle-tint); + --reactist-prose-code-border: var(--product-library-divider-primary); + --reactist-prose-quote-tint: var(--product-library-display-secondary-idle-tint); - --reactist-prose-link-idle-tint: #006f85; - --reactist-prose-link-idle-underline: var(--reactist-divider-primary); - --reactist-prose-link-hover-tint: #006f85; - --reactist-prose-link-hover-underline: #006f85; + --reactist-prose-link-idle-tint: inherit; + --reactist-prose-link-idle-underline: inherit; + --reactist-prose-link-hover-tint: var(--product-library-actionable-tertiary-hover-tint); + --reactist-prose-link-hover-underline: inherit; - --reactist-prose-horizontal-rule-color: var(--reactist-divider-primary); + --reactist-prose-horizontal-rule-color: var(--product-library-divider-primary); - --reactist-prose-table-border: var(--reactist-divider-primary); + --reactist-prose-table-border: var(--product-library-divider-primary); /* `transparent` (the initial value of `background-color`) rather than `initial`, which is special-cased in custom property values to mean "guaranteed invalid", or `inherit`, which diff --git a/src/spinner/spinner.module.css b/src/spinner/spinner.module.css index 4a402698..3f5045e7 100644 --- a/src/spinner/spinner.module.css +++ b/src/spinner/spinner.module.css @@ -1,6 +1,6 @@ :root { - --reactist-spinner-tint: var(--reactist-bg-brand); - --reactist-spinner-fill: var(--reactist-framework-fill-crest); + --reactist-spinner-tint: var(--product-library-display-accent-primary-fill); + --reactist-spinner-fill: var(--product-library-display-accent-secondary-fill); } @keyframes spinner { diff --git a/src/styles/design-tokens.css b/src/styles/design-tokens.css index c2417ff8..9e59202f 100644 --- a/src/styles/design-tokens.css +++ b/src/styles/design-tokens.css @@ -52,110 +52,166 @@ --reactist-font-weight-strong: 700; /* standard divider colors */ - --reactist-divider-primary: #c4c7c8; - --reactist-divider-secondary: #dde2e3; - --reactist-divider-tertiary: #edf2f3; + --reactist-divider-primary: var(--product-library-divider-primary); + --reactist-divider-secondary: var(--product-library-divider-secondary); + --reactist-divider-tertiary: var(--product-library-divider-tertiary); /* input border colors */ - --reactist-inputs-hover: var(--reactist-divider-primary); - --reactist-inputs-focus: var(--reactist-divider-primary); - --reactist-inputs-idle: var(--reactist-divider-secondary); - --reactist-inputs-alert: rgb(209, 69, 59); + --reactist-inputs-hover: var(--product-library-border-hover-tint); + --reactist-inputs-focus: var(--product-library-border-focus-tint); + --reactist-inputs-idle: var(--product-library-border-idle-tint); + --reactist-inputs-alert: var(--product-library-info-attention-primary-idle-tint); /* border-radius */ --reactist-border-radius-small: 5px; --reactist-border-radius-large: 10px; /* background color */ - --reactist-bg-default: rgb(255, 255, 255); - --reactist-bg-brand: rgb(36, 111, 224); - --reactist-bg-aside: rgb(250, 250, 250); - --reactist-bg-highlight: rgb(242, 242, 242); - --reactist-bg-selected: rgb(230, 230, 230); - --reactist-bg-toast: rgb(40, 40, 40); + --reactist-bg-default: var(--product-library-background-base-primary); + --reactist-bg-brand: rgb(36, 111, 224); /* no product-library source */ + --reactist-bg-aside: var(--product-library-background-base-secondary); + --reactist-bg-highlight: var(--product-library-actionable-quaternary-hover-fill); + --reactist-bg-selected: var(--product-library-selectable-secondary-selected-fill); + --reactist-bg-toast: var(--product-library-background-raised-quaternary); /* colors */ - --reactist-framework-fill-background: rgb(250, 250, 250); - --reactist-framework-fill-crest: rgb(230, 230, 230); - --reactist-framework-fill-selected: rgb(236, 236, 236); - --reactist-framework-fill-summit: rgb(214, 214, 214); - - --reactist-content-primary: rgba(0, 0, 0, 0.88); - --reactist-content-secondary: rgba(0, 0, 0, 0.56); - --reactist-content-tertiary: rgba(0, 0, 0, 0.4); - --reactist-toast-content-primary: rgb(255, 255, 255); - --reactist-toast-content-secondary: hsla(0, 0%, 100%, 0.56); - --reactist-content-positive: rgb(5, 133, 39); - --reactist-content-danger: rgb(209, 69, 59); + --reactist-framework-fill-background: var(--product-library-background-base-secondary); + --reactist-framework-fill-crest: rgb(230, 230, 230); /* no product-library source */ + --reactist-framework-fill-selected: rgb(236, 236, 236); /* no product-library source */ + --reactist-framework-fill-summit: var(--product-library-selectable-primary-unselected-fill); + + --reactist-content-primary: var(--product-library-display-primary-idle-tint); + --reactist-content-secondary: var(--product-library-display-secondary-idle-tint); + --reactist-content-tertiary: var(--product-library-display-tertiary-idle-tint); + --reactist-toast-content-primary: var(--product-library-display-primary-on-dark-tint); + --reactist-toast-content-secondary: hsla(0, 0%, 100%, 0.56); /* no product-library source */ + --reactist-content-positive: rgb(5, 133, 39); /* no product-library source */ + --reactist-content-danger: var(--product-library-actionable-destructive-idle-tint); /* component-specific */ /* actionable colors */ - --reactist-actionable-primary-idle-tint: #ffffff; - --reactist-actionable-primary-idle-fill: #008aa6; - --reactist-actionable-primary-hover-tint: #ffffff; - --reactist-actionable-primary-hover-fill: #007992; - --reactist-actionable-primary-disabled-tint: #ffffff; - --reactist-actionable-primary-disabled-fill: #99d0db; - - --reactist-actionable-secondary-idle-tint: #282f30; - --reactist-actionable-secondary-idle-fill: #f2f6f7; - --reactist-actionable-secondary-hover-tint: #282f30; - --reactist-actionable-secondary-hover-fill: #e3e7e8; - --reactist-actionable-secondary-disabled-tint: #a9acac; - --reactist-actionable-secondary-disabled-fill: #f2f6f7; - - --reactist-actionable-tertiary-idle-tint: #006f85; - --reactist-actionable-tertiary-hover-tint: #006f85; - --reactist-actionable-tertiary-hover-fill: #f2f6f7; - --reactist-actionable-tertiary-disabled-tint: #99c5ce; - - --reactist-actionable-quaternary-idle-tint: #6c777a; - --reactist-actionable-quaternary-hover-tint: #282f30; - --reactist-actionable-quaternary-hover-fill: #e0e7e8; - --reactist-actionable-quaternary-disabled-tint: #c4c9ca; - - --reactist-actionable-primary-destructive-idle-tint: #ffffff; - --reactist-actionable-primary-destructive-idle-fill: #dc4c3e; - --reactist-actionable-primary-destructive-hover-tint: #ffffff; - --reactist-actionable-primary-destructive-hover-fill: #b03d32; - --reactist-actionable-primary-destructive-disabled-tint: #ffffff; - --reactist-actionable-primary-destructive-disabled-fill: #f1b7b2; - - --reactist-actionable-secondary-destructive-idle-tint: #dc4c3e; - --reactist-actionable-secondary-destructive-hover-tint: #b03d32; + --reactist-actionable-primary-idle-tint: var(--product-library-actionable-primary-on-idle-tint); + --reactist-actionable-primary-idle-fill: var(--product-library-actionable-primary-idle-fill); + --reactist-actionable-primary-hover-tint: var( + --product-library-actionable-primary-on-hover-tint + ); + --reactist-actionable-primary-hover-fill: var(--product-library-actionable-primary-hover-fill); + --reactist-actionable-primary-disabled-tint: var( + --product-library-actionable-primary-on-disabled-tint + ); + --reactist-actionable-primary-disabled-fill: var( + --product-library-actionable-primary-disabled-fill + ); + + --reactist-actionable-secondary-idle-tint: var( + --product-library-actionable-secondary-on-idle-tint + ); + --reactist-actionable-secondary-idle-fill: var( + --product-library-actionable-secondary-idle-fill + ); + --reactist-actionable-secondary-hover-tint: var( + --product-library-actionable-secondary-on-hover-tint + ); + --reactist-actionable-secondary-hover-fill: var( + --product-library-actionable-secondary-hover-fill + ); + --reactist-actionable-secondary-disabled-tint: var( + --product-library-actionable-secondary-on-disabled-tint + ); + --reactist-actionable-secondary-disabled-fill: var( + --product-library-actionable-secondary-disabled-fill + ); + + --reactist-actionable-tertiary-idle-tint: var(--product-library-actionable-tertiary-idle-tint); + --reactist-actionable-tertiary-hover-tint: var( + --product-library-actionable-tertiary-on-hover-tint + ); + --reactist-actionable-tertiary-hover-fill: var( + --product-library-actionable-tertiary-hover-fill + ); + --reactist-actionable-tertiary-disabled-tint: var( + --product-library-actionable-tertiary-disabled-tint + ); + + --reactist-actionable-quaternary-idle-tint: var( + --product-library-actionable-quaternary-idle-tint + ); + --reactist-actionable-quaternary-hover-tint: var( + --product-library-actionable-quaternary-on-hover-tint + ); + --reactist-actionable-quaternary-hover-fill: var( + --product-library-actionable-quaternary-hover-fill + ); + --reactist-actionable-quaternary-disabled-tint: var( + --product-library-actionable-quaternary-disabled-tint + ); + + --reactist-actionable-primary-destructive-idle-tint: var( + --product-library-actionable-destructive-on-idle-tint + ); + --reactist-actionable-primary-destructive-idle-fill: var( + --product-library-actionable-destructive-idle-fill + ); + --reactist-actionable-primary-destructive-hover-tint: var( + --product-library-actionable-destructive-on-hover-tint + ); + --reactist-actionable-primary-destructive-hover-fill: var( + --product-library-actionable-destructive-hover-fill + ); + --reactist-actionable-primary-destructive-disabled-tint: var( + --product-library-actionable-destructive-on-disabled-tint + ); + --reactist-actionable-primary-destructive-disabled-fill: var( + --product-library-actionable-destructive-disabled-fill + ); + + --reactist-actionable-secondary-destructive-idle-tint: var( + --product-library-actionable-destructive-idle-tint + ); + --reactist-actionable-secondary-destructive-hover-tint: var( + --product-library-actionable-destructive-hover-tint + ); --reactist-actionable-secondary-destructive-hover-fill: transparent; - --reactist-actionable-secondary-destructive-disabled-tint: #f1b7b2; + --reactist-actionable-secondary-destructive-disabled-tint: var( + --product-library-actionable-destructive-disabled-tint + ); /* alerts */ - --reactist-alert-tone-info-icon: rgba(49, 111, 234); - --reactist-alert-tone-info-border: rgba(238, 238, 238); - --reactist-alert-tone-info-background: rgba(250, 250, 250); + --reactist-alert-tone-info-icon: var(--product-library-info-neutral-primary-idle-fill); + --reactist-alert-tone-info-border: var(--product-library-divider-primary); + --reactist-alert-tone-info-background: var(--product-library-background-base-secondary); - --reactist-alert-tone-positive-icon: rgba(5, 133, 39); - --reactist-alert-tone-positive-border: rgba(238, 238, 238); - --reactist-alert-tone-positive-background: rgba(250, 250, 250); + --reactist-alert-tone-positive-icon: var(--product-library-info-positive-primary-idle-fill); + --reactist-alert-tone-positive-border: var(--product-library-divider-primary); + --reactist-alert-tone-positive-background: var(--product-library-background-base-secondary); - --reactist-alert-tone-caution-icon: rgba(235, 137, 9); - --reactist-alert-tone-caution-border: rgba(238, 238, 238); - --reactist-alert-tone-caution-background: rgba(250, 250, 250); + --reactist-alert-tone-caution-icon: var(--product-library-info-warning-primary-on-idle-fill); + --reactist-alert-tone-caution-border: var(--product-library-divider-primary); + --reactist-alert-tone-caution-background: var(--product-library-background-base-secondary); - --reactist-alert-tone-critical-icon: rgba(220, 76, 62); - --reactist-alert-tone-critical-border: rgba(238, 238, 238); - --reactist-alert-tone-critical-background: rgba(250, 250, 250); + --reactist-alert-tone-critical-icon: var(--product-library-info-attention-primary-idle-fill); + --reactist-alert-tone-critical-border: var(--product-library-divider-primary); + --reactist-alert-tone-critical-background: var(--product-library-background-base-secondary); /* fields */ - --reactist-field-readonly-background: rgb(246, 244, 244); + --reactist-field-readonly-background: var(--product-library-background-base-tertiary); /* switches and checkboxes */ - --reactist-switch-background: var(--reactist-framework-fill-summit); - --reactist-switch-checked: var(--reactist-content-positive); - --reactist-switch-toggle: var(--reactist-bg-default); + --reactist-switch-background: var(--product-library-selectable-primary-unselected-fill); + --reactist-switch-checked: var(--product-library-actionable-primary-idle-fill); + --reactist-switch-toggle: var(--product-library-selectable-primary-on-selected-fill); /* toasts */ - --reactist-toast-actionable-primary-tint: #39d1ef; - --reactist-toast-actionable-secondary-tint: #b6c1c3; - --reactist-toast-actionable-hover-fill: #506063; + --reactist-toast-actionable-primary-tint: var( + --product-library-actionable-tertiary-on-dark-idle-tint + ); + --reactist-toast-actionable-secondary-tint: var( + --product-library-actionable-quaternary-on-dark-idle-tint + ); + --reactist-toast-actionable-hover-fill: var( + --product-library-actionable-tertiary-on-dark-hover-fill + ); --reactist-toast-box-shadow: rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px; /* stacking orders */ @@ -165,5 +221,5 @@ --reactist-stacking-order-tooltip: 1000; /* scrollbar colors */ - --reactist-scrollbar-thumb-idle: rgba(0, 0, 0, 0.2); + --reactist-scrollbar-thumb-idle: rgba(0, 0, 0, 0.2); /* no product-library source */ } diff --git a/src/switch-field/switch-field.module.css b/src/switch-field/switch-field.module.css index ebb3b6c3..47093954 100644 --- a/src/switch-field/switch-field.module.css +++ b/src/switch-field/switch-field.module.css @@ -1,7 +1,7 @@ :root { - --reactist-switch-background: var(--reactist-framework-fill-summit); - --reactist-switch-checked: var(--reactist-content-positive); - --reactist-switch-toggle: var(--reactist-bg-default); + --reactist-switch-background: var(--product-library-selectable-primary-unselected-fill); + --reactist-switch-checked: var(--product-library-actionable-primary-idle-fill); + --reactist-switch-toggle: var(--product-library-selectable-primary-on-selected-fill); } .container, diff --git a/src/tabs/tabs.module.css b/src/tabs/tabs.module.css index 2b9f958f..2cbdb42e 100644 --- a/src/tabs/tabs.module.css +++ b/src/tabs/tabs.module.css @@ -1,6 +1,6 @@ :root { --reactist-tab-themed-selected-tint: #006f85; - --reactist-tab-themed-selected-fill: var(--reactist-bg-default); + --reactist-tab-themed-selected-fill: var(--product-library-background-base-primary); --reactist-tab-themed-unselected-tint: #006f85; --reactist-tab-themed-unselected-fill: transparent; --reactist-tab-themed-hover-tint: #006f85; @@ -8,19 +8,27 @@ --reactist-tab-themed-disabled-tint: #006f85; --reactist-tab-themed-disabled-fill: transparent; --reactist-tab-themed-track: rgb(242, 246, 247); - --reactist-tab-themed-border: var(--reactist-divider-secondary); + --reactist-tab-themed-border: var(--product-library-divider-secondary); --reactist-tab-themed-shadow: none; - --reactist-tab-neutral-selected-tint: var(--reactist-content-primary); - --reactist-tab-neutral-selected-fill: var(--reactist-bg-default); - --reactist-tab-neutral-unselected-tint: var(--reactist-content-tertiary); + --reactist-tab-neutral-selected-tint: var( + --product-library-selectable-tertiary-on-selected-enabled-tint + ); + --reactist-tab-neutral-selected-fill: var(--product-library-selectable-tertiary-selected-fill); + --reactist-tab-neutral-unselected-tint: var( + --product-library-selectable-tertiary-on-unselected-enabled-tint + ); --reactist-tab-neutral-unselected-fill: transparent; - --reactist-tab-neutral-hover-tint: var(--reactist-content-tertiary); + --reactist-tab-neutral-hover-tint: var( + --product-library-selectable-tertiary-on-selected-enabled-tint + ); --reactist-tab-neutral-hover-fill: transparent; - --reactist-tab-neutral-disabled-tint: var(--reactist-content-tertiary); + --reactist-tab-neutral-disabled-tint: var( + --product-library-selectable-tertiary-on-unselected-disabled-tint + ); --reactist-tab-neutral-disabled-fill: transparent; - --reactist-tab-neutral-track: var(--reactist-framework-fill-selected); - --reactist-tab-neutral-border: var(--reactist-divider-primary); + --reactist-tab-neutral-track: var(--product-library-selectable-background); + --reactist-tab-neutral-border: var(--product-library-divider-primary); --reactist-tab-neutral-shadow: none; --reactist-tab-track-border-radius: 20px; diff --git a/src/text-link/text-link.module.css b/src/text-link/text-link.module.css index ead35ce1..20af6a33 100644 --- a/src/text-link/text-link.module.css +++ b/src/text-link/text-link.module.css @@ -1,6 +1,6 @@ :root { - --reactist-text-link-idle-tint: var(--reactist-actionable-tertiary-idle-tint); - --reactist-text-link-hover-tint: var(--reactist-actionable-tertiary-hover-tint); + --reactist-text-link-idle-tint: var(--product-library-actionable-tertiary-idle-tint); + --reactist-text-link-hover-tint: var(--product-library-actionable-tertiary-hover-tint); --reactist-text-link-idle-decoration: underline; --reactist-text-link-hover-decoration: underline; } From 49ff69cf3e57fe035e7e9c46ade5ccb806007273 Mon Sep 17 00:00:00 2001 From: Frankie Yan Date: Tue, 14 Jul 2026 17:42:01 -0700 Subject: [PATCH 04/12] docs: document product-library theming and token import paths --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.md b/README.md index 26522078..52d75443 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,39 @@ If you prefer to include static files grab the [minified build from the dist fol ``` +## Theming + +Reactist bakes a light palette (`@doist/product-libraries-tokens`) into `reactist.css`. To use a dark or accent theme, load one of the theme files Reactist re-exports and toggle its class on the root element: + +```html + +``` + +```js +import '@doist/reactist/styles/tokens/.css' +``` + +Then set the matching class on `:root`. Each theme file sets its own `color-scheme`, so you do not need to declare it yourself — the column below is what you get, not what you set. + +| Theme / file name | color-scheme | class | +| ------------------- | ------------ | ---------------------- | +| `td-light` | `light` | none | +| `td-dark` | `dark` | `theme_dark` | +| `td-blueberry` | `light` | `theme_blueberry` | +| `td-blueberry-dark` | `dark` | `theme_blueberry_dark` | +| `td-gold` | `light` | `theme_gold` | +| `td-gold-dark` | `dark` | `theme_gold_dark` | +| `td-kale` | `light` | `theme_kale` | +| `td-kale-dark` | `dark` | `theme_kale_dark` | +| `td-lavender` | `light` | `theme_lavender` | +| `td-lavender-dark` | `dark` | `theme_lavender_dark` | +| `td-moonstone` | `light` | `theme_moonstone` | +| `td-moonstone-dark` | `dark` | `theme_moonstone_dark` | +| `td-raspberry` | `light` | `theme_raspberry` | +| `td-raspberry-dark` | `dark` | `theme_raspberry_dark` | +| `td-tangerine` | `light` | `theme_tangerine` | +| `td-tangerine-dark` | `dark` | `theme_tangerine_dark` | + # Changelog You can find our changelog [here](./CHANGELOG.md). From 53ab829177e1f868cbd564a0e60a0adf38d93af7 Mon Sep 17 00:00:00 2001 From: Frankie Yan Date: Tue, 28 Jul 2026 13:45:13 -0700 Subject: [PATCH 05/12] refactor: point colour callsites at product-library tokens --- src/avatar/avatar.module.css | 2 +- src/base-field/base-field.module.css | 8 +-- src/box/box.module.css | 46 ++++++++----- src/button/button.module.css | 64 +++++++++---------- src/checkbox-field/checkbox-field.module.css | 6 +- .../progress-bar/progress-bar.module.css | 2 +- src/divider/divider.module.css | 6 +- src/heading/heading.module.css | 4 +- src/menu/menu.module.css | 26 +++++--- src/modal/modal.stories.tsx | 2 +- src/notice/notice.module.css | 10 +-- src/prose/prose.module.css | 4 +- src/prose/prose.stories.tsx | 3 +- src/select-field/select-field.module.css | 14 ++-- src/switch-field/switch-field.module.css | 8 +-- src/text-area/text-area.module.css | 12 ++-- src/text-field/text-field.module.css | 16 ++--- src/text/text.module.css | 6 +- src/toast/toast.module.css | 2 +- stories/components/color.stories.tsx | 57 +++++++---------- stories/components/styles/color-story.css | 6 +- 21 files changed, 156 insertions(+), 148 deletions(-) diff --git a/src/avatar/avatar.module.css b/src/avatar/avatar.module.css index 90aeb382..cfe69dcd 100644 --- a/src/avatar/avatar.module.css +++ b/src/avatar/avatar.module.css @@ -1,5 +1,5 @@ :root { - --reactist-avatar-initials-color: var(--reactist-actionable-primary-idle-tint); + --reactist-avatar-initials-color: var(--product-library-actionable-primary-on-idle-tint); --reactist-avatar-border-tint: #0000001a; --reactist-avatar-empty-fill: var(--reactist-framework-fill-crest); diff --git a/src/base-field/base-field.module.css b/src/base-field/base-field.module.css index e50898cf..8d09b865 100644 --- a/src/base-field/base-field.module.css +++ b/src/base-field/base-field.module.css @@ -18,7 +18,7 @@ .container.bordered { border-radius: var(--reactist-border-radius-large); - border: 1px solid var(--reactist-inputs-idle); + border: 1px solid var(--product-library-border-idle-tint); padding: var(--reactist-spacing-small); padding-bottom: var(--reactist-spacing-xsmall); overflow: clip; @@ -37,15 +37,15 @@ } .container.bordered:hover { - border-color: var(--reactist-inputs-hover) !important; + border-color: var(--product-library-border-hover-tint) !important; } .container.bordered:focus-within { - border-color: var(--reactist-inputs-focus) !important; + border-color: var(--product-library-border-focus-tint) !important; } .container.bordered.error { - border-color: var(--reactist-inputs-alert) !important; + border-color: var(--product-library-info-attention-primary-idle-tint) !important; } .container.bordered .primaryLabel { diff --git a/src/box/box.module.css b/src/box/box.module.css index 7202e45f..9adbb7c0 100644 --- a/src/box/box.module.css +++ b/src/box/box.module.css @@ -339,32 +339,44 @@ pre.box { /* background color */ .bg-default { - background-color: var(--reactist-bg-default); + background-color: var(--product-library-background-base-primary); } .bg-aside { - background-color: var(--reactist-bg-aside); + background-color: var(--product-library-background-base-secondary); } .bg-highlight { - background-color: var(--reactist-bg-highlight); + background-color: var(--product-library-actionable-quaternary-hover-fill); } .bg-selected { - background-color: var(--reactist-bg-selected); + background-color: var(--product-library-selectable-secondary-selected-fill); } /* toasts background-color requires more customization as it features an inverted (dark) background, even in light mode */ .bg-toast { - background-color: var(--reactist-bg-toast); - color: var(--reactist-content-primary); - --reactist-content-primary: var(--reactist-toast-content-primary); + background-color: var(--product-library-background-raised-quaternary); + color: var(--product-library-display-primary-idle-tint); + --reactist-content-primary: var(--product-library-display-primary-on-dark-tint); --reactist-content-secondary: var(--reactist-toast-content-secondary); - --reactist-text-link-idle-tint: var(--reactist-content-primary); + --reactist-text-link-idle-tint: var(--product-library-display-primary-idle-tint); --reactist-text-link-idle-decoration: var(--reactist-text-link-hover-decoration); - --reactist-actionable-tertiary-idle-tint: var(--reactist-toast-actionable-primary-tint); - --reactist-actionable-tertiary-hover-tint: var(--reactist-toast-actionable-primary-tint); - --reactist-actionable-tertiary-hover-fill: var(--reactist-toast-actionable-hover-fill); - --reactist-actionable-quaternary-idle-tint: var(--reactist-toast-actionable-secondary-tint); - --reactist-actionable-quaternary-hover-tint: var(--reactist-toast-actionable-secondary-tint); - --reactist-actionable-quaternary-hover-fill: var(--reactist-toast-actionable-hover-fill); + --reactist-actionable-tertiary-idle-tint: var( + --product-library-actionable-tertiary-on-dark-idle-tint + ); + --reactist-actionable-tertiary-hover-tint: var( + --product-library-actionable-tertiary-on-dark-idle-tint + ); + --reactist-actionable-tertiary-hover-fill: var( + --product-library-actionable-tertiary-on-dark-hover-fill + ); + --reactist-actionable-quaternary-idle-tint: var( + --product-library-actionable-quaternary-on-dark-idle-tint + ); + --reactist-actionable-quaternary-hover-tint: var( + --product-library-actionable-quaternary-on-dark-idle-tint + ); + --reactist-actionable-quaternary-hover-fill: var( + --product-library-actionable-tertiary-on-dark-hover-fill + ); } /* border radius */ @@ -377,13 +389,13 @@ pre.box { /* border */ .border-primary { - border: 1px solid var(--reactist-divider-primary); + border: 1px solid var(--product-library-divider-primary); } .border-secondary { - border: 1px solid var(--reactist-divider-secondary); + border: 1px solid var(--product-library-divider-secondary); } .border-tertiary { - border: 1px solid var(--reactist-divider-tertiary); + border: 1px solid var(--product-library-divider-tertiary); } /* text-align */ diff --git a/src/button/button.module.css b/src/button/button.module.css index 66df51e0..3e03d2e4 100644 --- a/src/button/button.module.css +++ b/src/button/button.module.css @@ -139,58 +139,58 @@ /* variants with normal tone */ .variant-primary { - --reactist-btn-idle-tint: var(--reactist-actionable-primary-idle-tint); - --reactist-btn-idle-fill: var(--reactist-actionable-primary-idle-fill); - --reactist-btn-hover-tint: var(--reactist-actionable-primary-hover-tint); - --reactist-btn-hover-fill: var(--reactist-actionable-primary-hover-fill); - --reactist-btn-disabled-tint: var(--reactist-actionable-primary-disabled-tint); - --reactist-btn-disabled-fill: var(--reactist-actionable-primary-disabled-fill); + --reactist-btn-idle-tint: var(--product-library-actionable-primary-on-idle-tint); + --reactist-btn-idle-fill: var(--product-library-actionable-primary-idle-fill); + --reactist-btn-hover-tint: var(--product-library-actionable-primary-on-hover-tint); + --reactist-btn-hover-fill: var(--product-library-actionable-primary-hover-fill); + --reactist-btn-disabled-tint: var(--product-library-actionable-primary-on-disabled-tint); + --reactist-btn-disabled-fill: var(--product-library-actionable-primary-disabled-fill); } .variant-secondary { - --reactist-btn-idle-tint: var(--reactist-actionable-secondary-idle-tint); - --reactist-btn-idle-fill: var(--reactist-actionable-secondary-idle-fill); - --reactist-btn-hover-tint: var(--reactist-actionable-secondary-hover-tint); - --reactist-btn-hover-fill: var(--reactist-actionable-secondary-hover-fill); - --reactist-btn-disabled-tint: var(--reactist-actionable-secondary-disabled-tint); - --reactist-btn-disabled-fill: var(--reactist-actionable-secondary-disabled-fill); + --reactist-btn-idle-tint: var(--product-library-actionable-secondary-on-idle-tint); + --reactist-btn-idle-fill: var(--product-library-actionable-secondary-idle-fill); + --reactist-btn-hover-tint: var(--product-library-actionable-secondary-on-hover-tint); + --reactist-btn-hover-fill: var(--product-library-actionable-secondary-hover-fill); + --reactist-btn-disabled-tint: var(--product-library-actionable-secondary-on-disabled-tint); + --reactist-btn-disabled-fill: var(--product-library-actionable-secondary-disabled-fill); } .variant-tertiary { - --reactist-btn-idle-tint: var(--reactist-actionable-tertiary-idle-tint); + --reactist-btn-idle-tint: var(--product-library-actionable-tertiary-idle-tint); --reactist-btn-idle-fill: transparent; - --reactist-btn-hover-tint: var(--reactist-actionable-tertiary-hover-tint); - --reactist-btn-hover-fill: var(--reactist-actionable-tertiary-hover-fill); - --reactist-btn-disabled-tint: var(--reactist-actionable-tertiary-disabled-tint); + --reactist-btn-hover-tint: var(--product-library-actionable-tertiary-on-hover-tint); + --reactist-btn-hover-fill: var(--product-library-actionable-tertiary-hover-fill); + --reactist-btn-disabled-tint: var(--product-library-actionable-tertiary-disabled-tint); --reactist-btn-disabled-fill: transparent; } .variant-quaternary { - --reactist-btn-idle-tint: var(--reactist-actionable-quaternary-idle-tint); + --reactist-btn-idle-tint: var(--product-library-actionable-quaternary-idle-tint); --reactist-btn-idle-fill: transparent; - --reactist-btn-hover-tint: var(--reactist-actionable-quaternary-hover-tint); - --reactist-btn-hover-fill: var(--reactist-actionable-quaternary-hover-fill); - --reactist-btn-disabled-tint: var(--reactist-actionable-quaternary-disabled-tint); + --reactist-btn-hover-tint: var(--product-library-actionable-quaternary-on-hover-tint); + --reactist-btn-hover-fill: var(--product-library-actionable-quaternary-hover-fill); + --reactist-btn-disabled-tint: var(--product-library-actionable-quaternary-disabled-tint); --reactist-btn-disabled-fill: transparent; } /* variants with destructive tone */ .variant-primary.tone-destructive { - --reactist-btn-idle-tint: var(--reactist-actionable-primary-destructive-idle-tint); - --reactist-btn-idle-fill: var(--reactist-actionable-primary-destructive-idle-fill); - --reactist-btn-hover-tint: var(--reactist-actionable-primary-destructive-hover-tint); - --reactist-btn-hover-fill: var(--reactist-actionable-primary-destructive-hover-fill); - --reactist-btn-disabled-tint: var(--reactist-actionable-primary-destructive-disabled-tint); - --reactist-btn-disabled-fill: var(--reactist-actionable-primary-destructive-disabled-fill); + --reactist-btn-idle-tint: var(--product-library-actionable-destructive-on-idle-tint); + --reactist-btn-idle-fill: var(--product-library-actionable-destructive-idle-fill); + --reactist-btn-hover-tint: var(--product-library-actionable-destructive-on-hover-tint); + --reactist-btn-hover-fill: var(--product-library-actionable-destructive-hover-fill); + --reactist-btn-disabled-tint: var(--product-library-actionable-destructive-on-disabled-tint); + --reactist-btn-disabled-fill: var(--product-library-actionable-destructive-disabled-fill); } .variant-secondary.tone-destructive { - --reactist-btn-idle-tint: var(--reactist-actionable-secondary-destructive-idle-tint); + --reactist-btn-idle-tint: var(--product-library-actionable-destructive-idle-tint); --reactist-btn-idle-fill: transparent; - --reactist-btn-hover-tint: var(--reactist-actionable-secondary-destructive-hover-tint); + --reactist-btn-hover-tint: var(--product-library-actionable-destructive-hover-tint); --reactist-btn-hover-fill: var(--reactist-actionable-secondary-destructive-hover-fill); - --reactist-btn-disabled-tint: var(--reactist-actionable-secondary-destructive-disabled-tint); + --reactist-btn-disabled-tint: var(--product-library-actionable-destructive-disabled-tint); --reactist-btn-disabled-fill: transparent; } @@ -207,7 +207,7 @@ .variant-tertiary.tone-destructive, .variant-quaternary.tone-destructive { - --reactist-btn-idle-tint: var(--reactist-actionable-secondary-destructive-idle-tint); - --reactist-btn-hover-tint: var(--reactist-actionable-secondary-destructive-hover-tint); - --reactist-btn-disabled-tint: var(--reactist-actionable-secondary-destructive-disabled-tint); + --reactist-btn-idle-tint: var(--product-library-actionable-destructive-idle-tint); + --reactist-btn-hover-tint: var(--product-library-actionable-destructive-hover-tint); + --reactist-btn-disabled-tint: var(--product-library-actionable-destructive-disabled-tint); } diff --git a/src/checkbox-field/checkbox-field.module.css b/src/checkbox-field/checkbox-field.module.css index 04f4b74f..40b06127 100644 --- a/src/checkbox-field/checkbox-field.module.css +++ b/src/checkbox-field/checkbox-field.module.css @@ -18,13 +18,13 @@ } .container svg { - color: var(--reactist-content-secondary); + color: var(--product-library-display-secondary-idle-tint); border-radius: 5px; min-width: 24px; } .container.checked svg { - color: var(--reactist-switch-checked); + color: var(--product-library-actionable-primary-idle-fill); } .container input[type='checkbox'] { @@ -39,7 +39,7 @@ } .container.keyFocused svg { - border: 2px solid var(--reactist-actionable-primary-idle-fill); + border: 2px solid var(--product-library-actionable-primary-idle-fill); } .icon { diff --git a/src/components/progress-bar/progress-bar.module.css b/src/components/progress-bar/progress-bar.module.css index 5109f0ec..2d3567a0 100644 --- a/src/components/progress-bar/progress-bar.module.css +++ b/src/components/progress-bar/progress-bar.module.css @@ -4,7 +4,7 @@ --reactist-progressbar-radius-inner: var(--reactist-progressbar-height); --reactist-progressbar-track: var(--reactist-framework-fill-crest); --reactist-progressbar-fill: var(--reactist-bg-brand); - --reactist-progressbar-scale-tint: var(--reactist-content-tertiary); + --reactist-progressbar-scale-tint: var(--product-library-display-tertiary-idle-tint); --reactist-progressbar-scale-tick-height: 8px; --reactist-progressbar-scale-minor-tick-opacity: 0.15; --reactist-progressbar-scale-major-tick-opacity: 0.35; diff --git a/src/divider/divider.module.css b/src/divider/divider.module.css index 4ff47b38..733841bb 100644 --- a/src/divider/divider.module.css +++ b/src/divider/divider.module.css @@ -1,9 +1,9 @@ .weight-primary { - border-bottom: 1px solid var(--reactist-divider-primary); + border-bottom: 1px solid var(--product-library-divider-primary); } .weight-secondary { - border-bottom: 1px solid var(--reactist-divider-secondary); + border-bottom: 1px solid var(--product-library-divider-secondary); } .weight-tertiary { - border-bottom: 1px solid var(--reactist-divider-tertiary); + border-bottom: 1px solid var(--product-library-divider-tertiary); } diff --git a/src/heading/heading.module.css b/src/heading/heading.module.css index aee2b460..2ca4387a 100644 --- a/src/heading/heading.module.css +++ b/src/heading/heading.module.css @@ -1,5 +1,5 @@ .heading { - color: var(--reactist-content-primary); + color: var(--product-library-display-primary-idle-tint); font-weight: var(--reactist-font-weight-strong); font-family: var(--reactist-font-family); } @@ -15,7 +15,7 @@ /* tone */ .tone-secondary { - color: var(--reactist-content-secondary); + color: var(--product-library-display-secondary-idle-tint); } .tone-danger { color: rgb(209, 69, 59); diff --git a/src/menu/menu.module.css b/src/menu/menu.module.css index 1659fd26..3189f402 100644 --- a/src/menu/menu.module.css +++ b/src/menu/menu.module.css @@ -10,7 +10,7 @@ font-size: var(--reactist-font-size-copy); padding: 4px 0; min-width: 180px; - border: 1px solid var(--reactist-divider-secondary); + border: 1px solid var(--product-library-divider-secondary); border-radius: 3px; margin: -4px; /* Required to add spacing between the viewport, used in conjunction with unstable_offset */ z-index: var(--reactist-stacking-order-menu); @@ -32,7 +32,7 @@ } :global(.reactist_menulist) :global(.reactist_menugroup__label) { - color: var(--reactist-content-secondary); + color: var(--product-library-display-secondary-idle-tint); font-size: var(--reactist-font-size-copy); } @@ -44,13 +44,13 @@ :global(.reactist_menulist) [role='menuitem']:hover, :global(.reactist_menulist) [role='menuitem']:focus, :global(.reactist_menulist) [role='menuitem'][aria-expanded='true'] { - color: var(--reactist-content-primary); - background-color: var(--reactist-bg-selected); + color: var(--product-library-display-primary-idle-tint); + background-color: var(--product-library-selectable-secondary-selected-fill); } :global(.reactist_menulist) [role='menuitem'][aria-disabled='true'], :global(.reactist_menulist) [role='menuitem']:disabled { - color: var(--reactist-content-secondary); + color: var(--product-library-display-secondary-idle-tint); pointer-events: none; } @@ -65,19 +65,25 @@ /* Link menu items without an icon are styled like a text link */ :global(.reactist_menulist) a[role='menuitem']:not(:has(svg)):not([aria-disabled='true']) { - color: var(--reactist-text-link-idle-tint, var(--reactist-actionable-tertiary-idle-tint)); + color: var( + --reactist-text-link-idle-tint, + var(--product-library-actionable-tertiary-idle-tint) + ); --reactist-content-primary: var( --reactist-text-link-idle-tint, - var(--reactist-actionable-tertiary-idle-tint) + var(--product-library-actionable-tertiary-idle-tint) ); } :global(.reactist_menulist) a[role='menuitem']:not(:has(svg)):not([aria-disabled='true']):hover, :global(.reactist_menulist) a[role='menuitem']:not(:has(svg)):not([aria-disabled='true']):focus { - color: var(--reactist-text-link-hover-tint, var(--reactist-actionable-tertiary-hover-tint)); + color: var( + --reactist-text-link-hover-tint, + var(--product-library-actionable-tertiary-on-hover-tint) + ); --reactist-content-primary: var( --reactist-text-link-hover-tint, - var(--reactist-actionable-tertiary-hover-tint) + var(--product-library-actionable-tertiary-on-hover-tint) ); } @@ -89,6 +95,6 @@ :global(.reactist_menulist) hr { border: none; height: 1px; - background-color: var(--reactist-bg-selected); + background-color: var(--product-library-selectable-secondary-selected-fill); margin: 4px 0; } diff --git a/src/modal/modal.stories.tsx b/src/modal/modal.stories.tsx index 9c82f342..0d339d02 100644 --- a/src/modal/modal.stories.tsx +++ b/src/modal/modal.stories.tsx @@ -253,7 +253,7 @@ export function ModalWithScrollableTabPanels() { diff --git a/src/notice/notice.module.css b/src/notice/notice.module.css index a76331fc..29095f7e 100644 --- a/src/notice/notice.module.css +++ b/src/notice/notice.module.css @@ -1,5 +1,5 @@ .container { - color: var(--reactist-content-primary); + color: var(--product-library-display-primary-idle-tint); } .content { @@ -11,17 +11,17 @@ } .tone-info .icon { - color: var(--reactist-alert-tone-info-icon); + color: var(--product-library-info-neutral-primary-idle-fill); } .tone-positive .icon { - color: var(--reactist-alert-tone-positive-icon); + color: var(--product-library-info-positive-primary-idle-fill); } .tone-caution .icon { - color: var(--reactist-alert-tone-caution-icon); + color: var(--product-library-info-warning-primary-on-idle-fill); } .tone-critical .icon { - color: var(--reactist-alert-tone-critical-icon); + color: var(--product-library-info-attention-primary-idle-fill); } diff --git a/src/prose/prose.module.css b/src/prose/prose.module.css index 8362700f..2e4befa5 100644 --- a/src/prose/prose.module.css +++ b/src/prose/prose.module.css @@ -44,7 +44,7 @@ .prose { font-size: var(--reactist-prose-content-font-size); - color: var(--reactist-content-primary); + color: var(--product-library-display-primary-idle-tint); line-height: 1.65; overflow-wrap: break-word; word-wrap: break-word; @@ -179,7 +179,7 @@ .prose blockquote::before { content: ''; - border-left: 2px solid var(--reactist-divider-primary); + border-left: 2px solid var(--product-library-divider-primary); position: absolute; top: 0.25em; bottom: 0.25em; diff --git a/src/prose/prose.stories.tsx b/src/prose/prose.stories.tsx index 81181990..3b8bc19b 100644 --- a/src/prose/prose.stories.tsx +++ b/src/prose/prose.stories.tsx @@ -34,7 +34,8 @@ export function ProsePlaygroundStory({ darkModeTypography, dangerouslySetInnerHT '--reactist-content-primary': 'rgba(255, 255, 255, 0.88)', '--reactist-prose-code-tint': 'rgba(255, 255, 255, 0.88)', '--reactist-prose-code-fill': 'rgb(40, 40, 40)', - '--reactist-prose-code-border': 'var(--reactist-divider-secondary)', + '--reactist-prose-code-border': + 'var(--product-library-divider-secondary)', '--reactist-prose-quote-tint': '#9db4b9', // divider colors '--reactist-divider-primary': '#53595b', diff --git a/src/select-field/select-field.module.css b/src/select-field/select-field.module.css index 11020ce5..bb87ea19 100644 --- a/src/select-field/select-field.module.css +++ b/src/select-field/select-field.module.css @@ -15,7 +15,7 @@ right: 10px; top: 8px; bottom: 8px; - color: var(--reactist-content-secondary); + color: var(--product-library-display-secondary-idle-tint); } .selectWrapper select { @@ -41,25 +41,25 @@ appearance: none; box-sizing: border-box; width: 100%; - color: var(--reactist-content-primary); + color: var(--product-library-display-primary-idle-tint); background: none; border-radius: var(--reactist-border-radius-small); - border: 1px solid var(--reactist-inputs-idle); + border: 1px solid var(--product-library-border-idle-tint); margin: 0; } .selectWrapper:not(.bordered).error select { - border-color: var(--reactist-inputs-alert) !important; + border-color: var(--product-library-info-attention-primary-idle-tint) !important; } .selectWrapper:not(.bordered) option { - background-color: var(--reactist-bg-aside); + background-color: var(--product-library-background-base-secondary); } .selectWrapper:not(.bordered) select:hover { - border-color: var(--reactist-inputs-hover); + border-color: var(--product-library-border-hover-tint); } .selectWrapper:not(.bordered) select:focus { - border-color: var(--reactist-inputs-focus); + border-color: var(--product-library-border-focus-tint); } diff --git a/src/switch-field/switch-field.module.css b/src/switch-field/switch-field.module.css index 47093954..dacdd984 100644 --- a/src/switch-field/switch-field.module.css +++ b/src/switch-field/switch-field.module.css @@ -34,7 +34,7 @@ height: var(--tmp-switch-height); min-height: auto; border-radius: calc(var(--tmp-switch-height) / 2); - background-color: var(--reactist-switch-background); + background-color: var(--product-library-selectable-primary-unselected-fill); cursor: pointer; position: relative; } @@ -55,12 +55,12 @@ width: var(--tmp-handle-size); height: var(--tmp-handle-size); border-radius: 50%; - background: var(--reactist-switch-toggle); + background: var(--product-library-selectable-primary-on-selected-fill); transition: left 0.28s cubic-bezier(0.4, 0, 0.2, 1); } .checked .toggle { - background-color: var(--reactist-switch-checked); + background-color: var(--product-library-actionable-primary-idle-fill); } .checked .toggle .handle { @@ -69,7 +69,7 @@ .container.keyFocused .toggle:after { border-radius: calc(var(--tmp-switch-height) + 8px / 2); - border: 2px solid var(--reactist-actionable-primary-idle-fill); + border: 2px solid var(--product-library-actionable-primary-idle-fill); bottom: -4px; content: ''; left: -4px; diff --git a/src/text-area/text-area.module.css b/src/text-area/text-area.module.css index 395b4679..8b80e578 100644 --- a/src/text-area/text-area.module.css +++ b/src/text-area/text-area.module.css @@ -30,8 +30,8 @@ See https://css-tricks.com/the-cleanest-trick-for-autogrowing-textareas/ } .textAreaContainer textarea[readonly] { - background-color: var(--reactist-field-readonly-background); - color: var(--reactist-content-primary); + background-color: var(--product-library-background-base-tertiary); + color: var(--product-library-display-primary-idle-tint); } .textAreaContainer:not(.bordered) .innerContainer::after, @@ -47,23 +47,23 @@ See https://css-tricks.com/the-cleanest-trick-for-autogrowing-textareas/ .textAreaContainer:not(.bordered) .innerContainer::after, .textAreaContainer:not(.bordered) textarea, .textAreaContainer.bordered { - border: 1px solid var(--reactist-inputs-idle); + border: 1px solid var(--product-library-border-idle-tint); } .textAreaContainer:not(.bordered) textarea:hover, .textAreaContainer.bordered:hover { - border-color: var(--reactist-inputs-hover); + border-color: var(--product-library-border-hover-tint); } .textAreaContainer:not(.bordered) textarea:focus, .textAreaContainer.bordered:focus-within { - border-color: var(--reactist-inputs-focus); + border-color: var(--product-library-border-focus-tint); } .textAreaContainer.error:not(.bordered) .innerContainer::after, .textAreaContainer.error:not(.bordered) textarea, .textAreaContainer.bordered.error { - border-color: var(--reactist-inputs-alert) !important; + border-color: var(--product-library-info-attention-primary-idle-tint) !important; } .innerContainer { diff --git a/src/text-field/text-field.module.css b/src/text-field/text-field.module.css index be6201c3..fd812946 100644 --- a/src/text-field/text-field.module.css +++ b/src/text-field/text-field.module.css @@ -4,19 +4,19 @@ } .inputWrapper.readOnly { - background-color: var(--reactist-field-readonly-background); + background-color: var(--product-library-background-base-tertiary); } .inputWrapper.readOnly input { - background-color: var(--reactist-field-readonly-background); - color: var(--reactist-content-primary); + background-color: var(--product-library-background-base-tertiary); + color: var(--product-library-display-primary-idle-tint); } .inputWrapper:not(.bordered) { --reactist-input-wrapper-height: 32px; border-radius: var(--reactist-border-radius-small); - border: 1px solid var(--reactist-inputs-idle); + border: 1px solid var(--product-library-border-idle-tint); overflow: clip; } @@ -30,19 +30,19 @@ } .inputWrapper:not(.bordered):hover { - border-color: var(--reactist-inputs-hover); + border-color: var(--product-library-border-hover-tint); } .inputWrapper:not(.bordered):focus-within { - border-color: var(--reactist-inputs-focus); + border-color: var(--product-library-border-focus-tint); } .inputWrapper:not(.bordered).error { - border-color: var(--reactist-inputs-alert) !important; + border-color: var(--product-library-info-attention-primary-idle-tint) !important; } .inputWrapper input { - color: var(--reactist-content-primary); + color: var(--product-library-display-primary-idle-tint); flex: 1; outline: none; /* we take care of the focus state above */ box-sizing: border-box; diff --git a/src/text/text.module.css b/src/text/text.module.css index d78d3aab..0dda4def 100644 --- a/src/text/text.module.css +++ b/src/text/text.module.css @@ -2,7 +2,7 @@ font-family: var(--reactist-font-family); font-size: var(--reactist-font-size-body); font-weight: var(--reactist-font-weight-regular); - color: var(--reactist-content-primary); + color: var(--product-library-display-primary-idle-tint); } .size-caption { @@ -23,10 +23,10 @@ } .tone-secondary { - color: var(--reactist-content-secondary); + color: var(--product-library-display-secondary-idle-tint); } .tone-danger { - color: var(--reactist-content-danger); + color: var(--product-library-actionable-destructive-idle-tint); } .tone-positive { color: var(--reactist-content-positive); diff --git a/src/toast/toast.module.css b/src/toast/toast.module.css index fc4380d5..651ba6e2 100644 --- a/src/toast/toast.module.css +++ b/src/toast/toast.module.css @@ -11,7 +11,7 @@ } .slot { - color: var(--reactist-content-primary); + color: var(--product-library-display-primary-idle-tint); } @media (max-width: 500px) { diff --git a/stories/components/color.stories.tsx b/stories/components/color.stories.tsx index 76433640..5ca88c88 100644 --- a/stories/components/color.stories.tsx +++ b/stories/components/color.stories.tsx @@ -6,29 +6,24 @@ import { Box } from '../../src/box' import { Column, Columns } from '../../src/columns' import { Heading } from '../../src/heading' import { Stack } from '../../src/stack' +import { Text } from '../../src/text' export default { title: 'Design tokens/Colors', } -const frameworkFillColors = [ - '--reactist-framework-fill-background', +/** + * The `--reactist-*` colour tokens that still carry a Reactist decision. Everything else Reactist + * used to alias now reads `--product-library-*` directly at the callsite, so the product library + * is the place to look for the rest of the palette. + */ +const retainedColors = [ + '--reactist-bg-brand', '--reactist-framework-fill-crest', - '--reactist-framework-fill-selected', - '--reactist-framework-fill-summit', -] - -const frameworkBorderColors = [ - '--reactist-divider-primary', - '--reactist-divider-secondary', - '--reactist-divider-tertiary', -] - -const contentColors = [ - '--reactist-content-primary', - '--reactist-content-secondary', - '--reactist-content-tertiary', - '--reactist-toast-content-primary', + '--reactist-content-positive', + '--reactist-toast-content-secondary', + '--reactist-scrollbar-thumb-idle', + '--reactist-actionable-secondary-destructive-hover-fill', ] function Swatch({ color }: { color: string }) { @@ -48,31 +43,25 @@ export function Colors() { return ( - Framework + Retained Reactist colours - Framework-Fill - - {frameworkFillColors.map((color) => ( - - ))} - + + These are the only colour custom properties Reactist still defines itself, because + they have no product-library equivalent. Every other colour resolves to a{' '} + --product-library-* token at the point of use. + - Framework-Border - {frameworkBorderColors.map((color) => ( + {retainedColors.map((color) => ( ))} - - Content - - - {contentColors.map((color) => ( - - ))} - + + --reactist-toast-box-shadow is also retained, but it is a shadow rather + than a colour, so it is not shown as a swatch. + ) } diff --git a/stories/components/styles/color-story.css b/stories/components/styles/color-story.css index 8dc29ece..f1ddac8b 100644 --- a/stories/components/styles/color-story.css +++ b/stories/components/styles/color-story.css @@ -1,13 +1,13 @@ .color_swatch { width: 32px; height: 32px; - border: 1px solid var(--reactist-divider-secondary); + border: 1px solid var(--product-library-divider-secondary); border-radius: var(--reactist-border-radius-small); } .color_swatch__css_variable { padding: 4px; border-radius: var(--reactist-border-radius-small); - border: 1px solid var(--reactist-divider-secondary); - background: var(--reactist-framework-fill-background); + border: 1px solid var(--product-library-divider-secondary); + background: var(--product-library-background-base-secondary); } From f1260c929a6066a700e44bc4598b7bf661c36e41 Mon Sep 17 00:00:00 2001 From: Frankie Yan Date: Tue, 28 Jul 2026 14:02:44 -0700 Subject: [PATCH 06/12] refactor: re-point local token overrides at product-library tokens --- src/badge/badge.stories.jsx | 2 +- src/box/box.module.css | 18 +++---- src/button/button.stories.jsx | 60 ++++++++++++------------ src/button/icon-button.stories.jsx | 60 ++++++++++++------------ src/menu/menu.module.css | 4 +- src/prose/prose.stories.tsx | 9 ++-- src/switch-field/switch-field.mdx | 12 ----- src/switch-field/switch-field.module.css | 6 --- 8 files changed, 78 insertions(+), 93 deletions(-) diff --git a/src/badge/badge.stories.jsx b/src/badge/badge.stories.jsx index 81363135..3b006b32 100644 --- a/src/badge/badge.stories.jsx +++ b/src/badge/badge.stories.jsx @@ -66,7 +66,7 @@ function DarkModeTemplate() { padding="xlarge" style={{ backgroundColor: '#202020', - '--reactist-content-primary': 'rgba(255, 255, 255, 0.88)', + '--product-library-display-primary-idle-tint': 'rgba(255, 255, 255, 0.88)', // tone="info" '--reactist-badge-info-tint': '#B3B3B3', '--reactist-badge-info-fill': '#363636', diff --git a/src/box/box.module.css b/src/box/box.module.css index 9adbb7c0..c877e420 100644 --- a/src/box/box.module.css +++ b/src/box/box.module.css @@ -355,26 +355,28 @@ pre.box { .bg-toast { background-color: var(--product-library-background-raised-quaternary); color: var(--product-library-display-primary-idle-tint); - --reactist-content-primary: var(--product-library-display-primary-on-dark-tint); - --reactist-content-secondary: var(--reactist-toast-content-secondary); + --product-library-display-primary-idle-tint: var( + --product-library-display-primary-on-dark-tint + ); + --product-library-display-secondary-idle-tint: var(--reactist-toast-content-secondary); --reactist-text-link-idle-tint: var(--product-library-display-primary-idle-tint); --reactist-text-link-idle-decoration: var(--reactist-text-link-hover-decoration); - --reactist-actionable-tertiary-idle-tint: var( + --product-library-actionable-tertiary-idle-tint: var( --product-library-actionable-tertiary-on-dark-idle-tint ); - --reactist-actionable-tertiary-hover-tint: var( + --product-library-actionable-tertiary-on-hover-tint: var( --product-library-actionable-tertiary-on-dark-idle-tint ); - --reactist-actionable-tertiary-hover-fill: var( + --product-library-actionable-tertiary-hover-fill: var( --product-library-actionable-tertiary-on-dark-hover-fill ); - --reactist-actionable-quaternary-idle-tint: var( + --product-library-actionable-quaternary-idle-tint: var( --product-library-actionable-quaternary-on-dark-idle-tint ); - --reactist-actionable-quaternary-hover-tint: var( + --product-library-actionable-quaternary-on-hover-tint: var( --product-library-actionable-quaternary-on-dark-idle-tint ); - --reactist-actionable-quaternary-hover-fill: var( + --product-library-actionable-quaternary-hover-fill: var( --product-library-actionable-tertiary-on-dark-hover-fill ); } diff --git a/src/button/button.stories.jsx b/src/button/button.stories.jsx index a8665e48..926d5c69 100644 --- a/src/button/button.stories.jsx +++ b/src/button/button.stories.jsx @@ -139,42 +139,42 @@ function DarkModeTemplate(props) { padding="xlarge" style={{ backgroundColor: 'rgb(31, 31, 31)', - '--reactist-content-primary': 'rgba(255, 255, 255, 0.88)', + '--product-library-display-primary-idle-tint': 'rgba(255, 255, 255, 0.88)', // variant="primary" - '--reactist-actionable-primary-idle-tint': '#eceeee', - '--reactist-actionable-primary-idle-fill': '#008099', - '--reactist-actionable-primary-hover-tint': '#eceeee', - '--reactist-actionable-primary-hover-fill': '#1f8fa5', - '--reactist-actionable-primary-disabled-tint': '#767777', - '--reactist-actionable-primary-disabled-fill': '#00404c', + '--product-library-actionable-primary-on-idle-tint': '#eceeee', + '--product-library-actionable-primary-idle-fill': '#008099', + '--product-library-actionable-primary-on-hover-tint': '#eceeee', + '--product-library-actionable-primary-hover-fill': '#1f8fa5', + '--product-library-actionable-primary-on-disabled-tint': '#767777', + '--product-library-actionable-primary-disabled-fill': '#00404c', // variant="secondary" - '--reactist-actionable-secondary-idle-tint': '#eceeee', - '--reactist-actionable-secondary-idle-fill': '#283233', - '--reactist-actionable-secondary-hover-tint': '#eceeee', - '--reactist-actionable-secondary-hover-fill': '#31393b', - '--reactist-actionable-secondary-disabled-tint': '#767777', - '--reactist-actionable-secondary-disabled-fill': '#283233', + '--product-library-actionable-secondary-on-idle-tint': '#eceeee', + '--product-library-actionable-secondary-idle-fill': '#283233', + '--product-library-actionable-secondary-on-hover-tint': '#eceeee', + '--product-library-actionable-secondary-hover-fill': '#31393b', + '--product-library-actionable-secondary-on-disabled-tint': '#767777', + '--product-library-actionable-secondary-disabled-fill': '#283233', // variant="tertiary" - '--reactist-actionable-tertiary-idle-tint': '#22a5bf', - '--reactist-actionable-tertiary-hover-tint': '#22a5bf', - '--reactist-actionable-tertiary-hover-fill': '#283233', - '--reactist-actionable-tertiary-disabled-tint': '#11525f', + '--product-library-actionable-tertiary-idle-tint': '#22a5bf', + '--product-library-actionable-tertiary-on-hover-tint': '#22a5bf', + '--product-library-actionable-tertiary-hover-fill': '#283233', + '--product-library-actionable-tertiary-disabled-tint': '#11525f', // variant="quaternary" - '--reactist-actionable-quaternary-idle-tint': '#8fa0a3', - '--reactist-actionable-quaternary-hover-tint': '#eceeee', - '--reactist-actionable-quaternary-hover-fill': '#283233', - '--reactist-actionable-quaternary-disabled-tint': '#444d4f', + '--product-library-actionable-quaternary-idle-tint': '#8fa0a3', + '--product-library-actionable-quaternary-on-hover-tint': '#eceeee', + '--product-library-actionable-quaternary-hover-fill': '#283233', + '--product-library-actionable-quaternary-disabled-tint': '#444d4f', // colour for the desctructive tone (used in certain ways by all variants) - '--reactist-actionable-primary-destructive-idle-tint': '#fff', - '--reactist-actionable-primary-destructive-idle-fill': '#d26160', - '--reactist-actionable-primary-destructive-hover-tint': '#fff', - '--reactist-actionable-primary-destructive-hover-fill': '#e98786', - '--reactist-actionable-primary-destructive-disabled-tint': '#767777', - '--reactist-actionable-primary-destructive-disabled-fill': '#7f2c24', + '--product-library-actionable-destructive-on-idle-tint': '#fff', + '--product-library-actionable-destructive-idle-fill': '#d26160', + '--product-library-actionable-destructive-on-hover-tint': '#fff', + '--product-library-actionable-destructive-hover-fill': '#e98786', + '--product-library-actionable-destructive-on-disabled-tint': '#767777', + '--product-library-actionable-destructive-disabled-fill': '#7f2c24', /* secondary destructive button colors (no fill, as these are transparent and bordered) */ - '--reactist-actionable-secondary-destructive-idle-tint': '#f68584', - '--reactist-actionable-secondary-destructive-hover-tint': '#eFa9a9', - '--reactist-actionable-secondary-destructive-disabled-tint': '#8a5853', + '--product-library-actionable-destructive-idle-tint': '#f68584', + '--product-library-actionable-destructive-hover-tint': '#eFa9a9', + '--product-library-actionable-destructive-disabled-tint': '#8a5853', }} > diff --git a/src/button/icon-button.stories.jsx b/src/button/icon-button.stories.jsx index 505db3fc..dc5e3243 100644 --- a/src/button/icon-button.stories.jsx +++ b/src/button/icon-button.stories.jsx @@ -57,42 +57,42 @@ function DarkModeTemplate(props) { padding="xlarge" style={{ backgroundColor: 'rgb(31, 31, 31)', - '--reactist-content-primary': 'rgba(255, 255, 255, 0.88)', + '--product-library-display-primary-idle-tint': 'rgba(255, 255, 255, 0.88)', // variant="primary" - '--reactist-actionable-primary-idle-tint': '#eceeee', - '--reactist-actionable-primary-idle-fill': '#008099', - '--reactist-actionable-primary-hover-tint': '#eceeee', - '--reactist-actionable-primary-hover-fill': '#1f8fa5', - '--reactist-actionable-primary-disabled-tint': '#767777', - '--reactist-actionable-primary-disabled-fill': '#00404c', + '--product-library-actionable-primary-on-idle-tint': '#eceeee', + '--product-library-actionable-primary-idle-fill': '#008099', + '--product-library-actionable-primary-on-hover-tint': '#eceeee', + '--product-library-actionable-primary-hover-fill': '#1f8fa5', + '--product-library-actionable-primary-on-disabled-tint': '#767777', + '--product-library-actionable-primary-disabled-fill': '#00404c', // variant="secondary" - '--reactist-actionable-secondary-idle-tint': '#eceeee', - '--reactist-actionable-secondary-idle-fill': '#283233', - '--reactist-actionable-secondary-hover-tint': '#eceeee', - '--reactist-actionable-secondary-hover-fill': '#31393b', - '--reactist-actionable-secondary-disabled-tint': '#767777', - '--reactist-actionable-secondary-disabled-fill': '#283233', + '--product-library-actionable-secondary-on-idle-tint': '#eceeee', + '--product-library-actionable-secondary-idle-fill': '#283233', + '--product-library-actionable-secondary-on-hover-tint': '#eceeee', + '--product-library-actionable-secondary-hover-fill': '#31393b', + '--product-library-actionable-secondary-on-disabled-tint': '#767777', + '--product-library-actionable-secondary-disabled-fill': '#283233', // variant="tertiary" - '--reactist-actionable-tertiary-idle-tint': '#22a5bf', - '--reactist-actionable-tertiary-hover-tint': '#22a5bf', - '--reactist-actionable-tertiary-hover-fill': '#283233', - '--reactist-actionable-tertiary-disabled-tint': '#11525f', + '--product-library-actionable-tertiary-idle-tint': '#22a5bf', + '--product-library-actionable-tertiary-on-hover-tint': '#22a5bf', + '--product-library-actionable-tertiary-hover-fill': '#283233', + '--product-library-actionable-tertiary-disabled-tint': '#11525f', // variant="quaternary" - '--reactist-actionable-quaternary-idle-tint': '#8fa0a3', - '--reactist-actionable-quaternary-hover-tint': '#eceeee', - '--reactist-actionable-quaternary-hover-fill': '#283233', - '--reactist-actionable-quaternary-disabled-tint': '#444d4f', + '--product-library-actionable-quaternary-idle-tint': '#8fa0a3', + '--product-library-actionable-quaternary-on-hover-tint': '#eceeee', + '--product-library-actionable-quaternary-hover-fill': '#283233', + '--product-library-actionable-quaternary-disabled-tint': '#444d4f', // colour for the desctructive tone (used in certain ways by all variants) - '--reactist-actionable-primary-destructive-idle-tint': '#fff', - '--reactist-actionable-primary-destructive-idle-fill': '#d26160', - '--reactist-actionable-primary-destructive-hover-tint': '#fff', - '--reactist-actionable-primary-destructive-hover-fill': '#e98786', - '--reactist-actionable-primary-destructive-disabled-tint': '#767777', - '--reactist-actionable-primary-destructive-disabled-fill': '#7f2c24', + '--product-library-actionable-destructive-on-idle-tint': '#fff', + '--product-library-actionable-destructive-idle-fill': '#d26160', + '--product-library-actionable-destructive-on-hover-tint': '#fff', + '--product-library-actionable-destructive-hover-fill': '#e98786', + '--product-library-actionable-destructive-on-disabled-tint': '#767777', + '--product-library-actionable-destructive-disabled-fill': '#7f2c24', /* secondary destructive button colors (no fill, as these are transparent and bordered) */ - '--reactist-actionable-secondary-destructive-idle-tint': '#f68584', - '--reactist-actionable-secondary-destructive-hover-tint': '#eFa9a9', - '--reactist-actionable-secondary-destructive-disabled-tint': '#8a5853', + '--product-library-actionable-destructive-idle-tint': '#f68584', + '--product-library-actionable-destructive-hover-tint': '#eFa9a9', + '--product-library-actionable-destructive-disabled-tint': '#8a5853', }} > diff --git a/src/menu/menu.module.css b/src/menu/menu.module.css index 3189f402..7b309263 100644 --- a/src/menu/menu.module.css +++ b/src/menu/menu.module.css @@ -69,7 +69,7 @@ --reactist-text-link-idle-tint, var(--product-library-actionable-tertiary-idle-tint) ); - --reactist-content-primary: var( + --product-library-display-primary-idle-tint: var( --reactist-text-link-idle-tint, var(--product-library-actionable-tertiary-idle-tint) ); @@ -81,7 +81,7 @@ --reactist-text-link-hover-tint, var(--product-library-actionable-tertiary-on-hover-tint) ); - --reactist-content-primary: var( + --product-library-display-primary-idle-tint: var( --reactist-text-link-hover-tint, var(--product-library-actionable-tertiary-on-hover-tint) ); diff --git a/src/prose/prose.stories.tsx b/src/prose/prose.stories.tsx index 3b8bc19b..53e15a0e 100644 --- a/src/prose/prose.stories.tsx +++ b/src/prose/prose.stories.tsx @@ -31,16 +31,17 @@ export function ProsePlaygroundStory({ darkModeTypography, dangerouslySetInnerHT ? { backgroundColor: '#202020', // @ts-expect-error - '--reactist-content-primary': 'rgba(255, 255, 255, 0.88)', + '--product-library-display-primary-idle-tint': + 'rgba(255, 255, 255, 0.88)', '--reactist-prose-code-tint': 'rgba(255, 255, 255, 0.88)', '--reactist-prose-code-fill': 'rgb(40, 40, 40)', '--reactist-prose-code-border': 'var(--product-library-divider-secondary)', '--reactist-prose-quote-tint': '#9db4b9', // divider colors - '--reactist-divider-primary': '#53595b', - '--reactist-divider-secondary': '#424b4c', - '--reactist-divider-tertiary': '#323839', + '--product-library-divider-primary': '#53595b', + '--product-library-divider-secondary': '#424b4c', + '--product-library-divider-tertiary': '#323839', // link colors '--reactist-prose-link-idle-tint': '#22a5bf', '--reactist-prose-link-idle-underline': '#53595b', diff --git a/src/switch-field/switch-field.mdx b/src/switch-field/switch-field.mdx index b5a535cc..9b1e072c 100644 --- a/src/switch-field/switch-field.mdx +++ b/src/switch-field/switch-field.mdx @@ -18,18 +18,6 @@ A checkbox with a built-in label element that visually looks like a toggle switc -## Colors - -The following CSS custom properties are available to customize the SwitchField's appearance. The values appearing below are the default values. - -```css -:root { - --reactist-switch-background: rgb(214, 214, 214); - --reactist-switch-checked: rgb(5, 133, 39); - --reactist-switch-toggle: rgb(255, 255, 255); -} -``` - ## Accessibility diff --git a/src/switch-field/switch-field.module.css b/src/switch-field/switch-field.module.css index dacdd984..09c3ba01 100644 --- a/src/switch-field/switch-field.module.css +++ b/src/switch-field/switch-field.module.css @@ -1,9 +1,3 @@ -:root { - --reactist-switch-background: var(--product-library-selectable-primary-unselected-fill); - --reactist-switch-checked: var(--product-library-actionable-primary-idle-fill); - --reactist-switch-toggle: var(--product-library-selectable-primary-on-selected-fill); -} - .container, .container * { font-family: var(--reactist-font-family); From 25f0cfae645f7f6ebf225057e10ae5b9d87a66b4 Mon Sep 17 00:00:00 2001 From: Frankie Yan Date: Tue, 28 Jul 2026 14:03:08 -0700 Subject: [PATCH 07/12] feat!: remove the aliased --reactist-* colour custom properties --- src/styles/design-tokens.css | 173 +++-------------------------------- 1 file changed, 14 insertions(+), 159 deletions(-) diff --git a/src/styles/design-tokens.css b/src/styles/design-tokens.css index 9e59202f..baabf11a 100644 --- a/src/styles/design-tokens.css +++ b/src/styles/design-tokens.css @@ -51,167 +51,25 @@ --reactist-font-weight-medium: 600; --reactist-font-weight-strong: 700; - /* standard divider colors */ - --reactist-divider-primary: var(--product-library-divider-primary); - --reactist-divider-secondary: var(--product-library-divider-secondary); - --reactist-divider-tertiary: var(--product-library-divider-tertiary); - - /* input border colors */ - --reactist-inputs-hover: var(--product-library-border-hover-tint); - --reactist-inputs-focus: var(--product-library-border-focus-tint); - --reactist-inputs-idle: var(--product-library-border-idle-tint); - --reactist-inputs-alert: var(--product-library-info-attention-primary-idle-tint); - /* border-radius */ --reactist-border-radius-small: 5px; --reactist-border-radius-large: 10px; - /* background color */ - --reactist-bg-default: var(--product-library-background-base-primary); - --reactist-bg-brand: rgb(36, 111, 224); /* no product-library source */ - --reactist-bg-aside: var(--product-library-background-base-secondary); - --reactist-bg-highlight: var(--product-library-actionable-quaternary-hover-fill); - --reactist-bg-selected: var(--product-library-selectable-secondary-selected-fill); - --reactist-bg-toast: var(--product-library-background-raised-quaternary); - - /* colors */ - --reactist-framework-fill-background: var(--product-library-background-base-secondary); - --reactist-framework-fill-crest: rgb(230, 230, 230); /* no product-library source */ - --reactist-framework-fill-selected: rgb(236, 236, 236); /* no product-library source */ - --reactist-framework-fill-summit: var(--product-library-selectable-primary-unselected-fill); - - --reactist-content-primary: var(--product-library-display-primary-idle-tint); - --reactist-content-secondary: var(--product-library-display-secondary-idle-tint); - --reactist-content-tertiary: var(--product-library-display-tertiary-idle-tint); - --reactist-toast-content-primary: var(--product-library-display-primary-on-dark-tint); - --reactist-toast-content-secondary: hsla(0, 0%, 100%, 0.56); /* no product-library source */ - --reactist-content-positive: rgb(5, 133, 39); /* no product-library source */ - --reactist-content-danger: var(--product-library-actionable-destructive-idle-tint); - - /* component-specific */ - - /* actionable colors */ - --reactist-actionable-primary-idle-tint: var(--product-library-actionable-primary-on-idle-tint); - --reactist-actionable-primary-idle-fill: var(--product-library-actionable-primary-idle-fill); - --reactist-actionable-primary-hover-tint: var( - --product-library-actionable-primary-on-hover-tint - ); - --reactist-actionable-primary-hover-fill: var(--product-library-actionable-primary-hover-fill); - --reactist-actionable-primary-disabled-tint: var( - --product-library-actionable-primary-on-disabled-tint - ); - --reactist-actionable-primary-disabled-fill: var( - --product-library-actionable-primary-disabled-fill - ); - - --reactist-actionable-secondary-idle-tint: var( - --product-library-actionable-secondary-on-idle-tint - ); - --reactist-actionable-secondary-idle-fill: var( - --product-library-actionable-secondary-idle-fill - ); - --reactist-actionable-secondary-hover-tint: var( - --product-library-actionable-secondary-on-hover-tint - ); - --reactist-actionable-secondary-hover-fill: var( - --product-library-actionable-secondary-hover-fill - ); - --reactist-actionable-secondary-disabled-tint: var( - --product-library-actionable-secondary-on-disabled-tint - ); - --reactist-actionable-secondary-disabled-fill: var( - --product-library-actionable-secondary-disabled-fill - ); - - --reactist-actionable-tertiary-idle-tint: var(--product-library-actionable-tertiary-idle-tint); - --reactist-actionable-tertiary-hover-tint: var( - --product-library-actionable-tertiary-on-hover-tint - ); - --reactist-actionable-tertiary-hover-fill: var( - --product-library-actionable-tertiary-hover-fill - ); - --reactist-actionable-tertiary-disabled-tint: var( - --product-library-actionable-tertiary-disabled-tint - ); - - --reactist-actionable-quaternary-idle-tint: var( - --product-library-actionable-quaternary-idle-tint - ); - --reactist-actionable-quaternary-hover-tint: var( - --product-library-actionable-quaternary-on-hover-tint - ); - --reactist-actionable-quaternary-hover-fill: var( - --product-library-actionable-quaternary-hover-fill - ); - --reactist-actionable-quaternary-disabled-tint: var( - --product-library-actionable-quaternary-disabled-tint - ); - - --reactist-actionable-primary-destructive-idle-tint: var( - --product-library-actionable-destructive-on-idle-tint - ); - --reactist-actionable-primary-destructive-idle-fill: var( - --product-library-actionable-destructive-idle-fill - ); - --reactist-actionable-primary-destructive-hover-tint: var( - --product-library-actionable-destructive-on-hover-tint - ); - --reactist-actionable-primary-destructive-hover-fill: var( - --product-library-actionable-destructive-hover-fill - ); - --reactist-actionable-primary-destructive-disabled-tint: var( - --product-library-actionable-destructive-on-disabled-tint - ); - --reactist-actionable-primary-destructive-disabled-fill: var( - --product-library-actionable-destructive-disabled-fill - ); - - --reactist-actionable-secondary-destructive-idle-tint: var( - --product-library-actionable-destructive-idle-tint - ); - --reactist-actionable-secondary-destructive-hover-tint: var( - --product-library-actionable-destructive-hover-tint - ); + /* + * colors + * + * Reactist's colours come from `@doist/product-libraries-tokens` and are referenced as + * `var(--product-library-*)` directly wherever they are used, so there is no aliasing layer + * here. The tokens below are the exceptions: they have no product-library equivalent, so + * Reactist still defines them itself. They do not adapt to dark or accent themes -- an app + * that needs them to must override them. + */ + --reactist-bg-brand: rgb(36, 111, 224); + --reactist-framework-fill-crest: rgb(230, 230, 230); + --reactist-content-positive: rgb(5, 133, 39); + --reactist-toast-content-secondary: hsla(0, 0%, 100%, 0.56); + --reactist-scrollbar-thumb-idle: rgba(0, 0, 0, 0.2); --reactist-actionable-secondary-destructive-hover-fill: transparent; - --reactist-actionable-secondary-destructive-disabled-tint: var( - --product-library-actionable-destructive-disabled-tint - ); - - /* alerts */ - --reactist-alert-tone-info-icon: var(--product-library-info-neutral-primary-idle-fill); - --reactist-alert-tone-info-border: var(--product-library-divider-primary); - --reactist-alert-tone-info-background: var(--product-library-background-base-secondary); - - --reactist-alert-tone-positive-icon: var(--product-library-info-positive-primary-idle-fill); - --reactist-alert-tone-positive-border: var(--product-library-divider-primary); - --reactist-alert-tone-positive-background: var(--product-library-background-base-secondary); - - --reactist-alert-tone-caution-icon: var(--product-library-info-warning-primary-on-idle-fill); - --reactist-alert-tone-caution-border: var(--product-library-divider-primary); - --reactist-alert-tone-caution-background: var(--product-library-background-base-secondary); - - --reactist-alert-tone-critical-icon: var(--product-library-info-attention-primary-idle-fill); - --reactist-alert-tone-critical-border: var(--product-library-divider-primary); - --reactist-alert-tone-critical-background: var(--product-library-background-base-secondary); - - /* fields */ - --reactist-field-readonly-background: var(--product-library-background-base-tertiary); - - /* switches and checkboxes */ - --reactist-switch-background: var(--product-library-selectable-primary-unselected-fill); - --reactist-switch-checked: var(--product-library-actionable-primary-idle-fill); - --reactist-switch-toggle: var(--product-library-selectable-primary-on-selected-fill); - - /* toasts */ - --reactist-toast-actionable-primary-tint: var( - --product-library-actionable-tertiary-on-dark-idle-tint - ); - --reactist-toast-actionable-secondary-tint: var( - --product-library-actionable-quaternary-on-dark-idle-tint - ); - --reactist-toast-actionable-hover-fill: var( - --product-library-actionable-tertiary-on-dark-hover-fill - ); --reactist-toast-box-shadow: rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px; /* stacking orders */ @@ -219,7 +77,4 @@ --reactist-stacking-order-menu: 1; --reactist-stacking-order-toast: 400; --reactist-stacking-order-tooltip: 1000; - - /* scrollbar colors */ - --reactist-scrollbar-thumb-idle: rgba(0, 0, 0, 0.2); /* no product-library source */ } From b8fd1b67476b04ce4aff8b1cd35e199612e7b4d2 Mon Sep 17 00:00:00 2001 From: Frankie Yan Date: Tue, 28 Jul 2026 14:37:16 -0700 Subject: [PATCH 08/12] feat!: source the last six colour tokens from the product library --- src/avatar/avatar.module.css | 2 +- src/box/box.module.css | 8 ++- src/button/button.module.css | 2 +- .../progress-bar/progress-bar.module.css | 4 +- src/styles/design-tokens.css | 14 +--- src/text/text.module.css | 2 +- stories/components/color.stories.tsx | 67 ------------------- stories/components/styles/color-story.css | 13 ---- 8 files changed, 11 insertions(+), 101 deletions(-) delete mode 100644 stories/components/color.stories.tsx delete mode 100644 stories/components/styles/color-story.css diff --git a/src/avatar/avatar.module.css b/src/avatar/avatar.module.css index cfe69dcd..70d9099b 100644 --- a/src/avatar/avatar.module.css +++ b/src/avatar/avatar.module.css @@ -1,7 +1,7 @@ :root { --reactist-avatar-initials-color: var(--product-library-actionable-primary-on-idle-tint); --reactist-avatar-border-tint: #0000001a; - --reactist-avatar-empty-fill: var(--reactist-framework-fill-crest); + --reactist-avatar-empty-fill: var(--product-library-background-base-tertiary); --reactist-avatar-meta-0-fill: #b8255f; --reactist-avatar-meta-0-on-idle-tint: var(--reactist-avatar-initials-color); diff --git a/src/box/box.module.css b/src/box/box.module.css index c877e420..376e1c78 100644 --- a/src/box/box.module.css +++ b/src/box/box.module.css @@ -358,7 +358,9 @@ pre.box { --product-library-display-primary-idle-tint: var( --product-library-display-primary-on-dark-tint ); - --product-library-display-secondary-idle-tint: var(--reactist-toast-content-secondary); + --product-library-display-secondary-idle-tint: var( + --product-library-display-secondary-on-dark-tint + ); --reactist-text-link-idle-tint: var(--product-library-display-primary-idle-tint); --reactist-text-link-idle-decoration: var(--reactist-text-link-hover-decoration); --product-library-actionable-tertiary-idle-tint: var( @@ -468,7 +470,7 @@ pre.box { } .overlayScroll:hover::-webkit-scrollbar-thumb { - background-color: var(--reactist-scrollbar-thumb-idle); + background-color: var(--product-library-display-quaternary-idle-tint); } /* Firefox */ @@ -478,5 +480,5 @@ pre.box { } .overlayScroll:hover { - scrollbar-color: var(--reactist-scrollbar-thumb-idle) transparent; + scrollbar-color: var(--product-library-display-quaternary-idle-tint) transparent; } diff --git a/src/button/button.module.css b/src/button/button.module.css index 3e03d2e4..37f811c8 100644 --- a/src/button/button.module.css +++ b/src/button/button.module.css @@ -189,7 +189,7 @@ --reactist-btn-idle-tint: var(--product-library-actionable-destructive-idle-tint); --reactist-btn-idle-fill: transparent; --reactist-btn-hover-tint: var(--product-library-actionable-destructive-hover-tint); - --reactist-btn-hover-fill: var(--reactist-actionable-secondary-destructive-hover-fill); + --reactist-btn-hover-fill: var(--product-library-info-attention-secondary-idle-fill); --reactist-btn-disabled-tint: var(--product-library-actionable-destructive-disabled-tint); --reactist-btn-disabled-fill: transparent; } diff --git a/src/components/progress-bar/progress-bar.module.css b/src/components/progress-bar/progress-bar.module.css index 2d3567a0..dd16b749 100644 --- a/src/components/progress-bar/progress-bar.module.css +++ b/src/components/progress-bar/progress-bar.module.css @@ -2,8 +2,8 @@ --reactist-progressbar-height: var(--reactist-spacing-xsmall); --reactist-progressbar-radius-outer: var(--reactist-progressbar-height); --reactist-progressbar-radius-inner: var(--reactist-progressbar-height); - --reactist-progressbar-track: var(--reactist-framework-fill-crest); - --reactist-progressbar-fill: var(--reactist-bg-brand); + --reactist-progressbar-track: var(--product-library-background-base-tertiary); + --reactist-progressbar-fill: var(--product-library-display-accent-primary-fill); --reactist-progressbar-scale-tint: var(--product-library-display-tertiary-idle-tint); --reactist-progressbar-scale-tick-height: 8px; --reactist-progressbar-scale-minor-tick-opacity: 0.15; diff --git a/src/styles/design-tokens.css b/src/styles/design-tokens.css index baabf11a..72041d29 100644 --- a/src/styles/design-tokens.css +++ b/src/styles/design-tokens.css @@ -56,20 +56,8 @@ --reactist-border-radius-large: 10px; /* - * colors - * - * Reactist's colours come from `@doist/product-libraries-tokens` and are referenced as - * `var(--product-library-*)` directly wherever they are used, so there is no aliasing layer - * here. The tokens below are the exceptions: they have no product-library equivalent, so - * Reactist still defines them itself. They do not adapt to dark or accent themes -- an app - * that needs them to must override them. + * elevation */ - --reactist-bg-brand: rgb(36, 111, 224); - --reactist-framework-fill-crest: rgb(230, 230, 230); - --reactist-content-positive: rgb(5, 133, 39); - --reactist-toast-content-secondary: hsla(0, 0%, 100%, 0.56); - --reactist-scrollbar-thumb-idle: rgba(0, 0, 0, 0.2); - --reactist-actionable-secondary-destructive-hover-fill: transparent; --reactist-toast-box-shadow: rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px; /* stacking orders */ diff --git a/src/text/text.module.css b/src/text/text.module.css index 0dda4def..69d340f1 100644 --- a/src/text/text.module.css +++ b/src/text/text.module.css @@ -29,7 +29,7 @@ color: var(--product-library-actionable-destructive-idle-tint); } .tone-positive { - color: var(--reactist-content-positive); + color: var(--product-library-info-positive-primary-idle-tint); } /* truncated text */ diff --git a/stories/components/color.stories.tsx b/stories/components/color.stories.tsx deleted file mode 100644 index 5ca88c88..00000000 --- a/stories/components/color.stories.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import './styles/color-story.css' - -import * as React from 'react' - -import { Box } from '../../src/box' -import { Column, Columns } from '../../src/columns' -import { Heading } from '../../src/heading' -import { Stack } from '../../src/stack' -import { Text } from '../../src/text' - -export default { - title: 'Design tokens/Colors', -} - -/** - * The `--reactist-*` colour tokens that still carry a Reactist decision. Everything else Reactist - * used to alias now reads `--product-library-*` directly at the callsite, so the product library - * is the place to look for the rest of the palette. - */ -const retainedColors = [ - '--reactist-bg-brand', - '--reactist-framework-fill-crest', - '--reactist-content-positive', - '--reactist-toast-content-secondary', - '--reactist-scrollbar-thumb-idle', - '--reactist-actionable-secondary-destructive-hover-fill', -] - -function Swatch({ color }: { color: string }) { - return ( - - - - - - {color} - - - ) -} - -export function Colors() { - return ( - - - Retained Reactist colours - - - - These are the only colour custom properties Reactist still defines itself, because - they have no product-library equivalent. Every other colour resolves to a{' '} - --product-library-* token at the point of use. - - - - {retainedColors.map((color) => ( - - ))} - - - - --reactist-toast-box-shadow is also retained, but it is a shadow rather - than a colour, so it is not shown as a swatch. - - - ) -} diff --git a/stories/components/styles/color-story.css b/stories/components/styles/color-story.css deleted file mode 100644 index f1ddac8b..00000000 --- a/stories/components/styles/color-story.css +++ /dev/null @@ -1,13 +0,0 @@ -.color_swatch { - width: 32px; - height: 32px; - border: 1px solid var(--product-library-divider-secondary); - border-radius: var(--reactist-border-radius-small); -} - -.color_swatch__css_variable { - padding: 4px; - border-radius: var(--reactist-border-radius-small); - border: 1px solid var(--product-library-divider-secondary); - background: var(--product-library-background-base-secondary); -} From 0012c00e51af8d3b716473fdb318d958f6588a2d Mon Sep 17 00:00:00 2001 From: Frankie Yan Date: Tue, 28 Jul 2026 18:10:39 -0700 Subject: [PATCH 09/12] fix: render the dark mode stories with the product library dark theme --- .storybook/dark-theme.tsx | 26 ++++++++++++++++ src/badge/badge.mdx | 4 +-- src/badge/badge.stories.jsx | 27 +++++----------- src/banner/banner.mdx | 4 +-- src/banner/banner.stories.jsx | 16 +++++----- src/button/button.mdx | 3 +- src/button/button.stories.jsx | 50 +++++------------------------- src/button/icon-button.mdx | 3 +- src/button/icon-button.stories.jsx | 50 +++++------------------------- 9 files changed, 62 insertions(+), 121 deletions(-) create mode 100644 .storybook/dark-theme.tsx diff --git a/.storybook/dark-theme.tsx b/.storybook/dark-theme.tsx new file mode 100644 index 00000000..599fba44 --- /dev/null +++ b/.storybook/dark-theme.tsx @@ -0,0 +1,26 @@ +import '@doist/product-libraries-tokens/css/td-dark.css' + +import * as React from 'react' + +const THEME_CLASS = 'theme_dark' + +function DarkTheme({ children }: { children: React.ReactNode }) { + React.useEffect(function applyDarkTheme() { + const root = document.documentElement + root.classList.add(THEME_CLASS) + return () => root.classList.remove(THEME_CLASS) + }, []) + + return <>{children} +} + +/** + * Renders a story under the product library's dark theme. + */ +export function withDarkTheme(Story: React.ComponentType) { + return ( + + + + ) +} diff --git a/src/badge/badge.mdx b/src/badge/badge.mdx index 7b442654..cca3062d 100644 --- a/src/badge/badge.mdx +++ b/src/badge/badge.mdx @@ -57,8 +57,6 @@ The following CSS custom properties are available to customize the badge compone ### Dark mode -Even though Reactist does not yet owns the concept of dark mode, and leaves it for apps to set it -up, here's a demo on how easily you can prepare badges for dark mode by setting CSS custom -properties. +Dark mode colors are applied when the `.theme_dark` class is set on the root element. diff --git a/src/badge/badge.stories.jsx b/src/badge/badge.stories.jsx index 3b006b32..46fdd42b 100644 --- a/src/badge/badge.stories.jsx +++ b/src/badge/badge.stories.jsx @@ -1,5 +1,6 @@ import * as React from 'react' +import { withDarkTheme } from '../../.storybook/dark-theme' import { Box } from '../box' import { Button } from '../button' import { Column, Columns } from '../columns' @@ -62,25 +63,7 @@ function BadgeExamples() { function DarkModeTemplate() { return ( - + ) @@ -188,6 +171,7 @@ export const InsideOtherElements = { export const DarkMode = { render: DarkModeTemplate.bind({}), + decorators: [withDarkTheme], name: 'Dark mode', parameters: { @@ -195,6 +179,11 @@ export const DarkMode = { source: { type: 'dynamic', }, + // Render as an iframe to scope `theme_dark` to the story + story: { + inline: false, + height: '260px', + }, }, }, } diff --git a/src/banner/banner.mdx b/src/banner/banner.mdx index df71ffb4..8f62a341 100644 --- a/src/banner/banner.mdx +++ b/src/banner/banner.mdx @@ -79,8 +79,6 @@ The following CSS custom properties are available to customize the banner compon ### Dark mode -Even though Reactist does not yet owns the concept of dark mode, and leaves it for apps to set it -up, here's a demo on how easily you can prepare banners for dark mode by setting CSS custom -properties. +Dark mode colors are applied when the `.theme_dark` class is set on the root element. diff --git a/src/banner/banner.stories.jsx b/src/banner/banner.stories.jsx index 3883eda6..bb60185a 100644 --- a/src/banner/banner.stories.jsx +++ b/src/banner/banner.stories.jsx @@ -1,5 +1,6 @@ import * as React from 'react' +import { withDarkTheme } from '../../.storybook/dark-theme' import { Box } from '../box' import { Button } from '../button' import { CheckboxField } from '../checkbox-field' @@ -355,14 +356,7 @@ function DarkModeTemplate() { display="flex" flexDirection="column" padding="xlarge" - style={{ - backgroundColor: '#202020', - '--reactist-banner-background-color': '#282828', - '--reactist-banner-border-color': '#3D3D3D', - '--reactist-banner-divider-color': '#3D3D3D', - '--reactist-banner-main-copy-color': '#FFFFFF', - '--reactist-banner-secondary-copy-color': '#B3B3B3', - }} + background="default" gap="large" > } description="This is a neutral message" /> @@ -539,6 +533,7 @@ export const Content = { export const DarkMode = { render: DarkModeTemplate.bind({}), + decorators: [withDarkTheme], name: 'Dark mode', parameters: { @@ -546,6 +541,11 @@ export const DarkMode = { source: { type: 'dynamic', }, + // Render as an iframe to scope `theme_dark` to the story + story: { + inline: false, + height: '760px', + }, }, chromatic: { diff --git a/src/button/button.mdx b/src/button/button.mdx index 1ce23319..d17779b0 100644 --- a/src/button/button.mdx +++ b/src/button/button.mdx @@ -74,8 +74,7 @@ Buttons can be set to take the full width of their container by using the `width ## Dark mode -Even though Reactist does not yet owns the concept of dark mode, and leaves it for apps to set it -up, here's a demo on how easily you can set it up by manipulating color variables only. +Dark mode colors are applied when the `.theme_dark` class is set on the root element. diff --git a/src/button/button.stories.jsx b/src/button/button.stories.jsx index 926d5c69..9597ef6a 100644 --- a/src/button/button.stories.jsx +++ b/src/button/button.stories.jsx @@ -1,6 +1,7 @@ import * as React from 'react' import { useEffect, useState } from 'react' +import { withDarkTheme } from '../../.storybook/dark-theme' import { Box } from '../box' import { Heading } from '../heading' import { Inline } from '../inline' @@ -135,48 +136,7 @@ function PlaygroundTemplate({ label, ...props }) { function DarkModeTemplate(props) { return ( - + ) @@ -834,6 +794,7 @@ export const Playground = { export const DarkMode = { render: DarkModeTemplate.bind({}), + decorators: [withDarkTheme], name: 'Dark mode', parameters: { @@ -841,6 +802,11 @@ export const DarkMode = { source: { type: 'dynamic', }, + // Render as an iframe to scope `theme_dark` to the story + story: { + inline: false, + height: '320px', + }, }, }, diff --git a/src/button/icon-button.mdx b/src/button/icon-button.mdx index 09bcfe0c..0813b0de 100644 --- a/src/button/icon-button.mdx +++ b/src/button/icon-button.mdx @@ -58,8 +58,7 @@ And here's how that look like: ### Dark mode -Even though Reactist does not yet owns the concept of dark mode, and leaves it for apps to set it -up, here's a demo on how easily you can set it up by manipulating color variables only. +Dark mode colors are applied when the `.theme_dark` class is set on the root element. diff --git a/src/button/icon-button.stories.jsx b/src/button/icon-button.stories.jsx index dc5e3243..0e06ceca 100644 --- a/src/button/icon-button.stories.jsx +++ b/src/button/icon-button.stories.jsx @@ -1,6 +1,7 @@ import * as React from 'react' import { useEffect, useState } from 'react' +import { withDarkTheme } from '../../.storybook/dark-theme' import { Box } from '../box' import { IconButton } from '../button' import { Heading } from '../heading' @@ -53,48 +54,7 @@ function PlaygroundTemplate({ label, ...props }) { function DarkModeTemplate(props) { return ( - + ) @@ -524,12 +484,18 @@ export const Playground = { export const DarkMode = { render: DarkModeTemplate.bind({}), + decorators: [withDarkTheme], parameters: { docs: { source: { type: 'dynamic', }, + // Render as an iframe to scope `theme_dark` to the story + story: { + inline: false, + height: '320px', + }, }, }, From 345c3e68268a24b9b9b8431350e2159da073df9e Mon Sep 17 00:00:00 2001 From: Frankie Yan Date: Tue, 28 Jul 2026 18:45:14 -0700 Subject: [PATCH 10/12] refactor: use Divider instead of an inline border in the modal story --- src/modal/modal.stories.tsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/modal/modal.stories.tsx b/src/modal/modal.stories.tsx index 0d339d02..45fab9a5 100644 --- a/src/modal/modal.stories.tsx +++ b/src/modal/modal.stories.tsx @@ -7,6 +7,7 @@ import { Box } from '../box' import { IconButton } from '../button' import { Column, Columns } from '../columns' import ThreeDotsIcon from '../components/icons/ThreeDotsIcon.svg' +import { Divider } from '../divider' import { Heading } from '../heading' import { Inline } from '../inline' import { Menu, MenuButton, MenuItem, MenuList } from '../menu' @@ -250,18 +251,14 @@ export function ModalWithScrollableTabPanels() { - + Sub-tasks Comments Activity + From 97bf066eb754ba559214f1e772fd8619efad8bdf Mon Sep 17 00:00:00 2001 From: Frankie Yan Date: Tue, 28 Jul 2026 19:01:57 -0700 Subject: [PATCH 11/12] docs: drop the component Colors sections listing removed tokens --- src/button/button.mdx | 34 --------------------------- src/button/icon-button.mdx | 34 +-------------------------- src/password-field/password-field.mdx | 11 --------- src/select-field/select-field.mdx | 11 --------- src/text-area/text-area.mdx | 11 --------- src/text-field/text-field.mdx | 11 --------- 6 files changed, 1 insertion(+), 111 deletions(-) diff --git a/src/button/button.mdx b/src/button/button.mdx index d17779b0..f8da6a30 100644 --- a/src/button/button.mdx +++ b/src/button/button.mdx @@ -77,37 +77,3 @@ Buttons can be set to take the full width of their container by using the `width Dark mode colors are applied when the `.theme_dark` class is set on the root element. - -## Colors - -The following CSS custom properties are available to customize the button-like element appearance. - -``` ---reactist-actionable-primary-idle-tint ---reactist-actionable-primary-idle-fill ---reactist-actionable-primary-hover-tint ---reactist-actionable-primary-hover-fill ---reactist-actionable-primary-disabled-tint ---reactist-actionable-primary-disabled-fill - ---reactist-actionable-secondary-idle-tint ---reactist-actionable-secondary-idle-fill ---reactist-actionable-secondary-hover-tint ---reactist-actionable-secondary-hover-fill ---reactist-actionable-secondary-disabled-tint ---reactist-actionable-secondary-disabled-fill - ---reactist-actionable-tertiary-idle-tint ---reactist-actionable-tertiary-idle-fill ---reactist-actionable-tertiary-hover-tint ---reactist-actionable-tertiary-hover-fill ---reactist-actionable-tertiary-disabled-tint ---reactist-actionable-tertiary-disabled-fill - ---reactist-actionable-destructive-idle-tint ---reactist-actionable-destructive-idle-fill ---reactist-actionable-destructive-hover-tint ---reactist-actionable-destructive-hover-fill ---reactist-actionable-destructive-disabled-tint ---reactist-actionable-destructive-disabled-fill -``` diff --git a/src/button/icon-button.mdx b/src/button/icon-button.mdx index 0813b0de..ffbd23e7 100644 --- a/src/button/icon-button.mdx +++ b/src/button/icon-button.mdx @@ -64,36 +64,4 @@ Dark mode colors are applied when the `.theme_dark` class is set on the root ele ## Style customization -### Colors - -The following CSS custom properties are available to customize the button-like element appearance. - -``` ---reactist-actionable-primary-idle-tint ---reactist-actionable-primary-idle-fill ---reactist-actionable-primary-hover-tint ---reactist-actionable-primary-hover-fill ---reactist-actionable-primary-disabled-tint ---reactist-actionable-primary-disabled-fill - ---reactist-actionable-secondary-idle-tint ---reactist-actionable-secondary-idle-fill ---reactist-actionable-secondary-hover-tint ---reactist-actionable-secondary-hover-fill ---reactist-actionable-secondary-disabled-tint ---reactist-actionable-secondary-disabled-fill - ---reactist-actionable-tertiary-idle-tint ---reactist-actionable-tertiary-idle-fill ---reactist-actionable-tertiary-hover-tint ---reactist-actionable-tertiary-hover-fill ---reactist-actionable-tertiary-disabled-tint ---reactist-actionable-tertiary-disabled-fill - ---reactist-actionable-destructive-idle-tint ---reactist-actionable-destructive-idle-fill ---reactist-actionable-destructive-hover-tint ---reactist-actionable-destructive-hover-fill ---reactist-actionable-destructive-disabled-tint ---reactist-actionable-destructive-disabled-fill -``` +# diff --git a/src/password-field/password-field.mdx b/src/password-field/password-field.mdx index 1aabb76c..3a8c739b 100644 --- a/src/password-field/password-field.mdx +++ b/src/password-field/password-field.mdx @@ -17,17 +17,6 @@ A component used to accept password input from the user. -## Colors - -The following CSS custom properties are available so that the `PasswordField`'s border colors can be customized. -Note that these variables are shared with other components such as `Textfield`, `SelectField`, and `TextArea`. - -``` ---reactist-inputs-focus ---reactist-inputs-idle ---reactist-inputs-alert -``` - diff --git a/src/select-field/select-field.mdx b/src/select-field/select-field.mdx index 842d4ded..857d11b7 100644 --- a/src/select-field/select-field.mdx +++ b/src/select-field/select-field.mdx @@ -17,17 +17,6 @@ A component that provides a menu of options, similar to the native `