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
75 changes: 73 additions & 2 deletions modules/docs/mdx/16.0-UPGRADE-GUIDE.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ Soon to be...
- [New Components](#new-components)
- [KBD](#kbd)
- [Component Updates](#component-updates)
- [Accessibility: Checked-State Contrast](#accessibility-checked-state-contrast)
- [Checkbox](#checkbox)
- [Radio](#radio)
- [Color Input](#color-input)
- [Color Picker](#color-picker)
- [Form Field](#form-field)
- [Text Area](#text-area)
- [Text Input](#text-input)
- [Card](#card)
- [New Utilities](#new-utilities)
- [cornerShapeStencil](#cornershapestencil)
Expand Down Expand Up @@ -122,8 +130,71 @@ functional shortcuts, refer to the storybook documentation and our example stori

## Component Updates

> **Note:** All visual updates apply to both the Default Canvas theme and new Sana Canvas theme
> unless specified otherwise.
### Accessibility: Checked-State Contrast

> **Important:** The checked states of `Checkbox`, `Radio`, and `Switch` now derive their
> background/fill color from `system.color.brand.accent.positive` (which maps to your theme's
> `brand.success.600`), while the foreground (the check icon, radio dot, and switch thumb) remains
> an inverse/white color. This pairing relies on `brand.success.600` being a sufficiently dark
> color.

This change is safe for the default Canvas themes, where `brand.success.600` is dark enough to
maintain adequate contrast against the white foreground. However, **consumer themes that override
`brand.success.600` with a light color may produce insufficient contrast** between the checked
background and the white check icon, radio dot, or switch thumb. This can cause the checked state to
fail
[WCAG 1.4.11 Non-text Contrast (3:1)](https://www.w3.org/WAI/WCAG21/Understanding/non-text-contrast.html).

If you customize `brand.success.600` in your theme, please verify the following:

- **Maintain a minimum 3:1 contrast ratio** between your `brand.success.main` value and the white
(`#ffffff`) foreground used for the check icon, radio dot, and switch thumb.
- Prefer a `brand.success.600` value that is dark enough to pair with a light foreground. If your
brand requires a light success color, you may need to override the component styles so the
foreground uses a darker, paired contrast color instead of white.
> **Note:** All visual updates apply to both the Default Canvas theme and new Sana Canvas theme
> unless specified otherwise.

### Checkbox

**PR:** [#3984](https://github.com/Workday/canvas-kit/pull/3984)

#### Visual Updates

- The default Checkbox size is now **20px** (previously 24px).
- Checked state uses `system.color.brand.accent.positive` instead of
Comment thread
RayRedGoose marked this conversation as resolved.
`system.color.brand.accent.primary` for the background.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- Error and alert states no longer display a status background color; only the standard background
is shown.
- The hover ring is smaller to better align with the smaller size. The hover ring background color
uses neutral instead of slate in `sana-canvas` theme.

### Radio

**PR:** [#3984](https://github.com/Workday/canvas-kit/pull/3984)

#### Visual Updates

- The default Radio size is now **20px** (previously 24px).
- Checked state uses `system.color.brand.accent.positive` instead of
`system.color.brand.accent.primary` for the background.
- Error and alert states no longer display a status background color; only the standard background
is shown.
- The hover ring is smaller to better align with the smaller size. The hover ring background color
uses a neutral color instead of slate in `sana-canvas` theme.

### Switch

**PR:** [#3984](https://github.com/Workday/canvas-kit/pull/3984)

#### Visual Updates

- The Switch thumb is now **16px** (was 14px). The icon-thumb container width remains unchanged.
- The checked state background now uses `system.color.brand.accent.positive` instead of
`system.color.brand.accent.primary`.
- The default (unchecked) background color now uses `system.color.surface.muted.default` instead of
`system.color.surface.muted.soft`. Background color uses a neutral color instead of slate in
`sana-canvas` theme.

### Color Input

Expand Down
2 changes: 1 addition & 1 deletion modules/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"@workday/canvas-kit-react": "^15.0.14",
"@workday/canvas-kit-styling": "^15.0.14",
"@workday/canvas-system-icons-web": "4.0.4",
"@workday/canvas-tokens-web": "4.4.0-beta.0",
"@workday/canvas-tokens-web": "4.4.0-beta.3",
"markdown-to-jsx": "^7.2.0",
"react-syntax-highlighter": "^15.5.0",
"ts-node": "^10.9.1"
Expand Down
2 changes: 1 addition & 1 deletion modules/labs-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"@workday/canvas-kit-react": "^15.0.14",
"@workday/canvas-kit-styling": "^15.0.14",
"@workday/canvas-system-icons-web": "4.0.4",
"@workday/canvas-tokens-web": "4.4.0-beta.0",
"@workday/canvas-tokens-web": "4.4.0-beta.3",
"@workday/design-assets-types": "^0.3.0",
"chroma-js": "^2.2.0",
"lodash.flatten": "^4.4.0",
Expand Down
2 changes: 1 addition & 1 deletion modules/preview-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"@workday/canvas-kit-react": "^15.0.14",
"@workday/canvas-kit-styling": "^15.0.14",
"@workday/canvas-system-icons-web": "4.0.4",
"@workday/canvas-tokens-web": "4.4.0-beta.0",
"@workday/canvas-tokens-web": "4.4.0-beta.3",
"@workday/design-assets-types": "^0.3.0"
},
"devDependencies": {
Expand Down
14 changes: 9 additions & 5 deletions modules/preview-react/radio/lib/RadioGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import {ErrorType, Themeable, createContainer} from '@workday/canvas-kit-react/common';
import {
ErrorType,
Themeable,
cornerShapeStencil,
createContainer,
} from '@workday/canvas-kit-react/common';
import {FlexProps, mergeStyles} from '@workday/canvas-kit-react/layout';
import {CSProps, calc, createStencil, px2rem} from '@workday/canvas-kit-styling';
import {base, system} from '@workday/canvas-tokens-web';
Expand All @@ -18,12 +23,13 @@ export interface RadioGroupProps extends Themeable, CSProps, FlexProps {
* Styles for RadioGroup
*/
const radioGroupStencil = createStencil({
extends: cornerShapeStencil,
base: {
[cornerShapeStencil.vars.shape]: system.legacy.shape.lg,
display: 'flex',
flexDirection: 'column',
borderRadius: system.legacy.shape.md,
gap: system.legacy.gap.sm,
padding: `${px2rem(10)} ${base.legacy.size150} ${system.legacy.padding.xs}`,
padding: `${system.legacy.padding.xs} ${system.legacy.padding.sm}`,
margin: `0 ${calc.negate(base.legacy.size150)}`,
transition: '100ms box-shadow',
width: 'fit-content',
Expand All @@ -32,10 +38,8 @@ const radioGroupStencil = createStencil({
error: {
error: {
boxShadow: `inset 0 0 0 ${px2rem(2)} ${system.legacy.color.brand.border.critical}`,
backgroundColor: system.legacy.color.brand.surface.critical.default,
},
caution: {
backgroundColor: system.legacy.color.brand.surface.caution.default,
boxShadow: `inset 0 0 0 ${px2rem(1)} ${system.legacy.color.brand.focus.caution.inner}, inset 0 0 0 ${px2rem(3)} ${system.legacy.color.brand.border.caution}`,
},
},
Expand Down
4 changes: 2 additions & 2 deletions modules/preview-react/radio/lib/RadioLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';
import {ExtractProps, Themeable, createSubcomponent} from '@workday/canvas-kit-react/common';
import {Flex, mergeStyles} from '@workday/canvas-kit-react/layout';
import {CSProps, createStencil} from '@workday/canvas-kit-styling';
import {base, system} from '@workday/canvas-tokens-web';
import {system} from '@workday/canvas-tokens-web';

import {RadioInput} from './RadioInput';
import {RadioText} from './RadioText';
Expand All @@ -28,7 +28,7 @@ export interface RadioLabelProps
const radioLabelStencil = createStencil({
base: {
alignItems: 'flex-start',
minHeight: base.legacy.size225,
minHeight: system.legacy.size.xxxs,
position: 'relative',
gap: system.legacy.gap.sm,
},
Expand Down
34 changes: 18 additions & 16 deletions modules/preview-react/radio/lib/StyledRadioButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';
import {ExtractProps, StyledType, createComponent} from '@workday/canvas-kit-react/common';
import {Box, Flex, mergeStyles} from '@workday/canvas-kit-react/layout';
import {CSProps, createStencil, handleCsProp, px2rem} from '@workday/canvas-kit-styling';
import {base, system} from '@workday/canvas-tokens-web';
import {system} from '@workday/canvas-tokens-web';

import {RadioLabelContext} from './RadioLabel';

Expand All @@ -17,23 +17,23 @@ export const radioInputStencil = createStencil({
},
base: {
cursor: 'pointer',
height: base.legacy.size225,
width: base.legacy.size225,
height: system.legacy.size.xs,
width: system.legacy.size.xs,
borderRadius: system.legacy.shape.full,
position: 'absolute',
margin: 0,
opacity: system.opacity.zero,
'&:focus-visible, &.focus, &:active': {
outline: 'transparent',
outline: `${px2rem(1)} solid transparent`,
},
'&:disabled, &.disabled': {
cursor: 'auto',
opacity: system.opacity.disabled,
// This creates the inner circle when the Radio is checked.
// The backgroundColor represents the dot in the middle of the radio.
// The borderColor represents the border around the middle dot of the radio.
'&:checked + .cnvs-radio-check, &.checked + .cnvs-radio-check': {
backgroundColor: system.legacy.color.surface.default, // inner circle background color
border: `${px2rem(5)} solid ${system.legacy.color.brand.accent.primary}`, // inner circle border color
border: `${px2rem(5)} solid ${system.legacy.color.brand.accent.positive}`, // inner circle border color
},
},

Expand All @@ -45,8 +45,8 @@ export const radioInputStencil = createStencil({
backgroundColor: system.color.bg.default,
boxSizing: 'border-box',
border: `${px2rem(1)} solid ${system.color.border.input.default}`,
height: base.legacy.size225,
width: base.legacy.size225,
height: system.legacy.size.xxxs,
width: system.legacy.size.xxxs,
borderRadius: system.legacy.shape.full,
justifyContent: 'center',
pointerEvents: 'none',
Expand All @@ -69,7 +69,7 @@ export const radioInputStencil = createStencil({
// The borderColor represents the border around the middle dot of the radio.
'&:checked + .cnvs-radio-check, &.checked + .cnvs-radio-check': {
backgroundColor: system.legacy.color.surface.default, // inner circle background color
border: `${px2rem(5)} solid ${system.legacy.color.brand.accent.primary}`, // inner circle border color
border: `${px2rem(5)} solid ${system.legacy.color.brand.accent.positive}`, // inner circle border color
},

'&:focus-visible:checked + .cnvs-radio-check, &:focus-visible:hover:checked + .cnvs-radio-check, &.focus:checked + .cnvs-radio-check, &.focus:hover:checked + .cnvs-radio-check':
Expand All @@ -96,7 +96,7 @@ export const radioInputStencil = createStencil({
// The backgroundColor represents the dot in the middle of the radio.
// The borderColor represents the border around the middle dot of the radio.
[`&:checked + ${checkPart}, &.checked + ${checkPart}`]: {
backgroundColor: system.legacy.color.brand.accent.primary, // inner circle background color
backgroundColor: system.legacy.color.brand.accent.positive, // inner circle background color
borderColor: system.legacy.color.border.inverse.default, // inner circle border color
},
},
Expand Down Expand Up @@ -135,29 +135,31 @@ const StyledRadioInput = createComponent('input')<StyledRadioButtonProps & Style

export const radioInputWrapperStencil = createStencil({
base: {
height: base.legacy.size225,
width: base.legacy.size225,
height: system.legacy.size.xxs,
width: system.legacy.size.xxs,
flex: '0 0 auto',
alignItems: 'center',
justifyContent: 'center',
// Hover Ripple element
'::before': {
content: "''",
position: 'absolute',
borderRadius: system.legacy.shape.full,
height: base.legacy.size225,
height: system.legacy.size.xxxs,
transition: 'box-shadow 150ms ease-out',
width: base.legacy.size225,
width: system.legacy.size.xxxs,
pointerEvents: 'none',
opacity: system.opacity.full,
},
'&:hover:before, &.hover:before': {
boxShadow: `0 0 0 ${px2rem(7)} ${system.legacy.color.surface.overlay.hover.default}`,
boxShadow: `0 0 0 ${px2rem(4)} ${system.legacy.color.surface.overlay.hover.default}`,
},
},
modifiers: {
variant: {
inverse: {
'&:hover:before, &.hover:before': {
boxShadow: `0 0 0 ${px2rem(7)} ${system.legacy.color.surface.overlay.hover.inverse}`,
boxShadow: `0 0 0 ${px2rem(4)} ${system.legacy.color.surface.overlay.hover.inverse}`,
},
},
},
Expand Down
8 changes: 4 additions & 4 deletions modules/preview-react/switch/lib/SwitchBackground.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {createComponent} from '@workday/canvas-kit-react/common';
import {createStencil, handleCsProp, px2rem} from '@workday/canvas-kit-styling';
import {base, system} from '@workday/canvas-tokens-web';
import {system} from '@workday/canvas-tokens-web';

export const switchBackgroundStencil = createStencil({
base: {
Expand All @@ -10,14 +10,14 @@ export const switchBackgroundStencil = createStencil({
pointerEvents: 'none',
// This is used in "High Contrast Mode" to show a border on the Switch background.
border: `${px2rem(1)} solid transparent`,
height: base.legacy.size225,
height: system.legacy.size.xxs,
// This value is in the spec and there is no token for this size.
// calc() does not work inside of cssVar() as the first value.
width: px2rem(34),
borderRadius: system.legacy.shape.full,
padding: `0 ${px2rem(2)}`,
padding: `0 ${px2rem(1)}`,
transition: 'background-color 200ms ease',
backgroundColor: system.legacy.color.accent.muted.soft,
backgroundColor: system.legacy.color.accent.muted.default,
},
});

Expand Down
10 changes: 5 additions & 5 deletions modules/preview-react/switch/lib/SwitchCircle.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {createComponent} from '@workday/canvas-kit-react/common';
import {createStencil, handleCsProp, px2rem} from '@workday/canvas-kit-styling';
import {base, system} from '@workday/canvas-tokens-web';
import {system} from '@workday/canvas-tokens-web';

import {SwitchProps} from './Switch';

export const switchCircleStencil = createStencil({
base: {
width: base.legacy.size150,
height: base.legacy.size150,
width: system.legacy.size.xxxs,
height: system.legacy.size.xxxs,
borderRadius: system.legacy.shape.full,
// This is used in "High Contrast Mode" to show a border on the Switch thumb.
border: `${px2rem(1)} solid transparent`,
Expand All @@ -20,9 +20,9 @@ export const switchCircleStencil = createStencil({
modifiers: {
checked: {
true: {
transform: `translateX(${px2rem(16)})`,
transform: `translateX(${px2rem(14)})`,
':dir(rtl)': {
transform: `translateX(${px2rem(-16)})`,
transform: `translateX(${px2rem(-14)})`,
},
},
},
Expand Down
4 changes: 2 additions & 2 deletions modules/preview-react/switch/lib/SwitchContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {createComponent} from '@workday/canvas-kit-react/common';
import {createStencil, handleCsProp, px2rem} from '@workday/canvas-kit-styling';
import {base, system} from '@workday/canvas-tokens-web';
import {system} from '@workday/canvas-tokens-web';

export const switchContainerStencil = createStencil({
base: {
position: 'relative',
marginBlockStart: system.legacy.gap.xs,
height: base.legacy.size225,
height: system.legacy.size.xxs,
// This value is in the spec and there is no token for this size.
// calc() does not work inside of cssVar() as the first value.
width: px2rem(34),
Expand Down
4 changes: 2 additions & 2 deletions modules/preview-react/switch/lib/SwitchIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ export const switchIconStencil = createStencil({
position: 'absolute',
transition: 'transform 0ms',
pointerEvents: 'none',
transform: `translateX(${px2rem(12)})`,
transform: `translateX(${px2rem(14)})`,
':dir(rtl)': {
transform: `translateX(${px2rem(-12)})`,
transform: `translateX(${px2rem(-14)})`,
},
},
modifiers: {
Expand Down
4 changes: 2 additions & 2 deletions modules/preview-react/switch/lib/SwitchInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const switchInputStencil = createStencil({
position: 'absolute',
// This allows for the input to be the same size as the clickable area for the Switch
margin: 0,
height: base.legacy.size225,
height: system.legacy.size.xs,
// This value is in the spec and there is no token for this size.
// calc() does not work inside of cssVar() as the first value.
width: px2rem(34),
Expand All @@ -23,7 +23,7 @@ export const switchInputStencil = createStencil({
},
'&:checked, &.checked': {
'& ~ div:first-of-type': {
backgroundColor: system.legacy.color.brand.accent.primary,
backgroundColor: system.legacy.color.brand.accent.positive,
Comment thread
RayRedGoose marked this conversation as resolved.
},
'&:disabled, &.disabled': {
'& ~ div:first-of-type': {
Expand Down
Loading
Loading