diff --git a/modules/docs/mdx/11.0-UPGRADE-GUIDE.mdx b/modules/docs/mdx/11.0-UPGRADE-GUIDE.mdx index 196148c262..ef54b99e5e 100644 --- a/modules/docs/mdx/11.0-UPGRADE-GUIDE.mdx +++ b/modules/docs/mdx/11.0-UPGRADE-GUIDE.mdx @@ -20,8 +20,8 @@ any questions. - [Text Area (Preview)](#text-area-preview) - [Text Input (Preview)](#text-input-preview) - [Component Style Updates](#component-style-updates) -- [Component Token Updates](#component-token-updates) - [Component Updates](#component-updates) + - [Buttons](#buttons) - [Card](#card) - [Checkbox](#checkbox) - [Combobox](#combobox) @@ -243,14 +243,6 @@ See below: - - Table (Header) - - - borderColor - soap400 - soap500 - Checkbox @@ -270,6 +262,22 @@ See below: licorice100 + + + DeleteButton + + disabled + backgroundColor + error.light + error.base + + + DeleteButton + + disabled + opacity + 1 + 0.4 Radio @@ -285,7 +293,19 @@ See below: SecondaryButton Inverse focus - color + border + + soap400 + + + transparent + + + + SecondaryButton + Inverse + focus + boxShdaow (Inner Color) blackPepper500 @@ -297,7 +317,7 @@ See below: SecondaryButton Inverse focus - boxShdaow (Inner Color) + color blackPepper500 @@ -317,6 +337,14 @@ See below: blackPepper400 + + Table (Header) + + + borderColor + soap400 + soap500 + TertiaryButton @@ -378,23 +406,7 @@ See below: - DeleteButton - - disabled - backgroundColor - error.light - error.base - - - DeleteButton - - disabled - opacity - 1 - 0.4 - - - TextInput + TextArea disabled borderColor @@ -404,7 +416,7 @@ See below: - TextArea + TextInput disabled borderColor @@ -416,13 +428,19 @@ See below: -### Component Token Updates +## Component Updates -The following components have been updated to use our [new system tokens](insert link). +### Buttons -- Text +**PR:** [#2666](https://github.com/Workday/canvas-kit/pull/2666) -## Component Updates +`PrimaryButton`, `SecondaryButton`, `TertiaryButton` and `DeleteButton` have been refactored to use our +[new styling utilities](https://workday.github.io/canvas-kit/?path=/docs/styling-basics--create-modifiers#createstyles-api) +and [tokens](https://workday.github.io/canvas-tokens/?path=/docs/docs-getting-started--docs). The +components now support the `cs` prop, but otherwise the API has not changed. + +> #### Visual Breaking Change +> The `border` color for `SecondaryButton` on the `focus` state is now `transparent` and may cause a small visual difference in visual tests. ### Card @@ -811,3 +829,5 @@ experimental code and is analagous to code in alpha. Breaking changes can be deployed to Labs at any time without triggering a major version update and may not be subject to the same rigor in communcation and migration strategies reserved for breaking changes in [Preview](#preview) and [Main](#main). +import { opacity } from "@workday/canvas-tokens-web/dist/es6/system" + diff --git a/modules/preview-react/pill/lib/Pill.tsx b/modules/preview-react/pill/lib/Pill.tsx index a6b7c3d574..7d7744c68c 100644 --- a/modules/preview-react/pill/lib/Pill.tsx +++ b/modules/preview-react/pill/lib/Pill.tsx @@ -1,7 +1,7 @@ import React from 'react'; import {CSSObject} from '@emotion/react'; -import {BaseButton, buttonVars} from '@workday/canvas-kit-react/button'; +import {BaseButton, buttonColorPropVars} from '@workday/canvas-kit-react/button'; import { createContainer, focusRing, @@ -11,7 +11,7 @@ import { } from '@workday/canvas-kit-react/common'; import {BoxProps, boxStyleFn, Flex} from '@workday/canvas-kit-react/layout'; import {borderRadius, colors, space, type} from '@workday/canvas-kit-react/tokens'; -import {handleCsProp, CSProps} from '@workday/canvas-kit-styling'; +import {handleCsProp, CSProps, px2rem} from '@workday/canvas-kit-styling'; import {usePillModel} from './usePillModel'; @@ -65,50 +65,50 @@ const StyledBasePill = styled(BaseButton.as('button'))( }, }, }), - [buttonVars.default.background]: colors.soap300, - [buttonVars.default.border]: colors.licorice200, - [buttonVars.default.label]: colors.blackPepper400, + [buttonColorPropVars.default.background]: colors.soap300, + [buttonColorPropVars.default.border]: colors.licorice200, + [buttonColorPropVars.default.label]: colors.blackPepper400, [systemIconStencil.vars.color]: colors.licorice200, button: { [systemIconStencil.vars.color]: colors.licorice200, }, '&:focus-visible, &.focus': { - [buttonVars.focus.background]: colors.soap300, - [buttonVars.focus.border]: colors.blueberry400, - [buttonVars.focus.label]: colors.blackPepper400, + [buttonColorPropVars.focus.background]: colors.soap300, + [buttonColorPropVars.focus.border]: colors.blueberry400, + [buttonColorPropVars.focus.label]: colors.blackPepper400, [systemIconStencil.vars.color]: colors.licorice500, button: { [systemIconStencil.vars.color]: colors.licorice500, }, 'span[data-count="ck-pill-count"]': { - borderTop: `1px solid ${colors.blueberry400}`, - borderBottom: `1px solid ${colors.blueberry400}`, - borderRight: `1px solid ${colors.blueberry400}`, + borderTop: `${px2rem(1)} solid ${colors.blueberry400}`, + borderBottom: `${px2rem(1)} solid ${colors.blueberry400}`, + borderRight: `${px2rem(1)} solid ${colors.blueberry400}`, }, }, '&:hover, &.hover': { - [buttonVars.hover.background]: colors.soap400, - [buttonVars.hover.border]: colors.licorice400, - [buttonVars.hover.label]: colors.blackPepper400, + [buttonColorPropVars.hover.background]: colors.soap400, + [buttonColorPropVars.hover.border]: colors.licorice400, + [buttonColorPropVars.hover.label]: colors.blackPepper400, [systemIconStencil.vars.color]: colors.licorice500, button: { [systemIconStencil.vars.color]: colors.licorice500, }, }, '&:active, &.active': { - [buttonVars.active.background]: colors.soap500, - [buttonVars.active.border]: colors.licorice500, - [buttonVars.active.label]: colors.blackPepper400, + [buttonColorPropVars.active.background]: colors.soap500, + [buttonColorPropVars.active.border]: colors.licorice500, + [buttonColorPropVars.active.label]: colors.blackPepper400, [systemIconStencil.vars.color]: colors.licorice500, button: { [systemIconStencil.vars.color]: colors.licorice500, }, }, '&:disabled, &.disabled': { - [buttonVars.disabled.background]: colors.soap100, - [buttonVars.disabled.border]: colors.licorice100, - [buttonVars.disabled.label]: colors.licorice100, - [buttonVars.disabled.opacity]: '1', + [buttonColorPropVars.disabled.background]: colors.soap100, + [buttonColorPropVars.disabled.border]: colors.licorice100, + [buttonColorPropVars.disabled.label]: colors.licorice100, + [buttonColorPropVars.disabled.opacity]: '1', [systemIconStencil.vars.color]: colors.licorice100, button: { [systemIconStencil.vars.color]: colors.licorice100, @@ -132,32 +132,32 @@ const StyledBasePill = styled(BaseButton.as('button'))( ); const StyledNonInteractivePill = styled(StyledBasePill)({ - [buttonVars.default.background]: colors.soap300, - [buttonVars.default.border]: colors.licorice200, - [buttonVars.default.label]: colors.blackPepper400, + [buttonColorPropVars.default.background]: colors.soap300, + [buttonColorPropVars.default.border]: colors.licorice200, + [buttonColorPropVars.default.label]: colors.blackPepper400, '&:focus-visible, &.focus': { - [buttonVars.focus.background]: colors.soap300, - [buttonVars.focus.border]: colors.licorice200, - [buttonVars.focus.label]: colors.blackPepper400, + [buttonColorPropVars.focus.background]: colors.soap300, + [buttonColorPropVars.focus.border]: colors.licorice200, + [buttonColorPropVars.focus.label]: colors.blackPepper400, }, '&:hover, &.hover': { - [buttonVars.hover.background]: colors.soap300, - [buttonVars.hover.border]: colors.licorice200, - [buttonVars.hover.label]: colors.blackPepper400, + [buttonColorPropVars.hover.background]: colors.soap300, + [buttonColorPropVars.hover.border]: colors.licorice200, + [buttonColorPropVars.hover.label]: colors.blackPepper400, }, '&:active, &.active': { - [buttonVars.active.background]: colors.soap500, - [buttonVars.active.border]: colors.licorice500, - [buttonVars.active.label]: colors.blackPepper400, + [buttonColorPropVars.active.background]: colors.soap500, + [buttonColorPropVars.active.border]: colors.licorice500, + [buttonColorPropVars.active.label]: colors.blackPepper400, }, '&:disabled, &.disabled': { - [buttonVars.disabled.background]: colors.soap100, - [buttonVars.disabled.label]: colors.licorice100, - [buttonVars.disabled.border]: colors.licorice100, + [buttonColorPropVars.disabled.background]: colors.soap100, + [buttonColorPropVars.disabled.label]: colors.licorice100, + [buttonColorPropVars.disabled.border]: colors.licorice100, }, cursor: 'default', overflow: 'revert', // override BaseButton overflow styles so the click target exists outside the pill for removable @@ -172,12 +172,12 @@ const StyledNonInteractivePill = styled(StyledBasePill)({ }); const StyledReadOnlyPill = styled(StyledNonInteractivePill)({ - [buttonVars.default.background]: 'transparent', - [buttonVars.hover.background]: 'transparent', - [buttonVars.focus.background]: 'transparent', - [buttonVars.active.background]: 'transparent', - [buttonVars.disabled.background]: 'transparent', - border: `1px solid ${colors.licorice200}`, + [buttonColorPropVars.default.background]: 'transparent', + [buttonColorPropVars.hover.background]: 'transparent', + [buttonColorPropVars.focus.background]: 'transparent', + [buttonColorPropVars.active.background]: 'transparent', + [buttonColorPropVars.disabled.background]: 'transparent', + border: `${px2rem(1)} solid ${colors.licorice200}`, }); /** diff --git a/modules/preview-react/pill/lib/PillIconButton.tsx b/modules/preview-react/pill/lib/PillIconButton.tsx index 7accf045f6..ca7e40d47f 100644 --- a/modules/preview-react/pill/lib/PillIconButton.tsx +++ b/modules/preview-react/pill/lib/PillIconButton.tsx @@ -7,7 +7,7 @@ import {usePillModel} from './usePillModel'; import {xSmallIcon} from '@workday/canvas-system-icons-web'; import {CanvasSystemIcon} from '@workday/design-assets-types'; import {colors, space} from '@workday/canvas-kit-react/tokens'; -import {BaseButton, buttonVars} from '@workday/canvas-kit-react/button'; +import {BaseButton, buttonColorPropVars} from '@workday/canvas-kit-react/button'; export interface PillIconButtonProps extends Omit { /** @@ -41,32 +41,32 @@ const StyledIconButton = styled(BaseButton)({ innerColor: 'transparent', }), }, - [buttonVars.default.background]: colors.soap300, - [buttonVars.default.border]: 'transparent', - [buttonVars.default.label]: colors.blackPepper400, + [buttonColorPropVars.default.background]: colors.soap300, + [buttonColorPropVars.default.border]: 'transparent', + [buttonColorPropVars.default.label]: colors.blackPepper400, '&:focus-visible, &.focus': { - [buttonVars.focus.background]: colors.soap300, - [buttonVars.focus.border]: 'transparent', - [buttonVars.focus.label]: colors.blackPepper400, + [buttonColorPropVars.focus.background]: colors.soap300, + [buttonColorPropVars.focus.border]: 'transparent', + [buttonColorPropVars.focus.label]: colors.blackPepper400, }, '&:hover, &.hover': { - [buttonVars.hover.background]: colors.soap300, - [buttonVars.hover.border]: 'transparent', - [buttonVars.hover.label]: colors.blackPepper400, + [buttonColorPropVars.hover.background]: colors.soap300, + [buttonColorPropVars.hover.border]: 'transparent', + [buttonColorPropVars.hover.label]: colors.blackPepper400, }, '&:active, &.active': { - [buttonVars.active.background]: colors.soap500, - [buttonVars.active.border]: 'transparent', - [buttonVars.active.label]: colors.blackPepper400, + [buttonColorPropVars.active.background]: colors.soap500, + [buttonColorPropVars.active.border]: 'transparent', + [buttonColorPropVars.active.label]: colors.blackPepper400, }, '&:disabled, &.disabled': { - [buttonVars.disabled.background]: colors.soap100, - [buttonVars.disabled.label]: colors.licorice100, - [buttonVars.disabled.border]: 'transparent', + [buttonColorPropVars.disabled.background]: colors.soap100, + [buttonColorPropVars.disabled.label]: colors.licorice100, + [buttonColorPropVars.disabled.border]: 'transparent', [systemIconStencil.vars.color]: colors.licorice100, }, }); diff --git a/modules/react/button/lib/BaseButton.tsx b/modules/react/button/lib/BaseButton.tsx index 015ff46b1b..fbe67bf296 100644 --- a/modules/react/button/lib/BaseButton.tsx +++ b/modules/react/button/lib/BaseButton.tsx @@ -4,12 +4,12 @@ import {ButtonLabelIcon} from '../lib/parts/ButtonLabelIcon'; import {ButtonLabel} from '../lib/parts/ButtonLabel'; import {createComponent, GrowthBehavior, focusRing} from '@workday/canvas-kit-react/common'; -import {mergeStyles} from '@workday/canvas-kit-react/layout'; -import {createStyles, createVars, cssVar, createModifiers} from '@workday/canvas-kit-styling'; +import {cssVar, createStencil, px2rem, createVars, calc} from '@workday/canvas-kit-styling'; import {SystemIconProps, systemIconStencil} from '@workday/canvas-kit-react/icon'; -import {base, brand, system} from '@workday/canvas-tokens-web'; +import {brand, system} from '@workday/canvas-tokens-web'; import {ButtonColors, ButtonSizes, IconPositions} from './types'; import {CanvasSystemIcon} from '@workday/design-assets-types'; +import {mergeStyles} from '@workday/canvas-kit-react/layout'; export interface ButtonContainerProps extends Partial, GrowthBehavior { /** @@ -25,7 +25,7 @@ export interface ButtonContainerProps extends Partial, GrowthBe size?: ButtonSizes; /** * The icon of the Button. - * Note: not displayed at `small` size + * Note: Not displayed at `small` size */ icon?: CanvasSystemIcon; /** @@ -56,9 +56,9 @@ export interface ButtonContainerProps extends Partial, GrowthBe export interface BaseButtonProps extends Omit {} /** - * Temporary css variables to be used across all Buttons. + * The purpose of this object is for the `colors` prop - to provide backwards compatibility with how we allowed color overrides in Emotion. */ -export const buttonVars = { +export const buttonColorPropVars = { default: createVars( 'background', 'border', @@ -69,7 +69,7 @@ export const buttonVars = { 'opacity', 'borderRadius' ), - hover: createVars( + focus: createVars( 'background', 'border', 'boxShadowInner', @@ -79,7 +79,7 @@ export const buttonVars = { 'opacity', 'borderRadius' ), - active: createVars( + hover: createVars( 'background', 'border', 'boxShadowInner', @@ -89,7 +89,7 @@ export const buttonVars = { 'opacity', 'borderRadius' ), - focus: createVars( + active: createVars( 'background', 'border', 'boxShadowInner', @@ -114,200 +114,260 @@ export const buttonVars = { /** * Base styles for Buttons. */ -const baseButtonStyles = createStyles({ - fontFamily: '"Roboto", "Helvetica Neue", "Helvetica", Arial, sans-serif', - fontSize: '0.875rem', - lineHeight: 'normal', - letterSpacing: '0.015rem', - fontWeight: 'bold', - backgroundColor: cssVar(buttonVars.default.background, 'transparent'), - color: cssVar(buttonVars.default.label, base.blackPepper400), - borderWidth: '1px', - borderStyle: 'solid', - gap: system.space.x2, - borderColor: cssVar(buttonVars.default.border, 'transparent'), - cursor: 'pointer', - display: 'inline-flex', - boxShadow: 'none', - alignItems: 'center', - justifyContent: 'center', - boxSizing: 'border-box', - outline: '2px transparent', - whiteSpace: 'nowrap', - WebkitFontSmoothing: 'antialiased', - MozOsxFontSmoothing: 'grayscale', - borderRadius: cssVar(buttonVars.default.borderRadius, system.shape.round), - position: 'relative', - verticalAlign: 'middle', - overflow: 'hidden', - [systemIconStencil.vars.color]: cssVar(buttonVars.default.icon, base.blackPepper400), - transition: - 'box-shadow 120ms linear, border 120ms linear, background-color 120ms linear, color 120ms linear', - '&:disabled, &:disabled:active, &.disabled': { - cursor: 'default', - boxShadow: 'none', - opacity: cssVar(buttonVars.disabled.opacity, '1'), - }, - /* - '& span .wd-icon-fill, & span .wd-icon-accent, & span .wd-icon-accent2': { - transitionDuration: '40ms', - fill: cssVar(buttonVars.default.icon, base.blackPepper400), +export const buttonStencil = createStencil({ + vars: { + background: '', + border: '', + boxShadowInner: '', + boxShadowOuter: '', + label: '', + opacity: '', + borderRadius: '', }, - '.wd-icon-background ~ .wd-icon-accent, .wd-icon-background ~ .wd-icon-accent2': { - fill: cssVar(buttonVars.default.icon, base.blackPepper400), - }, - */ - '&:focus-visible, &.focus': { - backgroundColor: cssVar(buttonVars.focus.background, 'transparent'), - borderColor: cssVar(buttonVars.focus.border, 'transparent'), - color: cssVar(buttonVars.focus.label, base.blackPepper400), - [systemIconStencil.vars.color]: cssVar(buttonVars.focus.icon, base.blackPepper400), - /* - '& span .wd-icon-fill, & span .wd-icon-accent, & span .wd-icon-accent2': { - fill: cssVar(buttonVars.focus.icon, base.blackPepper400), + base: ({background, border, boxShadowInner, boxShadowOuter, label, opacity, borderRadius}) => ({ + // Default Styles + fontFamily: '"Roboto", "Helvetica Neue", "Helvetica", Arial, sans-serif', + fontSize: '0.875rem', + lineHeight: 'normal', + letterSpacing: '0.015rem', + fontWeight: system.fontWeight.bold, + backgroundColor: cssVar( + buttonColorPropVars.default.background, + cssVar(background, 'transparent') + ), + color: cssVar(buttonColorPropVars.default.label, cssVar(label, system.color.fg.strong)), + borderWidth: px2rem(1), + borderStyle: 'solid', + gap: system.space.x2, + borderColor: cssVar(buttonColorPropVars.default.border, cssVar(border, 'transparent')), + cursor: 'pointer', + display: 'inline-flex', + boxShadow: 'none', + alignItems: 'center', + justifyContent: 'center', + boxSizing: 'border-box', + outline: `${px2rem(2)} transparent`, + whiteSpace: 'nowrap', + WebkitFontSmoothing: 'antialiased', + MozOsxFontSmoothing: 'grayscale', + borderRadius: cssVar( + buttonColorPropVars.default.borderRadius, + cssVar(borderRadius, system.shape.round) + ), + position: 'relative', + verticalAlign: 'middle', + overflow: 'hidden', + [systemIconStencil.vars.color]: cssVar( + buttonColorPropVars.default.icon, + system.color.fg.strong + ), + transition: + 'box-shadow 120ms linear, border 120ms linear, background-color 120ms linear, color 120ms linear', + '&:disabled, &:disabled:active, &.disabled': { + cursor: 'default', + boxShadow: 'none', + opacity: cssVar(buttonColorPropVars.default.opacity, cssVar(opacity, system.opacity.full)), }, - */ - ...focusRing({ - width: 2, - separation: 2, - innerColor: cssVar(buttonVars.focus.boxShadowInner, base.frenchVanilla100), - outerColor: cssVar(buttonVars.focus.boxShadowOuter, brand.primary.base), - }), - }, - '&:hover, &.hover': { - backgroundColor: cssVar(buttonVars.hover.background, base.blackPepper500), - borderColor: cssVar(buttonVars.hover.border, 'transparent'), - color: cssVar(buttonVars.hover.label, base.blackPepper500), - [systemIconStencil.vars.color]: cssVar(buttonVars.hover.icon, base.blackPepper500), - /* - '& span .wd-icon-fill, & span .wd-icon-accent, & span .wd-icon-accent2': { - fill: cssVar(buttonVars.hover.icon, base.blackPepper500), + // Focus Styles + '&:focus-visible, &.focus': { + backgroundColor: cssVar( + buttonColorPropVars.focus.background, + cssVar(background, 'transparent') + ), + borderColor: cssVar(buttonColorPropVars.focus.border, cssVar(border, 'transparent')), + color: cssVar(buttonColorPropVars.focus.label, cssVar(label, system.color.fg.strong)), + [systemIconStencil.vars.color]: cssVar( + buttonColorPropVars.focus.icon, + system.color.fg.strong + ), + ...focusRing({ + width: 2, + separation: 2, + innerColor: cssVar( + buttonColorPropVars.focus.boxShadowInner, + cssVar(boxShadowInner, system.color.fg.inverse) + ), + outerColor: cssVar( + buttonColorPropVars.focus.boxShadowOuter, + cssVar(boxShadowOuter, brand.primary.base) + ), + }), }, - */ - }, - '&:hover:active': {transitionDuration: '40ms'}, - '&:active, &.active': { - backgroundColor: cssVar(buttonVars.active.background, 'transparent'), - borderColor: cssVar(buttonVars.active.border, 'transparent'), - color: cssVar(buttonVars.active.label, base.blackPepper400), - [systemIconStencil.vars.color]: cssVar(buttonVars.active.icon, base.blackPepper400), - /* - '& span .wd-icon-fill, & span .wd-icon-accent, & span .wd-icon-accent2': { - fill: cssVar(buttonVars.active.icon, base.blackPepper400), + // Hover Styles + '&:hover, &.hover': { + backgroundColor: cssVar( + buttonColorPropVars.hover.background, + cssVar(background, system.color.bg.contrast.strong) + ), + borderColor: cssVar(buttonColorPropVars.hover.border, cssVar(border, 'transparent')), + color: cssVar(buttonColorPropVars.hover.label, cssVar(label, system.color.fg.stronger)), + [systemIconStencil.vars.color]: cssVar( + buttonColorPropVars.hover.icon, + system.color.fg.stronger + ), }, - */ - }, - '&:disabled, &.disabled': { - backgroundColor: cssVar(buttonVars.disabled.background, 'transparent'), - borderColor: cssVar(buttonVars.disabled.border, 'transparent'), - color: cssVar(buttonVars.disabled.label, base.blackPepper400), - [systemIconStencil.vars.color]: cssVar(buttonVars.disabled.icon, base.blackPepper400), - /* - '& span .wd-icon-fill, & span .wd-icon-accent, & span .wd-icon-accent2': { - fill: cssVar(buttonVars.disabled.icon, base.blackPepper400), + '&:hover:active': {transitionDuration: '40ms'}, + // Active Styles + '&:active, &.active': { + backgroundColor: cssVar( + buttonColorPropVars.active.background, + cssVar(background, 'transparent') + ), + borderColor: cssVar(buttonColorPropVars.active.border, cssVar(border, 'transparent')), + color: cssVar(buttonColorPropVars.active.label, cssVar(label, system.color.fg.strong)), + [systemIconStencil.vars.color]: cssVar( + buttonColorPropVars.active.icon, + system.color.fg.strong + ), + }, + // Disabled Styles + '&:disabled, &.disabled': { + backgroundColor: cssVar( + buttonColorPropVars.disabled.background, + cssVar(background, 'transparent') + ), + borderColor: cssVar(buttonColorPropVars.disabled.border, cssVar(border, 'transparent')), + color: cssVar(buttonColorPropVars.disabled.label, cssVar(label, system.color.fg.strong)), + [systemIconStencil.vars.color]: cssVar( + buttonColorPropVars.disabled.icon, + system.color.fg.strong + ), + }, + }), + modifiers: { + /** + * Button modifiers that will overwrite the base styles of Buttons. + * - `Size`: These modifiers will dictate a size of a Button and has a set of styles to associated with it. + * - `iconPosition`: These modifiers will override the existing `Size` styles. These are specific to icon locations + * within a button or if there is only an icon and no text. + */ + size: { + large: { + ...system.type.body.small, + fontWeight: system.fontWeight.bold, + height: px2rem(48), + paddingInline: system.space.x8, + minWidth: px2rem(112), + }, + medium: { + ...system.type.subtext.large, + fontWeight: system.fontWeight.bold, + minWidth: px2rem(96), + paddingInline: system.space.x6, + height: system.space.x10, + }, + small: { + ...system.type.subtext.large, + fontWeight: system.fontWeight.bold, + height: system.space.x8, + minWidth: system.space.x20, + paddingInline: system.space.x4, + gap: system.space.x1, + }, + extraSmall: { + ...system.type.subtext.medium, + fontWeight: system.fontWeight.bold, + height: system.space.x6, + minWidth: 'auto', + paddingInline: system.space.x3, + gap: system.space.x1, + }, + }, + // IconPosition Styles + iconPosition: { + only: {padding: system.space.zero}, + start: {}, + end: {}, }, - */ - }, -}); - -/** - * Button modifiers that will overwrite the base styles of Buttons. - * - `Size`: These modifiers will dictate a size of a Button and has a set of styles to associated with it. - * - `iconPosition`: These modifiers will override the existing `Size` styles. These are specific to icon locations - * within a button or if there is only an icon and no text. - */ -export const buttonModifiers = createModifiers({ - size: { - large: createStyles({ - fontSize: system.space.x4, - lineHeight: system.space.x6, - letterSpacing: '0.01rem', - height: '48px', - paddingInline: system.space.x8, - minWidth: '112px', - }), - medium: createStyles({ - fontSize: '0.875rem', - letterSpacing: '0.015rem', - minWidth: '96px', - paddingInline: system.space.x6, - height: system.space.x10, - }), - small: createStyles({ - fontSize: '0.875rem', - letterSpacing: '0.015rem', - height: system.space.x8, - minWidth: system.space.x20, - paddingInline: system.space.x4, - gap: system.space.x1, - }), - extraSmall: createStyles({ - fontSize: '0.75rem', - lineHeight: system.space.x4, - letterSpacing: '0.02rem', - height: system.space.x6, - minWidth: 'auto', - paddingInline: system.space.x3, - gap: system.space.x1, - }), - }, - iconPosition: { - largeOnly: createStyles({ - padding: '0', - minWidth: `calc(${system.space.x4} * 3)`, - }), - largeStart: createStyles({ - paddingInlineStart: system.space.x6, - paddingInlineEnd: system.space.x8, - }), - largeEnd: createStyles({ - paddingInlineStart: system.space.x8, - paddingInlineEnd: system.space.x6, - }), - mediumOnly: createStyles({padding: '0', minWidth: system.space.x10}), - mediumStart: createStyles({ - paddingInlineStart: `calc(${system.space.x1} * 5)`, - paddingInlineEnd: system.space.x6, - }), - mediumEnd: createStyles({ - paddingInlineStart: system.space.x6, - paddingInlineEnd: `calc(${system.space.x1} * 5)`, - }), - smallOnly: createStyles({padding: '0', minWidth: system.space.x8}), - smallStart: createStyles({ - paddingInlineStart: system.space.x3, - paddingInlineEnd: system.space.x4, - }), - smallEnd: createStyles({ - paddingInlineStart: system.space.x4, - paddingInlineEnd: system.space.x3, - }), - extraSmallOnly: createStyles({padding: '0', minWidth: system.space.x6}), - extraSmallStart: createStyles({ - paddingInlineStart: system.space.x2, - paddingInlineEnd: system.space.x3, - }), - extraSmallEnd: createStyles({ - paddingInlineStart: system.space.x3, - paddingInlineEnd: system.space.x2, - }), }, + // Compound Modifier Styles + compound: [ + { + modifiers: {size: 'large', iconPosition: 'only'}, + styles: { + minWidth: calc.multiply(system.space.x4, 3), + }, + }, + { + modifiers: {size: 'large', iconPosition: 'start'}, + styles: { + paddingInlineStart: system.space.x6, + paddingInlineEnd: system.space.x8, + }, + }, + { + modifiers: {size: 'large', iconPosition: 'end'}, + styles: { + paddingInlineStart: system.space.x8, + paddingInlineEnd: system.space.x6, + }, + }, + { + modifiers: {size: 'medium', iconPosition: 'only'}, + styles: { + minWidth: system.space.x10, + }, + }, + { + modifiers: {size: 'medium', iconPosition: 'start'}, + styles: { + paddingInlineStart: calc.multiply(system.space.x1, 5), + paddingInlineEnd: system.space.x6, + }, + }, + { + modifiers: {size: 'medium', iconPosition: 'end'}, + styles: { + paddingInlineStart: system.space.x6, + paddingInlineEnd: calc.multiply(system.space.x1, 5), + }, + }, + { + modifiers: {size: 'small', iconPosition: 'only'}, + styles: { + minWidth: system.space.x8, + }, + }, + { + modifiers: {size: 'small', iconPosition: 'start'}, + styles: { + paddingInlineStart: system.space.x3, + paddingInlineEnd: system.space.x4, + }, + }, + { + modifiers: {size: 'small', iconPosition: 'end'}, + styles: { + paddingInlineStart: system.space.x4, + paddingInlineEnd: system.space.x3, + }, + }, + { + modifiers: {size: 'extraSmall', iconPosition: 'only'}, + styles: { + minWidth: system.space.x6, + }, + }, + { + modifiers: {size: 'extraSmall', iconPosition: 'start'}, + styles: { + paddingInlineStart: system.space.x2, + paddingInlineEnd: system.space.x3, + }, + }, + { + modifiers: {size: 'extraSmall', iconPosition: 'end'}, + styles: { + paddingInlineStart: system.space.x3, + paddingInlineEnd: system.space.x2, + }, + }, + ], }); -export function capitalize(string: string = '') { - return string.charAt(0).toUpperCase() + string.substring(1); -} - -export function getIconPosition( - size?: keyof typeof buttonModifiers.size, - iconPosition?: IconPositions, - children?: React.ReactNode -): keyof typeof buttonModifiers.iconPosition { - return `${size}${capitalize(iconPosition)}` as keyof typeof buttonModifiers.iconPosition; -} - /** - * The base button which all other buttons are built. + * The base button which which is the foundation of all Button variants (`PrimaryButton`, + * `SecondaryButton`, `TertiaryButton`, `DeleteButton`, `ToolbarIconButton` and `ToolbarDropdownButton`). */ export const BaseButton = createComponent('button')({ displayName: 'BaseButton', @@ -330,16 +390,12 @@ export const BaseButton = createComponent('button')({ ref={ref} type="button" {...mergeStyles(elemProps, [ - baseButtonStyles, - buttonModifiers({ - size: size, - iconPosition: getIconPosition(size, iconPosition, children), - }), - buttonVars.default(colors?.default || {}), - buttonVars.focus(colors?.focus || {}), - buttonVars.hover(colors?.hover || {}), - buttonVars.active(colors?.active || {}), - buttonVars.disabled(colors?.disabled || {}), + buttonStencil({size, iconPosition}), + buttonColorPropVars.default(colors?.default || {}), + buttonColorPropVars.focus(colors?.focus || {}), + buttonColorPropVars.hover(colors?.hover || {}), + buttonColorPropVars.active(colors?.active || {}), + buttonColorPropVars.disabled(colors?.disabled || {}), ])} > {children} diff --git a/modules/react/button/lib/Button.tsx b/modules/react/button/lib/Button.tsx index 859b663522..cb7e181572 100644 --- a/modules/react/button/lib/Button.tsx +++ b/modules/react/button/lib/Button.tsx @@ -56,10 +56,7 @@ export const Button = createComponent('button')({ )} {children && {children}} - {icon && baseIconPosition === 'only' && ( - - )} - {icon && baseIconPosition === 'end' && ( + {icon && baseIconPosition && ['only', 'end'].includes(baseIconPosition) && ( )} diff --git a/modules/react/button/lib/DeleteButton.tsx b/modules/react/button/lib/DeleteButton.tsx index 43faec85e3..c44882c8f0 100644 --- a/modules/react/button/lib/DeleteButton.tsx +++ b/modules/react/button/lib/DeleteButton.tsx @@ -1,12 +1,12 @@ import * as React from 'react'; -import {buttonVars} from './BaseButton'; +import {buttonStencil} from './BaseButton'; import {createComponent} from '@workday/canvas-kit-react/common'; -import {createStyles} from '@workday/canvas-kit-styling'; -import {mergeStyles} from '@workday/canvas-kit-react/layout'; -import {base, brand, system} from '@workday/canvas-tokens-web'; +import {createStencil} from '@workday/canvas-kit-styling'; +import {brand, system} from '@workday/canvas-tokens-web'; import {Button, ButtonProps} from './Button'; -import {systemIconStencil} from '../../icon'; +import {systemIconStencil} from '@workday/canvas-kit-react/icon'; +import {mergeStyles} from '@workday/canvas-kit-react/layout'; /** * Extends all the style properties from Box to our buttons as well as props from ButtonProps. @@ -15,50 +15,54 @@ import {systemIconStencil} from '../../icon'; */ export interface DeleteButtonProps extends ButtonProps {} -const deleteStyles = createStyles({ - [buttonVars.default.background]: brand.error.base, - [buttonVars.default.border]: 'transparent', - [buttonVars.default.borderRadius]: system.shape.round, - [buttonVars.default.label]: brand.error.accent, - [systemIconStencil.vars.color]: brand.error.accent, - '&:focus-visible, &.focus': { - [buttonVars.focus.background]: brand.error.base, - [buttonVars.focus.border]: 'transparent', - [buttonVars.focus.label]: brand.error.accent, - [systemIconStencil.vars.color]: brand.error.accent, - [buttonVars.focus.boxShadowInner]: base.frenchVanilla100, - [buttonVars.focus.boxShadowOuter]: brand.common.focusOutline, - }, - '&:hover, &.hover': { - [buttonVars.hover.background]: brand.error.dark, - [buttonVars.hover.border]: 'transparent', - [buttonVars.hover.label]: brand.error.accent, - [systemIconStencil.vars.color]: brand.error.accent, - }, - '&:active, &.active': { - [buttonVars.active.background]: brand.error.darkest, - [buttonVars.active.border]: 'transparent', - [buttonVars.active.label]: brand.error.accent, - [systemIconStencil.vars.color]: brand.error.accent, - }, - '&:disabled, &.disabled': { - [buttonVars.disabled.background]: brand.error.base, - [buttonVars.disabled.label]: brand.error.accent, +const deleteButtonStencil = createStencil({ + extends: buttonStencil, + base: { + // Base Styles + [buttonStencil.vars.background]: brand.error.base, + [buttonStencil.vars.borderRadius]: system.shape.round, + [buttonStencil.vars.label]: brand.error.accent, [systemIconStencil.vars.color]: brand.error.accent, - [buttonVars.disabled.opacity]: '0.4', + // Focus Styles + '&:focus-visible, &.focus': { + [buttonStencil.vars.background]: brand.error.base, + [buttonStencil.vars.label]: brand.error.accent, + [systemIconStencil.vars.color]: brand.error.accent, + [buttonStencil.vars.boxShadowInner]: system.color.fg.inverse, + [buttonStencil.vars.boxShadowOuter]: brand.common.focusOutline, + }, + // Hover Styles + '&:hover, &.hover': { + [buttonStencil.vars.background]: brand.error.dark, + [buttonStencil.vars.label]: brand.error.accent, + [systemIconStencil.vars.color]: brand.error.accent, + }, + // Active Styles + '&:active, &.active': { + [buttonStencil.vars.background]: brand.error.darkest, + [buttonStencil.vars.label]: brand.error.accent, + [systemIconStencil.vars.color]: brand.error.accent, + }, + // Disabled Styles + '&:disabled, &.disabled': { + [buttonStencil.vars.background]: brand.error.base, + [buttonStencil.vars.label]: brand.error.accent, + [systemIconStencil.vars.color]: brand.error.accent, + [buttonStencil.vars.opacity]: system.opacity.disabled, + }, }, }); /** * Use sparingly for destructive actions that will result in data loss, can’t be undone, or will * have significant consequences. They commonly appear in confirmation dialogs as the final - * confirmation before deleting. + * confirmation before being deleted. */ export const DeleteButton = createComponent('button')({ displayName: 'DeleteButton', - Component: ({children, size, ...elemProps}: DeleteButtonProps, ref, Element) => { + Component: ({children, ...elemProps}: DeleteButtonProps, ref, Element) => { return ( - ); diff --git a/modules/react/button/lib/PrimaryButton.tsx b/modules/react/button/lib/PrimaryButton.tsx index b5f27ce3dc..a1bc7ae757 100644 --- a/modules/react/button/lib/PrimaryButton.tsx +++ b/modules/react/button/lib/PrimaryButton.tsx @@ -1,12 +1,12 @@ import * as React from 'react'; -import {buttonVars} from './BaseButton'; import {createComponent} from '@workday/canvas-kit-react/common'; -import {mergeStyles} from '@workday/canvas-kit-react/layout'; import {systemIconStencil} from '@workday/canvas-kit-react/icon'; -import {createStyles, createModifiers} from '@workday/canvas-kit-styling'; -import {base, brand, system} from '@workday/canvas-tokens-web'; +import {createStencil} from '@workday/canvas-kit-styling'; +import {brand, system} from '@workday/canvas-tokens-web'; +import {buttonStencil} from './BaseButton'; import {Button, ButtonProps} from './Button'; +import {mergeStyles} from '@workday/canvas-kit-react/layout'; /** * Extends all the style properties from Box to our buttons as well as props from ButtonProps. @@ -20,71 +20,78 @@ export interface PrimaryButtonProps extends ButtonProps { variant?: 'inverse'; } -const primaryStyles = createStyles({ - [buttonVars.default.background]: brand.primary.base, - [buttonVars.default.border]: 'transparent', - [buttonVars.default.borderRadius]: system.shape.round, - [buttonVars.default.label]: brand.primary.accent, - [systemIconStencil.vars.color]: brand.primary.accent, - '&:focus-visible, &.focus': { - [buttonVars.focus.background]: brand.primary.base, - [buttonVars.focus.border]: 'transparent', - [buttonVars.focus.label]: brand.primary.accent, - [buttonVars.focus.boxShadowInner]: base.frenchVanilla100, - [buttonVars.focus.boxShadowOuter]: brand.common.focusOutline, - [systemIconStencil.vars.color]: brand.primary.accent, - }, - '&:hover, &.hover': { - [buttonVars.hover.background]: brand.primary.dark, - [buttonVars.hover.border]: 'transparent', - [buttonVars.hover.label]: brand.primary.accent, +const primaryButtonStencil = createStencil({ + extends: buttonStencil, + base: { + // Base Styles + [buttonStencil.vars.background]: brand.primary.base, + [buttonStencil.vars.borderRadius]: system.shape.round, + [buttonStencil.vars.label]: brand.primary.accent, [systemIconStencil.vars.color]: brand.primary.accent, + // Focus Styles + '&:focus-visible, &.focus': { + [buttonStencil.vars.background]: brand.primary.base, + [buttonStencil.vars.label]: brand.primary.accent, + [buttonStencil.vars.boxShadowInner]: system.color.fg.inverse, + [buttonStencil.vars.boxShadowOuter]: brand.common.focusOutline, + [systemIconStencil.vars.color]: brand.primary.accent, + }, + // Hover Styles + '&:hover, &.hover': { + [buttonStencil.vars.background]: brand.primary.dark, + [buttonStencil.vars.label]: brand.primary.accent, + [systemIconStencil.vars.color]: brand.primary.accent, + }, + // Active Styles + '&:active, &.active': { + [buttonStencil.vars.background]: brand.primary.darkest, + [buttonStencil.vars.label]: brand.primary.accent, + [systemIconStencil.vars.color]: brand.primary.accent, + }, + // Disabled Styles + '&:disabled, &.disabled': { + [buttonStencil.vars.background]: brand.primary.base, + [buttonStencil.vars.label]: brand.primary.accent, + [buttonStencil.vars.opacity]: system.opacity.disabled, + [systemIconStencil.vars.color]: brand.primary.accent, + }, }, - '&:active, &.active': { - [buttonVars.active.background]: brand.primary.darkest, - [buttonVars.active.border]: 'transparent', - [buttonVars.active.label]: brand.primary.accent, - [systemIconStencil.vars.color]: brand.primary.accent, - }, - '&:disabled, &.disabled': { - [buttonVars.disabled.background]: brand.primary.base, - [buttonVars.disabled.border]: 'transparent', - [buttonVars.disabled.label]: brand.primary.accent, - [buttonVars.disabled.opacity]: '0.4', - [systemIconStencil.vars.color]: brand.primary.accent, - }, -}); - -export const primaryButtonModifiers = createModifiers({ - variant: { - inverse: createStyles({ - [buttonVars.default.background]: base.frenchVanilla100, - [buttonVars.default.borderRadius]: system.shape.round, - [buttonVars.default.label]: base.blackPepper400, - [systemIconStencil.vars.color]: base.blackPepper400, - '&:focus-visible, &.focus': { - [buttonVars.focus.background]: base.frenchVanilla100, - [buttonVars.focus.label]: base.blackPepper400, - [buttonVars.focus.boxShadowInner]: base.blackPepper400, - [buttonVars.focus.boxShadowOuter]: base.frenchVanilla100, - [systemIconStencil.vars.color]: base.blackPepper400, - }, - '&:hover, &.hover': { - [buttonVars.hover.background]: base.soap300, - [buttonVars.hover.label]: base.blackPepper500, - [systemIconStencil.vars.color]: base.blackPepper500, - }, - '&:active, &.active': { - [buttonVars.active.background]: base.soap400, - [buttonVars.active.label]: base.blackPepper500, - [systemIconStencil.vars.color]: base.blackPepper500, - }, - '&:disabled, &.disabled': { - [buttonVars.disabled.background]: base.frenchVanilla100, - [buttonVars.disabled.label]: base.blackPepper400, - [systemIconStencil.vars.color]: base.blackPepper400, + modifiers: { + variant: { + // Inverse Styles + inverse: { + [buttonStencil.vars.background]: system.color.bg.default, + [buttonStencil.vars.borderRadius]: system.shape.round, + [buttonStencil.vars.label]: system.color.fg.strong, + [systemIconStencil.vars.color]: system.color.fg.strong, + // Focus Styles + '&:focus-visible, &.focus': { + [buttonStencil.vars.background]: system.color.bg.default, + [buttonStencil.vars.label]: system.color.fg.strong, + [buttonStencil.vars.boxShadowInner]: system.color.fg.strong, + [buttonStencil.vars.boxShadowOuter]: system.color.fg.inverse, + [systemIconStencil.vars.color]: system.color.fg.strong, + }, + // Hover Styles + '&:hover, &.hover': { + [buttonStencil.vars.background]: system.color.bg.alt.default, + [buttonStencil.vars.label]: system.color.fg.stronger, + [systemIconStencil.vars.color]: system.color.fg.stronger, + }, + // Active Styles + '&:active, &.active': { + [buttonStencil.vars.background]: system.color.bg.alt.strong, + [buttonStencil.vars.label]: system.color.fg.stronger, + [systemIconStencil.vars.color]: system.color.fg.stronger, + }, + // Disabled Styles + '&:disabled, &.disabled': { + [buttonStencil.vars.background]: system.color.bg.default, + [buttonStencil.vars.label]: system.color.fg.strong, + [systemIconStencil.vars.color]: system.color.fg.strong, + }, }, - }), + }, }, }); @@ -92,11 +99,7 @@ export const PrimaryButton = createComponent('button')({ displayName: 'PrimaryButton', Component: ({children, variant, ...elemProps}: PrimaryButtonProps, ref, Element) => { return ( - ); diff --git a/modules/react/button/lib/SecondaryButton.tsx b/modules/react/button/lib/SecondaryButton.tsx index 6048afe4b5..217504538e 100644 --- a/modules/react/button/lib/SecondaryButton.tsx +++ b/modules/react/button/lib/SecondaryButton.tsx @@ -1,12 +1,12 @@ import * as React from 'react'; -import {buttonVars} from './BaseButton'; +import {buttonStencil} from './BaseButton'; import {createComponent} from '@workday/canvas-kit-react/common'; -import {mergeStyles} from '@workday/canvas-kit-react/layout'; -import {createStyles, createModifiers} from '@workday/canvas-kit-styling'; -import {base, brand, system} from '@workday/canvas-tokens-web'; +import {createStencil} from '@workday/canvas-kit-styling'; +import {brand, system} from '@workday/canvas-tokens-web'; import {Button, ButtonProps} from './Button'; -import {systemIconStencil} from '../../icon'; +import {systemIconStencil} from '@workday/canvas-kit-react/icon'; +import {mergeStyles} from '@workday/canvas-kit-react/layout'; /** * Extends all the style properties from Box to our buttons as well as props from ButtonProps. @@ -20,85 +20,87 @@ export interface SecondaryButtonProps extends ButtonProps { variant?: 'inverse'; } -const secondaryStyles = createStyles({ - // Default Styles - [buttonVars.default.background]: 'transparent', - [buttonVars.default.border]: base.blackPepper400, - [buttonVars.default.borderRadius]: system.shape.round, - [buttonVars.default.label]: base.blackPepper400, - [systemIconStencil.vars.color]: base.blackPepper400, - // Focus Styles - '&:focus-visible, &.focus': { - [buttonVars.focus.background]: 'transparent', - [buttonVars.focus.border]: base.blackPepper400, - [buttonVars.focus.label]: base.blackPepper400, - [buttonVars.focus.boxShadowInner]: base.frenchVanilla100, - [buttonVars.focus.boxShadowOuter]: brand.common.focusOutline, - [systemIconStencil.vars.color]: base.blackPepper400, - }, - // Hover Styles - '&:hover, &.hover': { - [buttonVars.hover.background]: base.blackPepper400, - [buttonVars.hover.border]: base.blackPepper400, - [buttonVars.hover.label]: brand.primary.accent, - [systemIconStencil.vars.color]: brand.primary.accent, - }, - // Active Styles - '&:active, &.active': { - [buttonVars.active.background]: base.blackPepper500, - [buttonVars.active.border]: base.blackPepper500, - [buttonVars.active.label]: brand.primary.accent, - [systemIconStencil.vars.color]: brand.primary.accent, - }, - // Disabled Styles - '&:disabled, &.disabled': { - [buttonVars.disabled.background]: 'transparent', - [buttonVars.disabled.border]: base.blackPepper400, - [buttonVars.disabled.label]: base.blackPepper400, - [buttonVars.disabled.opacity]: '0.4', - [systemIconStencil.vars.color]: base.blackPepper400, +const secondaryButtonStencil = createStencil({ + extends: buttonStencil, + base: { + // Base Styles + [buttonStencil.vars.background]: 'transparent', + [buttonStencil.vars.border]: system.color.border.contrast.default, + [buttonStencil.vars.borderRadius]: system.shape.round, + [buttonStencil.vars.label]: system.color.fg.strong, + [systemIconStencil.vars.color]: system.color.fg.strong, + // Focus Styles + '&:focus-visible, &.focus': { + [buttonStencil.vars.background]: 'transparent', + [buttonStencil.vars.border]: system.color.border.contrast.default, + [buttonStencil.vars.label]: system.color.fg.strong, + [buttonStencil.vars.boxShadowInner]: system.color.fg.inverse, + [buttonStencil.vars.boxShadowOuter]: brand.common.focusOutline, + [systemIconStencil.vars.color]: system.color.fg.strong, + }, + // Hover Styles + '&:hover, &.hover': { + [buttonStencil.vars.background]: system.color.bg.contrast.default, + [buttonStencil.vars.border]: system.color.border.contrast.default, + [buttonStencil.vars.label]: brand.primary.accent, + [systemIconStencil.vars.color]: brand.primary.accent, + }, + // Active Styles + '&:active, &.active': { + [buttonStencil.vars.background]: system.color.bg.contrast.strong, + [buttonStencil.vars.border]: system.color.border.contrast.strong, + [buttonStencil.vars.label]: brand.primary.accent, + [systemIconStencil.vars.color]: brand.primary.accent, + }, + // Disabled Styles + '&:disabled, &.disabled': { + [buttonStencil.vars.background]: 'transparent', + [buttonStencil.vars.border]: system.color.border.contrast.default, + [buttonStencil.vars.label]: system.color.fg.strong, + [buttonStencil.vars.opacity]: system.opacity.disabled, + [systemIconStencil.vars.color]: system.color.fg.strong, + }, }, -}); - -export const secondaryButtonModifiers = createModifiers({ - variant: { - inverse: createStyles({ - // Default Styles - [buttonVars.default.background]: 'transparent', - [buttonVars.default.border]: base.frenchVanilla100, - [buttonVars.default.label]: base.frenchVanilla100, - [systemIconStencil.vars.color]: base.frenchVanilla100, - // Focus Styles - '&:focus-visible, &.focus': { - [buttonVars.focus.background]: base.frenchVanilla100, - [buttonVars.focus.border]: base.frenchVanilla100, - [buttonVars.focus.label]: base.blackPepper400, - [buttonVars.focus.boxShadowInner]: base.blackPepper400, - [buttonVars.focus.boxShadowOuter]: base.frenchVanilla100, - [systemIconStencil.vars.color]: base.blackPepper400, - }, - // Hover Styles - '&:hover, &.hover': { - [buttonVars.hover.background]: base.soap300, - [buttonVars.hover.border]: base.soap300, - [buttonVars.hover.label]: base.blackPepper500, - [systemIconStencil.vars.color]: base.blackPepper500, - }, - // Active Styles - '&:active, &.active': { - [buttonVars.active.background]: base.soap400, - [buttonVars.active.border]: base.soap400, - [buttonVars.active.label]: base.blackPepper500, - [systemIconStencil.vars.color]: base.blackPepper500, - }, - // Disabled Styles - '&:disabled, &.disabled': { - [buttonVars.disabled.background]: 'transparent', - [buttonVars.disabled.border]: base.frenchVanilla100, - [buttonVars.disabled.label]: base.frenchVanilla100, - [systemIconStencil.vars.color]: base.frenchVanilla100, + modifiers: { + variant: { + inverse: { + // Default Styles + [buttonStencil.vars.background]: 'transparent', + [buttonStencil.vars.border]: system.color.border.inverse, + [buttonStencil.vars.label]: system.color.fg.inverse, + [systemIconStencil.vars.color]: system.color.fg.inverse, + // Focus Styles + '&:focus-visible, &.focus': { + [buttonStencil.vars.background]: system.color.bg.default, + [buttonStencil.vars.border]: 'transparent', + [buttonStencil.vars.label]: system.color.fg.strong, + [buttonStencil.vars.boxShadowInner]: system.color.fg.strong, + [buttonStencil.vars.boxShadowOuter]: system.color.fg.inverse, + [systemIconStencil.vars.color]: system.color.fg.strong, + }, + // Hover Styles + '&:hover, &.hover': { + [buttonStencil.vars.background]: system.color.bg.alt.default, + [buttonStencil.vars.border]: 'transparent', + [buttonStencil.vars.label]: system.color.fg.stronger, + [systemIconStencil.vars.color]: system.color.fg.stronger, + }, + // Active Styles + '&:active, &.active': { + [buttonStencil.vars.background]: system.color.bg.alt.strong, + [buttonStencil.vars.border]: 'transparent', + [buttonStencil.vars.label]: system.color.fg.stronger, + [systemIconStencil.vars.color]: system.color.fg.stronger, + }, + // Disabled Styles + '&:disabled, &.disabled': { + [buttonStencil.vars.background]: 'transparent', + [buttonStencil.vars.border]: system.color.border.inverse, + [buttonStencil.vars.label]: system.color.fg.inverse, + [systemIconStencil.vars.color]: system.color.fg.inverse, + }, }, - }), + }, }, }); @@ -106,11 +108,7 @@ export const SecondaryButton = createComponent('button')({ displayName: 'SecondaryButton', Component: ({children, variant, ...elemProps}: SecondaryButtonProps, ref, Element) => { return ( - ); diff --git a/modules/react/button/lib/TertiaryButton.tsx b/modules/react/button/lib/TertiaryButton.tsx index 4b98cb5503..3c5115634f 100644 --- a/modules/react/button/lib/TertiaryButton.tsx +++ b/modules/react/button/lib/TertiaryButton.tsx @@ -1,13 +1,12 @@ import * as React from 'react'; -import {buttonVars, getIconPosition} from './BaseButton'; +import {buttonStencil} from './BaseButton'; import {createComponent, focusRing} from '@workday/canvas-kit-react/common'; -import {createStyles, createModifiers} from '@workday/canvas-kit-styling'; -import {mergeStyles} from '@workday/canvas-kit-react/layout'; -import {system, brand, base} from '@workday/canvas-tokens-web'; -import {borderRadius, space} from '@workday/canvas-kit-react/tokens'; +import {calc, createStencil} from '@workday/canvas-kit-styling'; +import {system, brand} from '@workday/canvas-tokens-web'; import {Button, ButtonProps} from './Button'; -import {systemIconStencil} from '../../icon'; +import {systemIconStencil} from '@workday/canvas-kit-react/icon'; +import {mergeStyles} from '@workday/canvas-kit-react/layout'; /** * Extends all the style properties from Box to our buttons as well as props from ButtonProps. @@ -22,133 +21,215 @@ export interface TertiaryButtonProps extends ButtonProps { isThemeable?: boolean; } -const tertiaryStyles = createStyles({ - paddingInline: system.space.x2, - minWidth: 'auto', - textDecoration: 'underline', - border: 0, - [buttonVars.default.background]: 'transparent', - [buttonVars.default.border]: 'transparent', - [buttonVars.default.borderRadius]: system.shape.x1, - [buttonVars.default.label]: brand.primary.base, - [systemIconStencil.vars.color]: base.blackPepper400, - '&:focus-visible, &.focus': { - [buttonVars.focus.background]: 'transparent', - [buttonVars.focus.border]: 'transparent', - [buttonVars.focus.label]: brand.primary.base, - [buttonVars.focus.boxShadowInner]: brand.common.focusOutline, - [buttonVars.focus.boxShadowOuter]: brand.common.focusOutline, - [systemIconStencil.vars.color]: base.blackPepper400, - ...focusRing({ - width: 2, - separation: 0, - innerColor: base.frenchVanilla100, - outerColor: brand.common.focusOutline, - }), - }, - '&:hover, &.hover': { - [buttonVars.hover.background]: base.soap300, - [buttonVars.hover.border]: 'transparent', - [buttonVars.hover.label]: brand.primary.dark, - [systemIconStencil.vars.color]: base.blackPepper400, - }, - '&:active, &.active': { - [buttonVars.active.background]: base.soap400, - [buttonVars.active.border]: 'transparent', - [buttonVars.active.label]: brand.primary.darkest, - [systemIconStencil.vars.color]: base.blackPepper500, - }, - '&:disabled, &.disabled': { - [buttonVars.disabled.background]: 'transparent', - [buttonVars.disabled.border]: 'transparent', - [buttonVars.disabled.label]: brand.primary.base, - [buttonVars.disabled.opacity]: '0.4', - }, -}); - -export const tertiaryButtonModifiers = createModifiers({ - isThemeable: { - true: createStyles({ +const tertiaryButtonStencil = createStencil({ + extends: buttonStencil, + // Base Styles + base: { + paddingInline: system.space.x2, + minWidth: 'auto', + textDecoration: 'underline', + border: system.space.zero, + [buttonStencil.vars.background]: 'transparent', + [buttonStencil.vars.borderRadius]: system.shape.x1, + [buttonStencil.vars.label]: brand.primary.base, + [systemIconStencil.vars.color]: brand.primary.base, + // Focus Styles + '&:focus-visible, &.focus': { + [buttonStencil.vars.background]: 'transparent', + [buttonStencil.vars.label]: brand.primary.base, + [buttonStencil.vars.boxShadowInner]: brand.common.focusOutline, + [buttonStencil.vars.boxShadowOuter]: brand.common.focusOutline, + [systemIconStencil.vars.color]: brand.primary.base, + ...focusRing({ + width: 2, + separation: 0, + innerColor: system.color.fg.inverse, + outerColor: brand.common.focusOutline, + }), + }, + // Hover Styles + '&:hover, &.hover': { + [buttonStencil.vars.background]: system.color.bg.alt.default, + [buttonStencil.vars.label]: brand.primary.dark, + [systemIconStencil.vars.color]: brand.primary.dark, + }, + // Active Styles + '&:active, &.active': { + [buttonStencil.vars.background]: system.color.bg.alt.strong, + [buttonStencil.vars.label]: brand.primary.darkest, + [systemIconStencil.vars.color]: brand.primary.darkest, + }, + // Disabled Styles + '&:disabled, &.disabled': { + [buttonStencil.vars.background]: 'transparent', + [buttonStencil.vars.label]: brand.primary.base, + [buttonStencil.vars.opacity]: system.opacity.disabled, [systemIconStencil.vars.color]: brand.primary.base, - '&:focus-visible, &.focus': { + }, + }, + modifiers: { + // IconPosition Styles + iconPosition: { + only: { + padding: 0, + borderRadius: system.shape.round, + [systemIconStencil.vars.color]: system.color.fg.strong, + '&:focus-visible, &.focus': { + [systemIconStencil.vars.color]: system.color.fg.strong, + }, + '&:hover, &.hover': { + [systemIconStencil.vars.color]: system.color.fg.strong, + }, + '&:active, &.active': { + [systemIconStencil.vars.color]: system.color.fg.stronger, + }, + '&:disabled, &.disabled': { + [systemIconStencil.vars.color]: system.color.fg.strong, + }, + }, + start: {}, + end: {}, + }, + isThemeable: { + true: { [systemIconStencil.vars.color]: brand.primary.base, + '&:focus-visible, &.focus': { + [systemIconStencil.vars.color]: brand.primary.base, + }, + '&:hover, &.hover': { + [systemIconStencil.vars.color]: brand.primary.dark, + }, + '&:active, &.active': { + [systemIconStencil.vars.color]: brand.primary.darkest, + }, + '&:disabled, &.disabled': { + [systemIconStencil.vars.color]: brand.primary.base, + }, }, - '&:hover, &.hover': { - [systemIconStencil.vars.color]: brand.primary.dark, + }, + variant: { + // Inverse Styles + inverse: { + [buttonStencil.vars.background]: 'transparent', + [buttonStencil.vars.label]: system.color.fg.inverse, + [systemIconStencil.vars.color]: system.color.fg.inverse, + // Focus Styles + '&:focus-visible, &.focus': { + [buttonStencil.vars.background]: system.color.bg.default, + [buttonStencil.vars.label]: system.color.fg.strong, + [systemIconStencil.vars.color]: system.color.fg.strong, + ...focusRing({ + inset: 'inner', + width: 2, + separation: 2, + innerColor: system.color.fg.strong, + outerColor: system.color.fg.inverse, + }), + }, + // Hover Styles + '&:hover, &.hover': { + [buttonStencil.vars.background]: system.color.bg.default, + [buttonStencil.vars.label]: system.color.fg.strong, + [systemIconStencil.vars.color]: system.color.fg.strong, + }, + // Active Styles + '&:active, &.active': { + [buttonStencil.vars.background]: system.color.bg.alt.soft, + [buttonStencil.vars.label]: system.color.fg.strong, + [systemIconStencil.vars.color]: system.color.fg.strong, + }, + // Disabled Styles + '&:disabled, &.disabled': { + [buttonStencil.vars.background]: 'transparent', + [buttonStencil.vars.label]: system.color.fg.inverse, + [systemIconStencil.vars.color]: system.color.fg.inverse, + }, }, - '&:active, &.active': { - [systemIconStencil.vars.color]: brand.primary.darkest, + }, + }, + // Compound Modifier Styles + compound: [ + { + modifiers: {size: 'large', iconPosition: 'only'}, + styles: { + minWidth: calc.multiply(system.space.x4, 3), }, - '&:disabled, &.disabled': { - [systemIconStencil.vars.color]: brand.primary.base, + }, + { + modifiers: {size: 'large', iconPosition: 'start'}, + styles: { + paddingInlineStart: system.space.x2, + paddingInlineEnd: system.space.x3, }, - }), - }, - variant: { - inverse: createStyles({ - [buttonVars.default.background]: 'transparent', - [buttonVars.default.border]: 'transparent', - [buttonVars.default.label]: base.frenchVanilla100, - [systemIconStencil.vars.color]: base.frenchVanilla100, - '&:focus-visible, &.focus': { - [buttonVars.focus.background]: base.frenchVanilla100, - [buttonVars.focus.border]: 'transparent', - [buttonVars.focus.label]: base.blackPepper400, - [systemIconStencil.vars.color]: base.blackPepper400, - ...focusRing({ - inset: 'inner', - width: 2, - separation: 2, - innerColor: base.blackPepper400, - outerColor: base.frenchVanilla100, - }), + }, + { + modifiers: {size: 'large', iconPosition: 'end'}, + styles: { + paddingInlineStart: system.space.x3, + paddingInlineEnd: system.space.x2, + }, + }, + { + modifiers: {size: 'medium', iconPosition: 'only'}, + styles: { + minWidth: system.space.x10, }, - '&:hover, &.hover': { - [buttonVars.hover.background]: base.frenchVanilla100, - [buttonVars.hover.border]: 'transparent', - [buttonVars.hover.label]: base.blackPepper400, - [systemIconStencil.vars.color]: base.blackPepper400, + }, + { + modifiers: {size: 'medium', iconPosition: 'start'}, + styles: { + paddingInlineStart: system.space.x2, + paddingInlineEnd: system.space.x3, }, - '&:active, &.active': { - [buttonVars.active.background]: base.soap200, - [buttonVars.active.border]: 'transparent', - [buttonVars.active.label]: base.blackPepper400, - [systemIconStencil.vars.color]: base.blackPepper400, + }, + { + modifiers: {size: 'medium', iconPosition: 'end'}, + styles: { + paddingInlineStart: system.space.x3, + paddingInlineEnd: system.space.x2, }, - '&:disabled, &.disabled': { - // Disabled Styles - [buttonVars.disabled.background]: 'transparent', - [buttonVars.disabled.border]: base.frenchVanilla100, - [buttonVars.disabled.label]: base.frenchVanilla100, - [systemIconStencil.vars.color]: base.frenchVanilla100, + }, + { + modifiers: {size: 'small', iconPosition: 'only'}, + styles: { + minWidth: system.space.x8, }, - }), - }, - iconPosition: { - largeOnly: createStyles({ - borderRadius: borderRadius.circle, - padding: '0', - minWidth: `calc(${system.space.x4} * 3)`, - }), - largeStart: createStyles({ - paddingInlineStart: space.xxs, - paddingInlineEnd: space.xs, - }), - largeEnd: createStyles({paddingInlineStart: space.xs, paddingInlineEnd: space.xxs}), - mediumOnly: createStyles({padding: '0', minWidth: space.xl, borderRadius: borderRadius.circle}), - mediumStart: createStyles({paddingInlineStart: space.xxs, paddingInlineEnd: space.xs}), - mediumEnd: createStyles({paddingInlineStart: space.xs, paddingInlineEnd: space.xxs}), - smallOnly: createStyles({padding: '0', minWidth: space.l, borderRadius: borderRadius.circle}), - smallStart: createStyles({paddingInlineStart: space.xxs, paddingInlineEnd: space.xs}), - smallEnd: createStyles({paddingInlineStart: space.xs, paddingInlineEnd: space.xxs}), - extraSmallOnly: createStyles({ - padding: '0', - minWidth: space.m, - borderRadius: borderRadius.circle, - }), - extraSmallStart: createStyles({paddingInlineStart: space.xxxs, paddingInlineEnd: space.xxs}), - extraSmallEnd: createStyles({paddingInlineStart: space.xxs, paddingInlineEnd: space.xxxs}), - }, + }, + { + modifiers: {size: 'small', iconPosition: 'start'}, + styles: { + paddingInlineStart: system.space.x2, + paddingInlineEnd: system.space.x3, + }, + }, + { + modifiers: {size: 'small', iconPosition: 'end'}, + styles: { + paddingInlineStart: system.space.x3, + paddingInlineEnd: system.space.x2, + }, + }, + { + modifiers: {size: 'extraSmall', iconPosition: 'only'}, + styles: { + minWidth: system.space.x6, + }, + }, + { + modifiers: {size: 'extraSmall', iconPosition: 'start'}, + styles: { + paddingInlineStart: system.space.x1, + paddingInlineEnd: system.space.x2, + }, + }, + { + modifiers: {size: 'extraSmall', iconPosition: 'end'}, + styles: { + paddingInlineStart: system.space.x2, + paddingInlineEnd: system.space.x1, + }, + }, + ], }); export const TertiaryButton = createComponent('button')({ @@ -157,8 +238,8 @@ export const TertiaryButton = createComponent('button')({ { children, icon, - size = 'medium', isThemeable, + size = 'medium', variant, iconPosition, ...elemProps @@ -179,16 +260,17 @@ export const TertiaryButton = createComponent('button')({ as={Element} ref={ref} icon={icon} - iconPosition={iconPosition} size={size} - {...mergeStyles(elemProps, [ - tertiaryStyles, - tertiaryButtonModifiers({ + iconPosition={iconPosition} + {...mergeStyles( + elemProps, + tertiaryButtonStencil({ + variant, + size, isThemeable: (isThemeable || baseIconPosition !== 'only') as any, - variant: variant, - iconPosition: getIconPosition(size, baseIconPosition), - }), - ])} + iconPosition: baseIconPosition, + }) + )} > {children} diff --git a/modules/react/button/stories/visual-testing/stories_ColorsOverride.tsx b/modules/react/button/stories/visual-testing/stories_ColorsOverride.tsx new file mode 100644 index 0000000000..921334e4d4 --- /dev/null +++ b/modules/react/button/stories/visual-testing/stories_ColorsOverride.tsx @@ -0,0 +1,75 @@ +import {CSSObject} from '@emotion/react'; +import React from 'react'; +import {PartialEmotionCanvasTheme} from '@workday/canvas-kit-react/common'; +import { + ComponentStatesTable, + permutateProps, + StaticStates, +} from '@workday/canvas-kit-react/testing'; +import {withSnapshotsEnabled, customColorTheme} from '../../../../../utils/storybook'; +import { + PrimaryButton, + SecondaryButton, + TertiaryButton, + DeleteButton, + ToolbarDropdownButton, + ToolbarIconButton, +} from '@workday/canvas-kit-react/button'; +import {stateTableColumnProps} from './utils'; +import {playCircleIcon} from '@workday/canvas-system-icons-web'; +import {Flex} from '@workday/canvas-kit-react/layout'; + +export default withSnapshotsEnabled({ + title: 'Testing/Buttons/Button/Color Overrides', +}); + +const ColorOverrideContainer = props => { + return ( + + {props.children} + + ); +}; + +const ColorOverrideStates = (props: {theme?: PartialEmotionCanvasTheme}) => ( + + (props.iconPosition && props.icon) || (!props.icon && !props.iconPosition) + )} + columnProps={stateTableColumnProps} + > + {props => ( + <> + + Test + + Test + + Test + + Test + + + + + + + )} + + +); + +export const ColorOverrideThemedStates = () => ( + +); diff --git a/package.json b/package.json index 31763ce5e1..b937496c99 100644 --- a/package.json +++ b/package.json @@ -119,9 +119,9 @@ "cypress:run": "cypress run" }, "lint-staged": { - "*.{ts,tsx}": "yarn format", - "*.json": "node utils/check-mismatched-dependencies.js", - "yarn.lock": "node utils/check-lockfile.js" + "*.{ts,tsx}": "yarn format", + "*.json": "node utils/check-mismatched-dependencies.js", + "yarn.lock": "node utils/check-lockfile.js" }, "workspaces": [ "modules/**"