From d38977c7b4baf5e3a8baaf757c559a2411189f06 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 26 May 2026 15:08:53 +0200 Subject: [PATCH] feat(ui): introduce semantic color token families and deprecate legacy tokens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Redesigns the BUI color token system in `@backstage/ui`: - Adds a gray scale (`--bui-gray-1` through `--bui-gray-11`) - Adds new foreground tokens with explicit hex values (primary, secondary, disabled, positive, negative, warning, announcement) - Introduces five new semantic color families — Accent, Announcement, Warning, Negative, Positive — each with bg-base, bg-subdued, border, fg-on-base, and fg-on-subdued variants, for both light and dark themes - Moves all legacy tokens (`--bui-bg-solid-*`, `--bui-bg-neutral-*`, `--bui-bg-danger/warning/success/info`, `--bui-fg-solid`, `--bui-fg-danger/success/info`, `--bui-border-*`, `--bui-shadow`) into a clearly marked `/* Deprecated tokens */` section in both light and dark themes - Updates the Spotify theme overrides to use the new accent tokens and mark legacy overrides as deprecated - Rewrites the `Colors` Storybook story to display all token families as a live, theme-aware reference grid - Adds a new `@backstage/no-deprecated-bui-tokens` ESLint rule to `@backstage/eslint-plugin` that warns when any deprecated BUI token is referenced in JS/TS string literals; the rule is included in the `recommended` config so it applies to all plugin authors automatically Signed-off-by: Charles de Dreuille --- .storybook/themes/spotify.css | 35 +- packages/eslint-plugin/index.js | 2 + .../rules/no-deprecated-bui-tokens.js | 122 +++++ packages/ui/.eslintrc.js | 3 +- packages/ui/src/css/colors.stories.tsx | 448 +++++++++++------- packages/ui/src/css/tokens.css | 242 +++++++--- 6 files changed, 603 insertions(+), 249 deletions(-) create mode 100644 packages/eslint-plugin/rules/no-deprecated-bui-tokens.js diff --git a/.storybook/themes/spotify.css b/.storybook/themes/spotify.css index 7a34299817..1e8ef5090c 100644 --- a/.storybook/themes/spotify.css +++ b/.storybook/themes/spotify.css @@ -193,49 +193,48 @@ } [data-theme-mode='light'][data-theme-name='spotify'] { + --bui-ring: rgba(0, 0, 0, 0.2); + --bui-accent-bg: #1ed760; + --bui-accent-bg-hover: #3be477; + --bui-accent-bg-disabled: #0f6c30; + --bui-accent-fg: var(--bui-black); + --bui-accent-fg-disabled: #62ab7c; + + /* Deprecated tokens */ --bui-bg-solid: #1ed760; --bui-bg-solid-hover: #3be477; --bui-bg-solid-pressed: #1abc54; --bui-bg-solid-disabled: #0f6c30; - - --bui-fg-primary: var(--bui-black); - --bui-fg-secondary: #757575; --bui-fg-solid: var(--bui-black); --bui-fg-solid-disabled: #62ab7c; - - --bui-border-2: #d9d9d9; --bui-border-danger: #f87a7a; --bui-border-warning: #e36d05; --bui-border-success: #53db83; - - --bui-ring: rgba(0, 0, 0, 0.2); } [data-theme-mode='dark'][data-theme-name='spotify'] { - --bui-bg-app: var(--bui-black); + --bui-ring: rgba(255, 255, 255, 0.2); + --bui-accent-bg: #1ed760; + --bui-accent-bg-hover: #3be477; + --bui-accent-bg-disabled: #0f6c30; + --bui-accent-fg: var(--bui-black); + --bui-accent-fg-disabled: #62ab7c; + /* Deprecated tokens */ + --bui-bg-app: var(--bui-black); --bui-bg-solid: #1ed760; --bui-bg-solid-hover: #3be477; --bui-bg-solid-pressed: #1abc54; --bui-bg-solid-disabled: #0f6c30; - --bui-bg-danger: #3b1219; --bui-bg-warning: #302008; --bui-bg-success: #132d21; - - --bui-fg-primary: var(--bui-white); - --bui-fg-secondary: #9e9e9e; - --bui-fg-disabled: #575757; --bui-fg-solid: var(--bui-black); --bui-fg-solid-disabled: #072f15; --bui-fg-danger: #e22b2b; - --bui-fg-warning: #e36d05; --bui-fg-success: #1db954; - - --bui-border-2: #373737; + --bui-fg-warning: #e36d05; --bui-border-danger: #f87a7a; --bui-border-warning: #e36d05; --bui-border-success: #53db83; - - --bui-ring: rgba(255, 255, 255, 0.2); } diff --git a/packages/eslint-plugin/index.js b/packages/eslint-plugin/index.js index e31091ace3..69065f091d 100644 --- a/packages/eslint-plugin/index.js +++ b/packages/eslint-plugin/index.js @@ -25,6 +25,7 @@ module.exports = { '@backstage/no-mixed-plugin-imports': 'warn', '@backstage/no-ui-css-imports-in-non-frontend': 'error', '@backstage/no-self-package-imports': 'error', + '@backstage/no-deprecated-bui-tokens': 'warn', }, }, }, @@ -36,5 +37,6 @@ module.exports = { 'no-mixed-plugin-imports': require('./rules/no-mixed-plugin-imports'), 'no-ui-css-imports-in-non-frontend': require('./rules/no-ui-css-imports-in-non-frontend'), 'no-self-package-imports': require('./rules/no-self-package-imports'), + 'no-deprecated-bui-tokens': require('./rules/no-deprecated-bui-tokens'), }, }; diff --git a/packages/eslint-plugin/rules/no-deprecated-bui-tokens.js b/packages/eslint-plugin/rules/no-deprecated-bui-tokens.js new file mode 100644 index 0000000000..831688efd8 --- /dev/null +++ b/packages/eslint-plugin/rules/no-deprecated-bui-tokens.js @@ -0,0 +1,122 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-check + +/** @type {string[]} */ +const DEPRECATED_TOKENS = [ + '--bui-bg-solid', + '--bui-bg-solid-hover', + '--bui-bg-solid-pressed', + '--bui-bg-solid-disabled', + '--bui-bg-app', + '--bui-bg-neutral-1', + '--bui-bg-neutral-1-hover', + '--bui-bg-neutral-1-pressed', + '--bui-bg-neutral-1-disabled', + '--bui-bg-neutral-2', + '--bui-bg-neutral-2-hover', + '--bui-bg-neutral-2-pressed', + '--bui-bg-neutral-2-disabled', + '--bui-bg-neutral-3', + '--bui-bg-neutral-3-hover', + '--bui-bg-neutral-3-pressed', + '--bui-bg-neutral-3-disabled', + '--bui-bg-neutral-4', + '--bui-bg-neutral-4-hover', + '--bui-bg-neutral-4-pressed', + '--bui-bg-neutral-4-disabled', + '--bui-bg-danger', + '--bui-bg-warning', + '--bui-bg-success', + '--bui-bg-info', + '--bui-fg-solid', + '--bui-fg-solid-disabled', + '--bui-fg-danger-on-bg', + '--bui-fg-warning-on-bg', + '--bui-fg-success-on-bg', + '--bui-fg-info-on-bg', + '--bui-fg-danger', + '--bui-fg-success', + '--bui-fg-info', + '--bui-border-info', + '--bui-border-danger', + '--bui-border-warning', + '--bui-border-success', + '--bui-shadow', +]; + +const DEPRECATED_SET = new Set(DEPRECATED_TOKENS); + +/** + * Extracts all CSS custom property names referenced inside a string value, + * e.g. "var(--bui-bg-solid)" → ["--bui-bg-solid"] + * @param {string} value + * @returns {string[]} + */ +function extractTokenNames(value) { + const matches = value.match(/--bui-[\w-]+/g); + return matches ?? []; +} + +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + meta: { + type: 'suggestion', + docs: { + description: + 'Warn when deprecated Backstage UI CSS tokens are referenced in JS/TS string literals.', + url: 'https://github.com/backstage/backstage/blob/master/packages/eslint-plugin/docs/rules/no-deprecated-bui-tokens.md', + }, + messages: { + deprecated: + "'{{token}}' is a deprecated BUI token. Use the new semantic token families instead: --bui-negative-*, --bui-positive-*, --bui-warning-*, --bui-announcement-*, or --bui-accent-*.", + }, + schema: [], + }, + + create(context) { + /** + * @param {import('estree').Node} node + * @param {string} value + */ + function checkValue(node, value) { + for (const token of extractTokenNames(value)) { + if (DEPRECATED_SET.has(token)) { + context.report({ + node, + messageId: 'deprecated', + data: { token }, + }); + } + } + } + + return { + Literal(node) { + if (typeof node.value === 'string') { + checkValue(node, node.value); + } + }, + + TemplateElement(node) { + if (node.value?.cooked) { + checkValue(node, node.value.cooked); + } + }, + }; + }, +}; diff --git a/packages/ui/.eslintrc.js b/packages/ui/.eslintrc.js index 9638ff6e45..b098bceebb 100644 --- a/packages/ui/.eslintrc.js +++ b/packages/ui/.eslintrc.js @@ -3,7 +3,8 @@ module.exports = { extends: ['plugin:storybook/recommended'], rules: { 'react/forbid-elements': 'off', - '@backstage/no-mixed-plugin-imports': 'off' + '@backstage/no-mixed-plugin-imports': 'off', + '@backstage/no-deprecated-bui-tokens': 'warn', }, }; diff --git a/packages/ui/src/css/colors.stories.tsx b/packages/ui/src/css/colors.stories.tsx index 49e3cdaec5..e7d86cf6c3 100644 --- a/packages/ui/src/css/colors.stories.tsx +++ b/packages/ui/src/css/colors.stories.tsx @@ -14,192 +14,296 @@ * limitations under the License. */ import preview from '../../../../.storybook/preview'; -import { Box } from '../components/Box'; -import { Flex } from '../components/Flex'; -import { Text } from '../components/Text'; const meta = preview.meta({ title: 'Backstage UI/Colors', tags: ['!manifest'], }); -/** - * A `
` styled with `background: var(--bui-bg-inherit)` should always - * resolve to the same color as the surrounding bg provider — at every level - * of the neutral chain and inside intent surfaces. - */ -const Probe = ({ label }: { label: string }) => ( +type SwatchItem = { label: string; token: string }; + +const Swatch = ({ label, token }: SwatchItem) => (
- {label} +
+
+ + {label} + + + {token} + +
); -export const Default = meta.story({ +const Section = ({ + title, + tokens, +}: { + title: string; + tokens: SwatchItem[]; +}) => ( +
+
+ {title} +
+ {tokens.map(t => ( + + ))} +
+); + +export const All = meta.story({ + name: 'All Colors', render: () => ( -
- - - Neutral 1 - - Hover - - - Pressed - - - Disabled - - - - - Neutral 2 - - Hover - - - Pressed - - - Disabled - - - - - Neutral 3 - - Hover - - - Pressed - - - - Disabled - - - - - - Neutral 4 - - Hover - - - Pressed - - - - Disabled - - - - - - - +
+
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
), }); - -export const BgInherit = meta.story({ - render: () => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ), -}); diff --git a/packages/ui/src/css/tokens.css b/packages/ui/src/css/tokens.css index 9426993ea5..d50822613b 100644 --- a/packages/ui/src/css/tokens.css +++ b/packages/ui/src/css/tokens.css @@ -67,150 +67,276 @@ --bui-radius-6: calc(1.25rem); --bui-radius-full: 9999px; + /* Animations */ + --bui-animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + /* Base Colors */ --bui-black: #000000; --bui-white: #ffffff; + --bui-ring: #1f5493; + --bui-scrollbar: #a0a0a03b; + --bui-scrollbar-thumb: #a0a0a0; - /* Solid background colors */ + /* Gray scale */ + --bui-gray-1: #fafafa; + --bui-gray-2: #f5f5f5; + --bui-gray-3: #e5e5e5; + --bui-gray-4: #d4d4d4; + --bui-gray-5: #a1a1a1; + --bui-gray-6: #737373; + --bui-gray-7: #525252; + --bui-gray-8: #404040; + --bui-gray-9: #262626; + --bui-gray-10: #171717; + --bui-gray-11: #0a0a0a; + + /* Surface colors */ + --bui-surface-1: #f5f5f5; + --bui-surface-2: var(--bui-white); + --bui-surface-3: #f7f7f7; + --bui-surface-4: var(--bui-white); + --bui-surface-5: #f7f7f7; + + /* Foreground colors */ + --bui-fg-primary: var(--bui-black); + --bui-fg-secondary: #696969; + --bui-fg-disabled: #aaaaaa; + --bui-fg-positive: #1abc54; + --bui-fg-negative: #ee3a4c; + --bui-fg-warning: #f18900; + --bui-fg-announcement: #2a86f3; + + /* Border colors */ + --bui-border-1: var(--bui-gray-3); + --bui-border-2: var(--bui-gray-6); + + /* Accent */ + --bui-accent-bg: #1f5493; + --bui-accent-bg-hover: #163a66; + --bui-accent-bg-disabled: #163a66; + --bui-accent-fg: #ffffff; + --bui-accent-fg-disabled: #98a8bc; + + /* Announcement */ + --bui-announcement-bg: #0d72ea; + --bui-announcement-bg-hover: #2b88f5; + --bui-announcement-bg-disabled: #0d72ea; + --bui-announcement-bg-subdued: #c8e0fc; + --bui-announcement-bg-subdued-hover: #e0edfd; + --bui-announcement-bg-subdued-disabled: #c8e0fc; + --bui-announcement-border: #549ef4; + --bui-announcement-fg: #ffffff; + --bui-announcement-fg-disabled: #ffffff; + --bui-announcement-fg-subdued: #173da6; + --bui-announcement-fg-subdued-disabled: #173da6; + + /* Warning */ + --bui-warning-bg: #ff9400; + --bui-warning-bg-hover: #ffb656; + --bui-warning-bg-disabled: #ff9400; + --bui-warning-bg-subdued: #ffedd5; + --bui-warning-bg-subdued-hover: #f8ddb9; + --bui-warning-bg-subdued-disabled: #f8ddb9; + --bui-warning-border: #ff9400; + --bui-warning-fg: #000000; + --bui-warning-fg-disabled: #000000; + --bui-warning-fg-subdued: #aa4d00; + --bui-warning-fg-subdued-disabled: #aa4d00; + + /* Negative */ + --bui-negative-bg: #dc2626; + --bui-negative-bg-hover: #f44b4b; + --bui-negative-bg-disabled: #ff8686; + --bui-negative-bg-subdued: #ffcbcb; + --bui-negative-bg-subdued-hover: #f7b6b6; + --bui-negative-bg-subdued-disabled: #f7b6b6; + --bui-negative-border: #d06565; + --bui-negative-fg: #ffffff; + --bui-negative-fg-disabled: #ffffff; + --bui-negative-fg-subdued: #991919; + --bui-negative-fg-subdued-disabled: #bb7272; + + /* Positive */ + --bui-positive-bg: #1ed760; + --bui-positive-bg-hover: #3be477; + --bui-positive-bg-disabled: #1abc54; + --bui-positive-bg-subdued: #96f0b6; + --bui-positive-bg-subdued-hover: #c5f7d7; + --bui-positive-bg-subdued-disabled: #96f0b6; + --bui-positive-border: #54a671; + --bui-positive-fg: #000000; + --bui-positive-fg-disabled: #ffffff; + --bui-positive-fg-subdued: #0c632b; + --bui-positive-fg-subdued-disabled: #0c632b; + + /* Deprecated tokens */ --bui-bg-solid: #1f5493; --bui-bg-solid-hover: #163a66; --bui-bg-solid-pressed: #0f2b4e; --bui-bg-solid-disabled: #163a66; - - /* Neutral background colors */ --bui-bg-app: #f8f8f8; - --bui-bg-neutral-1: #fff; --bui-bg-neutral-1-hover: oklch(0% 0 0 / 6%); --bui-bg-neutral-1-pressed: oklch(0% 0 0 / 12%); --bui-bg-neutral-1-disabled: oklch(0% 0 0 / 6%); - --bui-bg-neutral-2: oklch(0% 0 0 / 6%); --bui-bg-neutral-2-hover: oklch(0% 0 0 / 12%); --bui-bg-neutral-2-pressed: oklch(0% 0 0 / 16%); --bui-bg-neutral-2-disabled: oklch(0% 0 0 / 6%); - --bui-bg-neutral-3: oklch(0% 0 0 / 6%); --bui-bg-neutral-3-hover: oklch(0% 0 0 / 12%); --bui-bg-neutral-3-pressed: oklch(0% 0 0 / 16%); --bui-bg-neutral-3-disabled: oklch(0% 0 0 / 6%); - --bui-bg-neutral-4: oklch(0% 0 0 / 6%); --bui-bg-neutral-4-hover: oklch(0% 0 0 / 12%); --bui-bg-neutral-4-pressed: oklch(0% 0 0 / 16%); --bui-bg-neutral-4-disabled: oklch(0% 0 0 / 6%); - - /* Status background colors */ --bui-bg-danger: #ffe2e2; --bui-bg-warning: #ffedd5; --bui-bg-success: #dcfce7; --bui-bg-info: #dbeafe; - - /* Foreground colors */ - --bui-fg-primary: var(--bui-black); - --bui-fg-secondary: oklch(0% 0 0 / 50%); - --bui-fg-disabled: oklch(0% 0 0 / 28%); --bui-fg-solid: var(--bui-white); --bui-fg-solid-disabled: #98a8bc; - - /* Foreground Statuses */ --bui-fg-danger-on-bg: #991919; --bui-fg-warning-on-bg: #92310a; --bui-fg-success-on-bg: #116932; --bui-fg-info-on-bg: #173da6; --bui-fg-danger: #ec3b18; - --bui-fg-warning: #ef7a32; --bui-fg-success: #1aaf4f; --bui-fg-info: #0d74ce; - - /* Border colors */ - --bui-border-1: #d5d5d5; - --bui-border-2: #bababa; --bui-border-info: #7ea9d6; --bui-border-danger: #f87a7a; --bui-border-warning: #e36d05; --bui-border-success: #53db83; - - /* Special colors */ - --bui-ring: #1f5493; - --bui-scrollbar: #a0a0a03b; - --bui-scrollbar-thumb: #a0a0a0; - - /* Shadows */ --bui-shadow: 0 10px 15px -3px rgba(0 0 0 / 0.1), 0 4px 6px -4px rgba(0 0 0 / 0.1); - - --bui-animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; } /* Dark theme tokens */ [data-theme-mode='dark'] { - /* Solid background colors */ + /* Base colors */ + --bui-ring: #1f5493; + --bui-scrollbar: #3636363a; + --bui-scrollbar-thumb: #575757; + + /* Surface colors */ + --bui-surface-1: #333333; + --bui-surface-2: #1a1a1a; + --bui-surface-3: #282828; + --bui-surface-4: #393939; + --bui-surface-5: #474747; + + /* Foreground colors */ + --bui-fg-primary: var(--bui-white); + --bui-fg-secondary: #a3a3a3; + --bui-fg-disabled: var(--bui-white); + --bui-fg-positive: #21b656; + --bui-fg-negative: #ee3a4c; + --bui-fg-warning: #f18900; + --bui-fg-announcement: #2a86f3; + + /* Border colors */ + --bui-border-1: var(--bui-gray-6); + --bui-border-2: var(--bui-gray-5); + + /* Accent */ + --bui-accent-bg: #9cc9ff; + --bui-accent-bg-hover: #83b9fd; + --bui-accent-bg-disabled: #3b6293; + --bui-accent-fg: #101821; + --bui-accent-fg-disabled: #6191cc; + + /* Announcement */ + --bui-announcement-bg: #0d72ea; + --bui-announcement-bg-hover: #2b88f5; + --bui-announcement-bg-disabled: #0d72ea; + --bui-announcement-bg-subdued: #052a56; + --bui-announcement-bg-subdued-hover: #0c3d77; + --bui-announcement-bg-subdued-disabled: #052a56; + --bui-announcement-border: #2363af; + --bui-announcement-fg: #ffffff; + --bui-announcement-fg-disabled: #ffffff; + --bui-announcement-fg-subdued: #70b8ff; + --bui-announcement-fg-subdued-disabled: #70b8ff; + + /* Warning */ + --bui-warning-bg: #ffa42c; + --bui-warning-bg-hover: #ffb656; + --bui-warning-bg-disabled: #ffb656; + --bui-warning-bg-subdued: #491e00; + --bui-warning-bg-subdued-hover: #612901; + --bui-warning-bg-subdued-disabled: #582400; + --bui-warning-border: #7c4903; + --bui-warning-fg: #000000; + --bui-warning-fg-disabled: #000000; + --bui-warning-fg-subdued: #f2ab4a; + --bui-warning-fg-subdued-disabled: #f2ab4a; + + /* Negative */ + --bui-negative-bg: #dc2626; + --bui-negative-bg-hover: #f44b4b; + --bui-negative-bg-disabled: #dc2626; + --bui-negative-bg-subdued: #350708; + --bui-negative-bg-subdued-hover: #5e1a1b; + --bui-negative-bg-subdued-disabled: #5e1a1b; + --bui-negative-border: #6f101c; + --bui-negative-fg: #ffffff; + --bui-negative-fg-disabled: #ffffff; + --bui-negative-fg-subdued: #fca5a5; + --bui-negative-fg-subdued-disabled: #ffffff; + + /* Positive */ + --bui-positive-bg: #1ed760; + --bui-positive-bg-hover: #3be477; + --bui-positive-bg-disabled: #1abc54; + --bui-positive-bg-subdued: #073116; + --bui-positive-bg-subdued-hover: #0b431f; + --bui-positive-bg-subdued-disabled: #073116; + --bui-positive-border: #136d33; + --bui-positive-fg: #000000; + --bui-positive-fg-disabled: #ffffff; + --bui-positive-fg-subdued: #8ddeaa; + --bui-positive-fg-subdued-disabled: #8ddeaa; + + /* Deprecated tokens */ --bui-bg-solid: #9cc9ff; --bui-bg-solid-hover: #83b9fd; --bui-bg-solid-pressed: #83b9fd; --bui-bg-solid-disabled: #1b3d68; - - /* Neutral background colors */ --bui-bg-app: #333333; - --bui-bg-neutral-1: oklch(100% 0 0 / 10%); --bui-bg-neutral-1-hover: oklch(100% 0 0 / 14%); --bui-bg-neutral-1-pressed: oklch(100% 0 0 / 20%); --bui-bg-neutral-1-disabled: oklch(100% 0 0 / 10%); - --bui-bg-neutral-2: oklch(100% 0 0 / 6%); --bui-bg-neutral-2-hover: oklch(100% 0 0 / 10%); --bui-bg-neutral-2-pressed: oklch(100% 0 0 / 16%); --bui-bg-neutral-2-disabled: oklch(100% 0 0 / 6%); - --bui-bg-neutral-3: oklch(100% 0 0 / 8%); --bui-bg-neutral-3-hover: oklch(100% 0 0 / 12%); --bui-bg-neutral-3-pressed: oklch(100% 0 0 / 20%); --bui-bg-neutral-3-disabled: oklch(100% 0 0 / 8%); - --bui-bg-neutral-4: oklch(100% 0 0 / 8%); --bui-bg-neutral-4-hover: oklch(100% 0 0 / 12%); --bui-bg-neutral-4-pressed: oklch(100% 0 0 / 20%); --bui-bg-neutral-4-disabled: oklch(100% 0 0 / 8%); - - /* Status background colors */ --bui-bg-danger: #300c0c; --bui-bg-warning: #302008; --bui-bg-success: #042713; --bui-bg-info: #132049; - - /* Foreground colors */ - --bui-fg-primary: var(--bui-white); - --bui-fg-secondary: oklch(100% 0 0 / 50%); - --bui-fg-disabled: oklch(100% 0 0 / 28%); --bui-fg-solid: #101821; --bui-fg-solid-disabled: #6191cc; - - /* Foreground statuses */ --bui-fg-danger-on-bg: #fca5a5; --bui-fg-warning-on-bg: #fdba74; --bui-fg-success-on-bg: #86efac; --bui-fg-info-on-bg: #a3cfff; --bui-fg-danger: #ff5a30; - --bui-fg-warning: #ffa057; --bui-fg-success: #1ed760; --bui-fg-info: #70b8ff; - - /* Border colors */ - --bui-border-1: #434343; - --bui-border-2: #585858; --bui-border-info: #7ea9d6; --bui-border-danger: #f87a7a; --bui-border-warning: #e36d05; --bui-border-success: #53db83; - - /* Special colors */ - --bui-ring: #1f5493; - --bui-scrollbar: #3636363a; - --bui-scrollbar-thumb: #575757; - - /* Shadows */ --bui-shadow: none; } }