diff --git a/.changeset/two-schools-deny.md b/.changeset/two-schools-deny.md new file mode 100644 index 0000000000..aca7242f15 --- /dev/null +++ b/.changeset/two-schools-deny.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': minor +--- + +Updated core CSS tokens and fixing the Button component accordingly. diff --git a/canon-docs/package.json b/canon-docs/package.json index 69fd1cae30..8558fac8e3 100644 --- a/canon-docs/package.json +++ b/canon-docs/package.json @@ -6,7 +6,7 @@ "build": "npm run build:css && next build", "build:css": "node scripts/build-css.js", "lint": "next lint", - "start": "next dev" + "start": "npm run build:css && next dev" }, "dependencies": { "@codemirror/lang-sass": "^6.0.2", diff --git a/canon-docs/scripts/build-css.js b/canon-docs/scripts/build-css.js index be85164347..dd9775150f 100644 --- a/canon-docs/scripts/build-css.js +++ b/canon-docs/scripts/build-css.js @@ -9,11 +9,6 @@ const source1 = path.join(__dirname, `${source}/core.css`); const destination1 = path.join(__dirname, `${destination}/core.css`); const source2 = path.join(__dirname, `${source}/components.css`); const destination2 = path.join(__dirname, `${destination}/components.css`); -const source3 = path.join( - __dirname, - `../../packages/canon/.storybook/themes/backstage.css`, -); -const destination3 = path.join(__dirname, `${destination}/backstage.css`); // Function to bundle and copy the CSS file const bundleAndCopyFile = async (source, destination) => { @@ -34,7 +29,6 @@ const bundleAndCopyFile = async (source, destination) => { Promise.all([ bundleAndCopyFile(source1, destination1), bundleAndCopyFile(source2, destination2), - bundleAndCopyFile(source3, destination3), ]) .then(() => { // Add an empty line after all operations are complete - It looks better in the terminal :) diff --git a/canon-docs/src/app/(docs)/components/button/page.mdx b/canon-docs/src/app/(docs)/components/button/page.mdx index b1276157b6..c92b5b9921 100644 --- a/canon-docs/src/app/(docs)/components/button/page.mdx +++ b/canon-docs/src/app/(docs)/components/button/page.mdx @@ -11,6 +11,7 @@ import { ButtonResponsive, } from '@/snippets/button'; import { buttonVariants } from '@/snippets/_snippets'; +import { buttonPropDefs } from '../../../../../../packages/canon/src/components/Button/Button.props'; # Button @@ -58,34 +59,7 @@ A button component that can be used to trigger actions. ## API reference - + ## Examples diff --git a/canon-docs/src/app/(docs)/theme/theming/page.mdx b/canon-docs/src/app/(docs)/theme/theming/page.mdx index 4cb03859f9..14cd06cb8f 100644 --- a/canon-docs/src/app/(docs)/theme/theming/page.mdx +++ b/canon-docs/src/app/(docs)/theme/theming/page.mdx @@ -186,7 +186,7 @@ are prefixed with `fg` to make it easier to identify. - --canon-fg-text-primary + --canon-fg-primary It should be used on top of `--canon-bg-app` or `--canon-bg-elevated`. @@ -194,7 +194,7 @@ are prefixed with `fg` to make it easier to identify. - --canon-fg-text-secondary + --canon-fg-secondary It should be used on top of `--canon-bg-app` or `--canon-bg-elevated`. diff --git a/canon-docs/src/components/HeadlessBanners/styles.module.css b/canon-docs/src/components/HeadlessBanners/styles.module.css index 31d08aedb4..c87787634e 100644 --- a/canon-docs/src/components/HeadlessBanners/styles.module.css +++ b/canon-docs/src/components/HeadlessBanners/styles.module.css @@ -10,7 +10,7 @@ } .icon path { - fill: var(--canon-fg-text-primary); + fill: var(--canon-fg-primary); } .content { diff --git a/canon-docs/src/components/PropsTable/PropsTable.tsx b/canon-docs/src/components/PropsTable/PropsTable.tsx index 69bff9ffe6..aa6b9f296e 100644 --- a/canon-docs/src/components/PropsTable/PropsTable.tsx +++ b/canon-docs/src/components/PropsTable/PropsTable.tsx @@ -6,8 +6,9 @@ import { icons } from '../../../../packages/canon'; // Define a more specific type for the data object type PropData = { - type: string | string[]; - responsive: boolean; + values?: string | string[]; + responsive?: boolean; + default?: string; }; // Modify the PropsTable component to use the new type @@ -16,17 +17,34 @@ export const PropsTable = >({ }: { data: T; }) => { + const completeData = { + ...data, + children: { + values: 'ReactNode', + responsive: false, + }, + className: { + values: 'string', + responsive: false, + }, + style: { + values: 'CSSProperties', + responsive: false, + }, + }; + return ( Prop Type + Default Responsive - {Object.keys(data).map(n => ( + {Object.keys(completeData).map(n => ( {n} @@ -35,17 +53,22 @@ export const PropsTable = >({
- {data[n].type === 'icon' ? ( + {completeData[n].values === 'icon' ? ( Object.keys(icons).map(icon => {icon}) - ) : Array.isArray(data[n].type) ? ( - data[n].type.map(t => {t}) + ) : Array.isArray(completeData[n].values) ? ( + completeData[n].values.map(t => {t}) ) : ( - {data[n].type} + {completeData[n].values} )}
- {data[n].responsive ? 'Yes' : 'No'} + + {completeData[n].default ? completeData[n].default : '-'} + + + + {completeData[n].responsive ? 'Yes' : 'No'}
))} diff --git a/canon-docs/src/snippets/button.tsx b/canon-docs/src/snippets/button.tsx index 2ae2ab0be9..a7df4315f9 100644 --- a/canon-docs/src/snippets/button.tsx +++ b/canon-docs/src/snippets/button.tsx @@ -11,9 +11,6 @@ export const ButtonPreview = () => { - ); }; diff --git a/packages/canon/.storybook/preview.tsx b/packages/canon/.storybook/preview.tsx index fbc319ccea..8ffa2e55df 100644 --- a/packages/canon/.storybook/preview.tsx +++ b/packages/canon/.storybook/preview.tsx @@ -1,15 +1,12 @@ import React from 'react'; import type { Preview, ReactRenderer } from '@storybook/react'; import { withThemeByDataAttribute } from '@storybook/addon-themes'; +import { CanonProvider } from '../src/contexts/canon'; // Canon specific styles import '../src/css/core.css'; import '../src/css/components.css'; -// Custom themes -import './themes/backstage.css'; -import { CanonProvider } from '../src/contexts/canon'; - const preview: Preview = { parameters: { controls: { @@ -79,8 +76,6 @@ const preview: Preview = { themes: { Light: 'light', Dark: 'dark', - 'Backstage Light': 'backstage-light', - 'Backstage Dark': 'backstage-dark', }, defaultTheme: 'Light', }), diff --git a/packages/canon/.storybook/themes/backstage.css b/packages/canon/.storybook/themes/backstage.css deleted file mode 100644 index 653836c558..0000000000 --- a/packages/canon/.storybook/themes/backstage.css +++ /dev/null @@ -1,88 +0,0 @@ -[data-theme-name='legacy'][data-theme='light'], -[data-theme-name='legacy'][data-theme='dark'] { - --canon-font-regular: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; - - .canon-Button { - border-radius: 60px; - font-weight: 400; - text-transform: uppercase; - font-size: 0.875rem; - transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, - box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, - border 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; - line-height: 1.75; - border-radius: 4px; - background-color: #1f5493; - padding: 6px 16px; - box-shadow: none; - - &:hover { - box-shadow: none; - } - - &.canon-Button--variant-primary { - color: #fff; - background-color: rgb(21, 58, 102); - box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.2), - 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12); - - &:hover { - box-shadow: 0px 2px 4px -1px rgba(0, 0, 0, 0.2), - 0px 4px 5px 0px rgba(0, 0, 0, 0.14), - 0px 1px 10px 0px rgba(0, 0, 0, 0.12); - } - } - - &.canon-Button--variant-secondary { - background-color: transparent; - border: 1px solid rgba(31, 84, 147, 0.5); - color: #1f5493; - - &:hover { - border: 1px solid #1f5493; - background-color: rgba(31, 84, 147, 0.04); - } - } - - &.canon-Button--variant-tertiary { - background-color: transparent; - border: none; - color: #1f5493; - } - } -} - -[data-theme-name='legacy'][data-theme='light'] { - /* Colors */ - --canon-bg-accent: #2e77d0; - --canon-bg: #f8f8f8; - --canon-bg-elevated: #fff; - --canon-bg: #f4f4f4; - - /* Text colors */ - --canon-fg-text-primary: #000; - --canon-fg-accent: #fff; - --canon-fg-text-secondary: #646464; -} - -[data-theme-name='legacy'][data-theme='dark'] { - /* Colors */ - --canon-bg-accent: #fff; - --canon-bg: #000; - --canon-bg-elevated: #121212; - --canon-bg: #1a1a1a; - - /* Borders */ - --canon-border: rgba(255, 255, 255, 0.2); - --canon-border-warning: #f50000; - --canon-border-danger: #f87503; - --canon-border-focus: #25d262; - - /* States - Add more states */ - --canon-fg-danger: #f50000; - - /* Text colors */ - --canon-fg-text-primary: #fff; - --canon-fg-accent: #000; - --canon-fg-text-secondary: #b3b3b3; -} diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index 7fe92e4abb..f194084a9b 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -121,6 +121,27 @@ export const Button: React_2.ForwardRefExoticComponent< ButtonProps & React_2.RefAttributes >; +// @public (undocumented) +export type ButtonOwnProps = GetPropDefTypes; + +// @public (undocumented) +export const buttonPropDefs: { + variant: { + type: 'enum'; + values: ('primary' | 'secondary')[]; + className: string; + default: 'primary'; + responsive: true; + }; + size: { + type: 'enum'; + values: ('small' | 'medium')[]; + className: string; + default: 'medium'; + responsive: true; + }; +}; + // @public export interface ButtonProps { // (undocumented) @@ -134,15 +155,11 @@ export interface ButtonProps { // (undocumented) iconStart?: IconNames; // (undocumented) - size?: 'small' | 'medium' | Partial>; + size?: ButtonOwnProps['size']; // (undocumented) style?: React.CSSProperties; // (undocumented) - variant?: - | 'primary' - | 'secondary' - | 'tertiary' - | Partial>; + variant?: ButtonOwnProps['variant']; } // @public (undocumented) diff --git a/packages/canon/src/components/Box/Box.tsx b/packages/canon/src/components/Box/Box.tsx index 7230b0cbba..8718c77724 100644 --- a/packages/canon/src/components/Box/Box.tsx +++ b/packages/canon/src/components/Box/Box.tsx @@ -37,6 +37,7 @@ export const Box = forwardRef((props, ref) => { ...displayPropDefs, ...boxPropDefs, }; + const { className, style } = extractProps(props, propDefs); return createElement(props.as || 'div', { diff --git a/packages/canon/src/components/Box/styles.css b/packages/canon/src/components/Box/styles.css index 229f322343..f3b24793cf 100644 --- a/packages/canon/src/components/Box/styles.css +++ b/packages/canon/src/components/Box/styles.css @@ -1,4 +1,4 @@ .canon-Box { font-family: var(--canon-font-regular); - color: var(--canon-fg-text-primary); + color: var(--canon-fg-primary); } diff --git a/packages/canon/src/components/Button/Button.props.ts b/packages/canon/src/components/Button/Button.props.ts new file mode 100644 index 0000000000..e363360afa --- /dev/null +++ b/packages/canon/src/components/Button/Button.props.ts @@ -0,0 +1,41 @@ +/* + * 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. + */ + +import type { PropDef, GetPropDefTypes } from '../../props/prop-def'; + +/** @public */ +export const buttonPropDefs = { + variant: { + type: 'enum', + values: ['primary', 'secondary'], + className: 'canon-Button--variant', + default: 'primary', + responsive: true, + }, + size: { + type: 'enum', + values: ['small', 'medium'], + className: 'canon-Button--size', + default: 'medium', + responsive: true, + }, +} satisfies { + variant: PropDef<'primary' | 'secondary'>; + size: PropDef<'small' | 'medium'>; +}; + +/** @public */ +export type ButtonOwnProps = GetPropDefTypes; diff --git a/packages/canon/src/components/Button/Button.stories.tsx b/packages/canon/src/components/Button/Button.stories.tsx index cd52c7fdba..8ba060ad8e 100644 --- a/packages/canon/src/components/Button/Button.stories.tsx +++ b/packages/canon/src/components/Button/Button.stories.tsx @@ -29,9 +29,14 @@ const meta = { control: 'select', options: ['small', 'medium'], }, + variant: { + control: 'select', + options: ['primary', 'secondary'], + }, }, args: { size: 'medium', + variant: 'primary', }, } satisfies Meta; @@ -57,9 +62,6 @@ export const Variants: Story = { - ), }; @@ -94,7 +96,7 @@ export const FullWidth: Story = { children: 'Button', }, render: args => ( - + + + + ))} diff --git a/packages/canon/src/components/Button/Button.tsx b/packages/canon/src/components/Button/Button.tsx index abdd027bf0..97e9ec8fe5 100644 --- a/packages/canon/src/components/Button/Button.tsx +++ b/packages/canon/src/components/Button/Button.tsx @@ -42,7 +42,6 @@ export const Button = forwardRef( return ( ); }, diff --git a/packages/canon/src/components/Button/index.tsx b/packages/canon/src/components/Button/index.tsx index c323ba0329..9051f1145e 100644 --- a/packages/canon/src/components/Button/index.tsx +++ b/packages/canon/src/components/Button/index.tsx @@ -15,3 +15,5 @@ */ export { Button } from './Button'; export type { ButtonProps } from './types'; +export { buttonPropDefs } from './Button.props'; +export type { ButtonOwnProps } from './Button.props'; diff --git a/packages/canon/src/components/Button/styles.css b/packages/canon/src/components/Button/styles.css index 6bfd93a8ea..258db9a2a2 100644 --- a/packages/canon/src/components/Button/styles.css +++ b/packages/canon/src/components/Button/styles.css @@ -22,62 +22,73 @@ user-select: none; font-family: var(--canon-font-regular); font-weight: var(--canon-font-weight-bold); - font-size: var(--canon-font-size-3); padding: 0; - transition: all 150ms ease; cursor: pointer; border-radius: var(--canon-radius-2); + gap: var(--canon-space-1_5); + + &:disabled { + cursor: not-allowed; + } } .canon-Button--variant-primary { - background-color: var(--canon-bg-accent); - color: var(--canon-fg-accent); + background-color: var(--canon-bg-solid); + color: var(--canon-fg-solid); + transition: background-color 150ms ease; &:hover { - background-color: transparent; - box-shadow: inset 0 0 0 1px var(--canon-border-focus); - color: var(--canon-fg-text-primary); + background-color: var(--canon-bg-solid-hover); + } + + &:active { + background-color: var(--canon-bg-solid-pressed); + } + + &:disabled { + background-color: var(--canon-bg-solid-disabled); + color: var(--canon-fg-solid-disabled); } } .canon-Button--variant-secondary { - background-color: transparent; + background-color: var(--canon-bg-elevated); box-shadow: inset 0 0 0 1px var(--canon-border); - color: var(--canon-fg-text-primary); + color: var(--canon-fg-primary); + transition: box-shadow 150ms ease; &:hover { box-shadow: inset 0 0 0 1px var(--canon-border-hover); } -} -.canon-Button--variant-tertiary { - background-color: transparent; - color: var(--canon-fg-text-primary); + &:active { + box-shadow: inset 0 0 0 1px var(--canon-border-focus); + } - &:hover { - color: var(--canon-fg-text-secondary); + &:disabled { + box-shadow: inset 0 0 0 1px var(--canon-border-disabled); + color: var(--canon-fg-disabled); } } -.canon-Button--size-small { - padding-left: 6px; - padding-right: 6px; - height: 32px; -} - .canon-Button--size-medium { - padding-left: 8px; - padding-right: 8px; + font-size: var(--canon-font-size-4); + padding: 0 var(--canon-space-3); height: 40px; } -.canon-Button--content { - display: flex; - align-items: center; - gap: var(--canon-space-3); - font-weight: var(--canon-font-weight-bold); +.canon-Button--size-small { + font-size: var(--canon-font-size-3); + padding: 0 var(--canon-space-2); + height: 32px; } -.canon-Button--icon-start-end { - flex: 1; +.canon-Button--size-small .canon-Button--icon { + width: 1rem; + height: 1rem; +} + +.canon-Button--size-medium .canon-Button--icon { + width: 1.5rem; + height: 1.5rem; } diff --git a/packages/canon/src/components/Button/types.ts b/packages/canon/src/components/Button/types.ts index 3e2adc84fc..89bb8c79e5 100644 --- a/packages/canon/src/components/Button/types.ts +++ b/packages/canon/src/components/Button/types.ts @@ -14,19 +14,16 @@ * limitations under the License. */ import { IconNames } from '../Icon'; -import type { Breakpoint } from '../../types'; +import type { ButtonOwnProps } from './Button.props'; + /** * Properties for {@link Button} * * @public */ export interface ButtonProps { - size?: 'small' | 'medium' | Partial>; - variant?: - | 'primary' - | 'secondary' - | 'tertiary' - | Partial>; + size?: ButtonOwnProps['size']; + variant?: ButtonOwnProps['variant']; children: React.ReactNode; className?: string; disabled?: boolean; diff --git a/packages/canon/src/components/Checkbox/Checkbox.tsx b/packages/canon/src/components/Checkbox/Checkbox.tsx index 634dc7044c..78dea16c1a 100644 --- a/packages/canon/src/components/Checkbox/Checkbox.tsx +++ b/packages/canon/src/components/Checkbox/Checkbox.tsx @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; +import React from 'react'; import { Checkbox as CheckboxPrimitive } from '@base-ui-components/react/checkbox'; import { Icon } from '@backstage/canon'; import type { CheckboxProps } from './types'; diff --git a/packages/canon/src/components/Checkbox/styles.css b/packages/canon/src/components/Checkbox/styles.css index 1da96e8344..386c6f4671 100644 --- a/packages/canon/src/components/Checkbox/styles.css +++ b/packages/canon/src/components/Checkbox/styles.css @@ -11,7 +11,8 @@ transition: all 0.2s ease-in-out; &[data-checked] { - background-color: var(--canon-bg-accent); + background-color: var(--canon-bg-solid); + color: var(--canon-fg-solid); } } @@ -23,7 +24,7 @@ gap: var(--canon-space-2); font-size: var(--canon-font-size-xs); font-family: var(--canon-font-regular); - color: var(--canon-fg-text-primary); + color: var(--canon-fg-primary); user-select: none; &:hover { diff --git a/packages/canon/src/components/Field/Field.styles.css b/packages/canon/src/components/Field/Field.styles.css index 6bf695fc97..6a8e3c8e22 100644 --- a/packages/canon/src/components/Field/Field.styles.css +++ b/packages/canon/src/components/Field/Field.styles.css @@ -24,14 +24,14 @@ .canon-FieldLabel { font-size: var(--canon-font-size-2); font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-text-primary); + color: var(--canon-fg-primary); margin-bottom: var(--canon-space-1_5); } .canon-FieldDescription { font-size: var(--canon-font-size-2); font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-text-secondary); + color: var(--canon-fg-secondary); margin: 0; padding-top: var(--canon-space-1_5); } @@ -47,7 +47,7 @@ .canon-FieldValidity { font-size: var(--canon-font-size-2); font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-text-secondary); + color: var(--canon-fg-secondary); margin: 0; padding-top: var(--canon-space-1_5); } diff --git a/packages/canon/src/components/Heading/styles.css b/packages/canon/src/components/Heading/styles.css index a730afe9f0..2db11d7eb2 100644 --- a/packages/canon/src/components/Heading/styles.css +++ b/packages/canon/src/components/Heading/styles.css @@ -16,7 +16,7 @@ .canon-Heading { font-family: var(--canon-font-regular); - color: var(--canon-fg-text-primary); + color: var(--canon-fg-primary); line-height: 100%; padding: 0; margin: 0; diff --git a/packages/canon/src/components/Icon/Icon.tsx b/packages/canon/src/components/Icon/Icon.tsx index c761d0d104..4c7b55680a 100644 --- a/packages/canon/src/components/Icon/Icon.tsx +++ b/packages/canon/src/components/Icon/Icon.tsx @@ -21,7 +21,7 @@ import clsx from 'clsx'; /** @public */ export const Icon = (props: IconProps) => { - const { name, size = 16, className, style, ...restProps } = props; + const { name, size, className, style, ...restProps } = props; const { icons } = useCanon(); const CanonIcon = icons[name] as React.ComponentType>; @@ -34,7 +34,10 @@ export const Icon = (props: IconProps) => { return ( ); diff --git a/packages/canon/src/components/Input/Input.styles.css b/packages/canon/src/components/Input/Input.styles.css index cfeed27b48..72248f887e 100644 --- a/packages/canon/src/components/Input/Input.styles.css +++ b/packages/canon/src/components/Input/Input.styles.css @@ -21,13 +21,13 @@ background-color: var(--canon-bg-elevated); font-size: var(--canon-font-size-3); font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-text-primary); + color: var(--canon-fg-primary); transition: border-color 0.2s ease-in-out, outline-color 0.2s ease-in-out; width: 100%; } .canon-Input::placeholder { - color: var(--canon-fg-text-secondary); + color: var(--canon-fg-secondary); } .canon-Input:hover { diff --git a/packages/canon/src/components/Text/styles.css b/packages/canon/src/components/Text/styles.css index 9cf8c884fb..871960b8db 100644 --- a/packages/canon/src/components/Text/styles.css +++ b/packages/canon/src/components/Text/styles.css @@ -16,7 +16,7 @@ .canon-Text { font-family: var(--canon-font-regular); - color: var(--canon-fg-text-primary); + color: var(--canon-fg-primary); padding: 0; margin: 0; } diff --git a/packages/canon/src/css/core.css b/packages/canon/src/css/core.css index d744d468d0..f871a08ada 100644 --- a/packages/canon/src/css/core.css +++ b/packages/canon/src/css/core.css @@ -62,81 +62,90 @@ --canon-space-14: calc(var(--canon-space) * 14); /* 56px */ /* Radius */ - --canon-radius-factor: 1.5; - --canon-radius-1: calc(3px * var(--canon-radius-factor)); - --canon-radius-2: calc(4px * var(--canon-radius-factor)); - --canon-radius-3: calc(6px * var(--canon-radius-factor)); - --canon-radius-4: calc(8px * var(--canon-radius-factor)); - --canon-radius-5: calc(12px * var(--canon-radius-factor)); - --canon-radius-6: calc(16px * var(--canon-radius-factor)); + --canon-radius-1: calc(0.125rem); + --canon-radius-2: calc(0.25rem); + --canon-radius-3: calc(0.5rem); + --canon-radius-4: calc(0.75rem); + --canon-radius-5: calc(1rem); + --canon-radius-6: calc(1.25rem); --canon-radius-full: 9999px; - /* Colors */ + /* Background Colors */ --canon-bg: #f8f8f8; --canon-bg-elevated: #fff; - --canon-bg-accent: #000; - --canon-bg-accent-focus: #000; - --canon-bg-accent-disabled: #000; - --canon-bg-accent-hover: #000; - --canon-bg-tint: #edf2fe; - --canon-bg-tint-active: #c7d7ff; - --canon-bg-tint-disabled: #f8f8f8; - --canon-bg-tint-hover: #dbe4ff; - --canon-bg-danger: #f8f8f8; - --canon-bg-elevated: #fff; - --canon-bg-success: #f8f8f8; - --canon-bg-warning: #f8f8f8; - --canon-border: rgba(0, 0, 0, 0.1); - --canon-border-accent: #000; - --canon-border-accent-focus: #000; - --canon-border-accent-hover: #000; - --canon-border-danger: #e22b2b; - --canon-border-focus: rgba(0, 0, 0, 0.4); - --canon-border-hover: rgba(0, 0, 0, 0.2); - --canon-border-success: #008000; - --canon-border-warning: #e36d05; - --canon-fg-text-primary: #000; - --canon-fg-text-secondary: #646464; - --canon-fg-link: #fff; - --canon-fg-link-hover: #fff; - --canon-fg-accent: #fff; - --canon-fg-tint: #000; + --canon-bg-solid: #1f5493; + --canon-bg-solid-hover: #163a66; + --canon-bg-solid-pressed: #0f2b4e; + --canon-bg-solid-disabled: #ebebeb; + --canon-bg-tint: transparent; + --canon-bg-tint-hover: rgba(31, 84, 147, 0.4); + --canon-bg-tint-pressed: rgba(31, 84, 147, 0.6); + --canon-bg-tint-disabled: #ebebeb; + --canon-bg-danger: #feebe7; + --canon-bg-warning: #fff2b2; + --canon-bg-success: #e6f6eb; + + /* Foreground Colors */ + --canon-fg-primary: #000000; + --canon-fg-secondary: #757575; + --canon-fg-link: #1f5493; + --canon-fg-link-hover: #1f2d5c; + --canon-fg-disabled: #9e9e9e; + --canon-fg-solid: #ffffff; + --canon-fg-solid-disabled: #9c9c9c; + --canon-fg-tint: #1f5493; + --canon-fg-tint-disabled: #9e9e9e; --canon-fg-danger: #e22b2b; --canon-fg-warning: #e36d05; - --canon-fg-success: #008000; + --canon-fg-success: #1db954; + + /* Border Colors */ + --canon-border: rgba(0, 0, 0, 0.1); + --canon-border-hover: rgba(0, 0, 0, 0.2); + --canon-border-focus: rgba(0, 0, 0, 0.4); + --canon-border-disabled: rgba(0, 0, 0, 0.1); + --canon-border-danger: #f87a7a; + --canon-border-warning: #e36d05; + --canon-border-success: #53db83; } /* Dark theme tokens */ [data-theme='dark'] { - --canon-bg: #f8f8f8; - --canon-bg-elevated: #fff; - --canon-bg-accent: #000; - --canon-bg-accent-focus: #000; - --canon-bg-accent-disabled: #000; - --canon-bg-accent-hover: #000; - --canon-bg-tint: #edf2fe; - --canon-bg-tint-active: #c7d7ff; - --canon-bg-tint-disabled: #f8f8f8; - --canon-bg-tint-hover: #dbe4ff; - --canon-bg-danger: #f8f8f8; - --canon-bg-elevated: #fff; - --canon-bg-success: #f8f8f8; - --canon-bg-warning: #f8f8f8; - --canon-border: rgba(0, 0, 0, 0.1); - --canon-border-accent: #000; - --canon-border-accent-focus: #000; - --canon-border-accent-hover: #000; - --canon-border-danger: #e22b2b; - --canon-border-focus: rgba(0, 0, 0, 0.4); - --canon-border-hover: rgba(0, 0, 0, 0.2); - --canon-border-success: #008000; - --canon-border-warning: #e36d05; - --canon-fg-accent: #000; + /* Background Colors */ + --canon-bg: #000000; + --canon-bg-elevated: #191919; + --canon-bg-solid: #9cc9ff; + --canon-bg-solid-hover: #83b9fd; + --canon-bg-solid-pressed: #83b9fd; + --canon-bg-solid-disabled: #222222; + --canon-bg-tint: transparent; + --canon-bg-tint-hover: rgba(156, 201, 255, 0.12); + --canon-bg-tint-pressed: rgba(156, 201, 255, 0.16); + --canon-bg-tint-disabled: transparent; + --canon-bg-danger: #3b1219; + --canon-bg-warning: #302008; + --canon-bg-success: #132d21; + + /* Foreground Colors */ + --canon-fg-primary: #ffffff; + --canon-fg-secondary: #9e9e9e; + --canon-fg-link: #9cc9ff; + --canon-fg-link-hover: #7eb5f7; + --canon-fg-disabled: #9e9e9e; + --canon-fg-solid: #101821; + --canon-fg-solid-disabled: #575757; + --canon-fg-tint: #9cc9ff; + --canon-fg-tint-disabled: #575757; --canon-fg-danger: #e22b2b; - --canon-fg-success: #008000; --canon-fg-warning: #e36d05; - --canon-fg-link: #fff; - --canon-fg-link-hover: #fff; - --canon-fg-text-primary: #000; - --canon-fg-text-secondary: #646464; + --canon-fg-success: #1db954; + + /* Border Colors */ + --canon-border: rgba(255, 255, 255, 0.2); + --canon-border-hover: rgba(255, 255, 255, 0.4); + --canon-border-focus: rgba(255, 255, 255, 0.5); + --canon-border-disabled: rgba(255, 255, 255, 0.2); + --canon-border-danger: #f87a7a; + --canon-border-warning: #e36d05; + --canon-border-success: #53db83; }