Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions modules/docs/llm/upgrade-guides/15.0-UPGRADE-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ semantic meaning to allow for better use and theming.
- [Indicators](#indicators)
- [Navigation](#navigation)
- [Popups](#popups)
- [Theming](#theming)
- [System Brand Tokens and Brand Tokens](#system-brand-tokens-and-brand-tokens)
- [Deprecations](#deprecations)
- [Accent Icon](#accent-icon)
- [Applet Icon](#applet-icon)
Expand Down Expand Up @@ -537,6 +539,23 @@ If you'd like to see the visual differences between `v14` with `v3` tokens and `

`Menu`, `Modal`, `Popup`, `Toast` and `Tooltip`

## Theming

### System Brand Tokens and Brand Tokens

The relationship between **system brand tokens** (e.g. `system.color.brand.accent.primary`) and **brand tokens** (e.g. `brand.primary600`) has changed. Teams can still set palette values such as `base`, `light`, `lighter`, `lightest`, `dark` and `darkest` via the `CanvasProvider` `theme` prop. The mapping inside `CanvasProvider` exists for **backwards compatibility**. When you pass a theme object, we forward those values to both the legacy brand tokens and the system brand tokens so current implementations will continue to work.

For more information on theming, view our [Theming](https://workday.github.io/canvas-kit/?path=/docs/features-theming-overview--docs) documentation.

For more information on our tokens, vie\w our [Tokens](https://workday.github.io/canvas-tokens/?path=/docs/docs-getting-started--docs) documentation.

```tsx
// This will set the [brand.primary.**] tokens to shades of purple.
<CanvasProvider theme={{canvas: {palette: {primary: {main: 'purple'}}}}}>
<App />
</CanvasProvider>
```

## Deprecations

We add the [@deprecated](https://jsdoc.app/tags-deprecated.html) JSDoc tag to code we plan to remove
Expand Down
20 changes: 20 additions & 0 deletions modules/docs/mdx/15.0-UPGRADE-GUIDE.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ semantic meaning to allow for better use and theming.
- [Indicators](#indicators)
- [Navigation](#navigation)
- [Popups](#popups)
- [Theming](#theming)
- [System Brand Tokens and Brand Tokens](#system-brand-tokens-and-brand-tokens)
- [Deprecations](#deprecations)
- [Accent Icon](#accent-icon)
- [Applet Icon](#applet-icon)
Expand Down Expand Up @@ -544,6 +546,24 @@ If you'd like to see the visual differences between `v14` with `v3` tokens and `

`Menu`, `Modal`, `Popup`, `Toast` and `Tooltip`

## Theming

### System Brand Tokens and Brand Tokens

The relationship between **system brand tokens** (e.g. `system.color.brand.accent.primary`) and **brand tokens** (e.g. `brand.primary600`) has changed. Teams can still set palette values such as `base`, `light`, `lighter`, `lightest`, `dark` and `darkest` via the `CanvasProvider` `theme` prop. The mapping inside `CanvasProvider` exists for **backwards compatibility**. When you pass a theme object, we forward those values to both the legacy brand tokens and the system brand tokens so current implementations will continue to work.

For more information on theming, view our [Theming](https://workday.github.io/canvas-kit/?path=/docs/features-theming-overview--docs) documentation.

For more information on our tokens, vie\w our [Tokens](https://workday.github.io/canvas-tokens/?path=/docs/docs-getting-started--docs) documentation.

```tsx
// This will set the [brand.primary.**] tokens to shades of purple.
<CanvasProvider theme={{canvas: {palette: {primary: {main: 'purple'}}}}}>
<App />
</CanvasProvider>
```


## Deprecations

We add the [@deprecated](https://jsdoc.app/tags-deprecated.html) JSDoc tag to code we plan to remove
Expand Down
296 changes: 279 additions & 17 deletions modules/react/common/lib/CanvasProvider.tsx

Large diffs are not rendered by default.

175 changes: 39 additions & 136 deletions modules/react/common/stories/mdx/Theming.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {Theming} from './examples/Theming';

## Overview

Canvas Kit v14 introduces a significant shift in our approach to theming: we've moved away from
Canvas Kit v14 and v15 introduce a significant shift in our approach to theming: we've moved away from
JavaScript-based theme objects to CSS variables. This change provides better performance, improved
developer experience, and greater flexibility for theming applications.

Expand All @@ -20,6 +20,8 @@ developer experience, and greater flexibility for theming applications.
>
> If your application renders within an environment that already imports these CSS variables, **do not re-import them**.

View our latest tokens documentation [here](https://workday.github.io/canvas-tokens/?path=/docs/docs-getting-started--docs).

## Migration from v10 Theme Prop to v14 CSS Variables

### The Evolution
Expand Down Expand Up @@ -80,11 +82,11 @@ and scoped to the `div` that the `CanvasProvider` created. This meant that anyth
or outside of the `CanvasProvider` would not be able to cascade down to the components within the
`CanvasProvider`.

If you provide a `theme` to the `CanvasProvider`, it will create a scoped theme. Note that in v14, global CSS variables are the recommended way to theme Popups and Modals consistently.
If you provide a `theme` to the `CanvasProvider`, it will create a scoped theme. Note that in v14 and v15, global CSS variables are the recommended way to theme Popups and Modals consistently.

## Global vs Scoped Theming

Canvas Kit v14 supports two theming strategies: **global theming** and **scoped theming**. Understanding the difference is important to avoid unexpected behavior.
Canvas Kit v14 and v15 support two theming strategies: **global theming** and **scoped theming**. Understanding the difference is important to avoid unexpected behavior.

### Global Theming

Expand All @@ -94,16 +96,16 @@ Global theming applies CSS variables at the `:root` level, making them available
@import '@workday/canvas-tokens-web/css/base/_variables.css';
:root {
// This is showing how you can change the value of a token at the root level of your application.
--cnvs-brand-primary-base: var(--cnvs-base-palette-magenta-600);
--cnvs-brand-primary-600: var(--cnvs-base-palette-magenta-600);
}
```

### Scoped Theming

Scoped theming applies CSS variables to a specific section of your application using the `CanvasProvider` with either a `className` or `theme` prop. The theme only affects components within that provider.
Scoped theming applies CSS variables to a specific section of your application using the `CanvasProvider` via the `theme` prop. The theme only affects components within that provider.

```tsx
// Using the theme prop for scoped theming. This will set the [brand.primary.**] tokens to shades of purple.
// Using the theme prop for scoped theming. This will set the [brand.primary.**] tokens to shades of purple. This will also ensure that the Popup and Modal components are themed consistently.
<CanvasProvider theme={{canvas: {palette: {primary: {main: 'purple'}}}}}>
<ScopedSection />
</CanvasProvider>
Expand All @@ -123,7 +125,7 @@ For all other cases, use global theming at `:root` to ensure consistent theming

## ✅ Preferred Approach (v14+)

Canvas Kit v14 promotes using CSS variables for theming, which can be applied in two ways:
Canvas Kit v14 and v15 promote using CSS variables for theming, which can be applied in two ways:

### Method 1: Global CSS Variables (Recommended)

Expand All @@ -138,13 +140,12 @@ CSS:

:root {
/* Override brand primary colors */
--cnvs-brand-primary-base: var(--cnvs-base-palette-magenta-600);
--cnvs-brand-primary-light: var(--cnvs-base-palette-magenta-200);
--cnvs-brand-primary-lighter: var(--cnvs-base-palette-magenta-50);
--cnvs-brand-primary-lightest: var(--cnvs-base-palette-magenta-25);
--cnvs-brand-primary-dark: var(--cnvs-base-palette-magenta-700);
--cnvs-brand-primary-darkest: var(--cnvs-base-palette-magenta-800);
--cnvs-brand-primary-accent: var(--cnvs-base-palette-neutral-0);
--cnvs-brand-primary-600: var(--cnvs-base-palette-magenta-600);
--cnvs-brand-primary-200: var(--cnvs-base-palette-magenta-200);
--cnvs-brand-primary-50: var(--cnvs-base-palette-magenta-50);
--cnvs-brand-primary-25: var(--cnvs-base-palette-magenta-25);
--cnvs-brand-primary-700: var(--cnvs-base-palette-magenta-700);
--cnvs-brand-primary-800: var(--cnvs-base-palette-magenta-800);
}
```

Expand All @@ -154,65 +155,18 @@ CSS:

### Method 2: Provider-Level CSS Variables

Use Canvas Kit's `createStyles` utility to generate themed class names that can be applied to
Use Canvas Kit's `CanvasProvider` and `theme` prop to generate themed class names that can be applied to
specific components or sections:

> **Note:** Doing the following **will create a cascade barrier**. Only use this method if you
> intentionally want to override the default theme.

```tsx
import {createStyles}from "@workday/canvas-kit-styling"
import {brand, base} from "@workday/canvas-tokens-web"
import {CanvasProvider} from "@workday/canvas-kit-react/common"

// You can import the CSS variables in a ts file or an index.css file. You do not need to do both.
import '@workday/canvas-tokens-web/css/base/_variables.css';
import '@workday/canvas-tokens-web/css/system/_variables.css';
import '@workday/canvas-tokens-web/css/brand/_variables.css';

// Generate a class name that defines CSS variables
const themedBrand = createStyles({
[brand.primary.accent]: base.neutral0,
[brand.primary.darkest]: base.blue800,
[brand.primary.dark]: base.blue700,
[brand.primary.base]: base.blue600,
[brand.primary.light]: base.blue200,
[brand.primary.lighter]: base.blue50,
[brand.primary.lightest]: base.blue25,
})

<CanvasProvider className={themedBrand}>
// This will set the [brand.primary.**] tokens to shades of purple. This will also ensure that the Popup and Modal components are themed consistently.
<CanvasProvider theme={{canvas: {palette: {primary: {main: 'purple'}}}}}>
<App/>
</CanvasProvider>
```

### Theming Modals and Dialogs

Previously, the `usePopupStack` hook created a CSS class name that was passed to our Popups. We attached those theme styles to that class name. This allowed the theme to be available in our Popups. But it also created a cascade barrier that blocked the global theme from being applied to our Popup components.
Because we now use global CSS variables, we no longer need this class name to provide the global theme to Popups. But we have to remove this generated class name to allow the global theme to be applied to Popups.

**Before in v13**

```tsx
// When passing a theme to the Canvas Provider, the `usePopupStack` would grab the theme and generate a class to forward the theme to Modals and Dialogs. This would create a cascade barrier for any CSS variables defined at the root.
<CanvasProvider theme={{canvas: {palette: {primary: {main: 'blue'}}}}}>
<Modal>//... rest of modal code</Modal>
</CanvasProvider>
```

**After in v14**

```tsx
// If you wish to still theme you application and Modals, you can either define the CSS variables at the root level of your application or define a className and pass it to the CanvasProvider.
:root {
--cnvs-brand-primary-base: blue;
}

<CanvasProvider>
<Modal>//... rest of modal code</Modal>
</CanvasProvider>
```

## CSS Token Structure

Canvas Kit provides three layers of CSS variables.
Expand All @@ -233,20 +187,21 @@ Base tokens define foundation palette and design values.
Brand tokens define semantic color assignments.

```css
--cnvs-brand-primary-base: var(--cnvs-base-palette-blue-600);
--cnvs-brand-primary-accent: var(--cnvs-base-palette-neutral-0);
--cnvs-brand-error-base: var(--cnvs-base-palette-red-600);
--cnvs-brand-success-base: var(--cnvs-base-palette-green-600);
--cnvs-brand-primary-600: var(--cnvs-base-palette-blue-600);
--cnvs-brand-primary-200: var(--cnvs-base-palette-blue-200);
--cnvs-brand-primary-50: var(--cnvs-base-palette-blue-50);
--cnvs-brand-primary-25: var(--cnvs-base-palette-blue-25);
--cnvs-brand-primary-700: var(--cnvs-base-palette-blue-700);
--cnvs-brand-primary-800: var(--cnvs-base-palette-blue-800);
```

### System Tokens (`system/_variables.css`)

System tokens define component-specific values.

```css
--cnvs-sys-color-bg-primary-default: var(--cnvs-base-palette-blue-600);
--cnvs-sys-color-text-primary-default: var(--cnvs-base-palette-blue-600);
--cnvs-sys-space-x4: calc(var(--cnvs-base-unit) * 4);
--cnvs-sys-color-bg-default: var(--cnvs-base-palette-blue-600);
--cnvs-sys-shape-sm: var(--cnvs-base-size-50);
```

## Practical Examples
Expand All @@ -261,29 +216,19 @@ System tokens define component-specific values.

:root {
/* Primary brand colors */
--cnvs-brand-primary-base: var(--cnvs-base-palette-magenta-600);
--cnvs-brand-primary-light: var(--cnvs-base-palette-magenta-200);
--cnvs-brand-primary-lighter: var(--cnvs-base-palette-magenta-50);
--cnvs-brand-primary-lightest: var(--cnvs-base-palette-magenta-25);
--cnvs-brand-primary-dark: var(--cnvs-base-palette-magenta-700);
--cnvs-brand-primary-darkest: var(--cnvs-base-palette-magenta-800);
--cnvs-brand-primary-accent: var(--cnvs-base-palette-neutral-0);
--cnvs-brand-primary-600: var(--cnvs-base-palette-magenta-600);
--cnvs-brand-primary-200: var(--cnvs-base-palette-magenta-200);
--cnvs-brand-primary-50: var(--cnvs-base-palette-magenta-50);
--cnvs-brand-primary-25: var(--cnvs-base-palette-magenta-25);
--cnvs-brand-primary-700: var(--cnvs-base-palette-magenta-700);
--cnvs-brand-primary-800: var(--cnvs-base-palette-magenta-800);
}
```

<ExampleCodeBlock code={Theming} />
### Scoped Theming

### Dark Mode Implementation
<ExampleCodeBlock code={Theming} />

```css
/* Dark mode theming */
[data-theme='dark'] {
--cnvs-sys-color-bg-default: var(--cnvs-base-palette-neutral-950);
--cnvs-sys-color-text-default: var(--cnvs-base-palette-neutral-50);
--cnvs-sys-color-border-container: var(--cnvs-base-palette-slate-700);
--cnvs-sys-color-bg-alt-default: var(--cnvs-base-palette-slate-800);
}
```

### RTL Support

Expand Down Expand Up @@ -410,31 +355,11 @@ const theme = {
Replace theme-based `CanvasProvider` usage with CSS class-based theming.

```tsx
// Before:
<CanvasProvider theme={customTheme}>
<App />
</CanvasProvider>

// After:
<CanvasProvider className={customThemeClass}>
<CanvasProvider theme={{canvas: {palette: {primary: {main: 'green'}}}}}>
<App />
</CanvasProvider>
```

> **Note:** Using a class means you will need to define each property of the palette for full
> control over theming.

### Step 4: Test Component Rendering

Verify that Canvas Kit components (like `PrimaryButton`) correctly use the new CSS variables.

```tsx
import {PrimaryButton} from '@workday/canvas-kit-react/button';

// This should automatically use your CSS variable overrides
<PrimaryButton>Themed Button</PrimaryButton>;
```

## Best Practices

### 1. Use Semantic Token Names
Expand All @@ -443,7 +368,7 @@ Use brand tokens instead of base tokens for better maintainability.

```css
/* ✅ Good - semantic meaning */
--cnvs-brand-primary-base: var(--cnvs-base-palette-blue-600);
--cnvs-brand-primary-600: var(--cnvs-base-palette-blue-600);

/* ❌ Avoid - direct base token usage */
--cnvs-base-palette-blue-600: blue;
Expand All @@ -453,13 +378,7 @@ Use brand tokens instead of base tokens for better maintainability.

Ensure color combinations meet accessibility standards.

```css
/* Verify contrast ratios for text/background combinations */
:root {
--cnvs-brand-primary-base: var(--cnvs-base-palette-blue-600);
--cnvs-brand-primary-accent: var(--cnvs-base-palette-neutral-0); /* White text */
}
```
For a full list of color contrast pairs, view our [Color Contrast](https://canvas.workday.com/guidelines/color/color-contrast) documentation.

### 3. Avoid Component Level Theming

Expand All @@ -469,15 +388,11 @@ component level.
```tsx
/* ✅ Good - App level theming */
import {CanvasProvider} from '@workday/canvas-kit-react/common';
import {createStyles} from '@workday/canvas-kit-styling';
import {base, brand} from '@workday/canvas-tokens-web';

const myCustomTheme = createStyles({
[brand.primary.base]: base.magenta600
})
import {base, brand} from '@workday/canvas-tokens-web';


<CanvasProvider className={myCustomTheme}>
<CanvasProvider theme={{canvas: {palette: {primary: {main: base.magenta600}}}}}>
<App/>
</CanvasProvider>

Expand All @@ -495,18 +410,6 @@ const myCustomTheme = createStyles({

```

## Component Compatibility

All Canvas Kit components in v14 automatically consume CSS variables. No component-level changes are
required when switching from the theme prop approach to CSS variables.

### Supported Components

- ✅ All Button variants (`PrimaryButton`, `SecondaryButton`, etc.)
- ✅ Form components (`TextInput`, `FormField`, etc.)
- ✅ Layout components (`Card`, `Modal`, etc.)
- ✅ Navigation components (`Tabs`, `SidePanel`, etc.)

## Performance Benefits

The CSS variable approach provides several performance improvements:
Expand Down
Loading