UNPKG

@workday/canvas-kit-react

Version:

The parent module that contains all Workday Canvas Kit React components

106 lines (95 loc) 3.48 kB
import {Theme, CSSObject} from '@emotion/react'; import {cssVar} from '@workday/canvas-kit-styling'; import {base, brand} from '@workday/canvas-tokens-web'; interface FocusRingOptions { width?: number; separation?: number; animate?: boolean; /** * Specifies where the ring(s) should be attached. * - undefined: Both "inner" and "outer" shadows outside the container. * - 'inner': "Inner" shadow inset. "Outer" shadow outside the container. * - 'outer': Both "inner" and "outer" shadows inside the container. */ inset?: 'inner' | 'outer'; innerColor?: string; outerColor?: string; } function calculateFocusRing({ width, separation, inset, innerColor, outerColor, }: Required<Omit<FocusRingOptions, 'memoize' | 'inset'>> & Pick<FocusRingOptions, 'inset'>): CSSObject { let boxShadow, innerWidth, outerWidth; if (innerColor && innerColor.startsWith('--')) { // eslint-disable-next-line no-param-reassign innerColor = cssVar(innerColor); } if (outerColor && outerColor.startsWith('--')) { // eslint-disable-next-line no-param-reassign outerColor = cssVar(outerColor); } switch (inset) { case 'outer': innerWidth = width + separation; outerWidth = separation; boxShadow = `inset 0 0 0 ${outerWidth}px ${outerColor}, inset 0 0 0 ${innerWidth}px ${innerColor}`; break; case 'inner': innerWidth = separation; outerWidth = width; boxShadow = `inset 0 0 0 ${innerWidth}px ${innerColor}, 0 0 0 ${outerWidth}px ${outerColor}`; break; default: innerWidth = separation; outerWidth = width + separation; boxShadow = `0 0 0 ${innerWidth}px ${innerColor}, 0 0 0 ${outerWidth}px ${outerColor}`; break; } return {boxShadow}; } /** * A utility to create a canvas style focus ring around your widget. * By default, this mixin will create a 2px focus ring tightly wrapped * to the container (no whitespace). * * @param width Allows the user to specify the thickness in px of the focus ring. * @param separation Allows the user to define the width in px of the whitespace * that there should be between the component and the focus ring. * @param animate Set property to false to opt out of the standard grow out of the middle animation * @param inset Determines whether or not the focus ring is inset * @param innerShadowColor Allows the user to specify the inner shadow color * @param outerShadowColor Allows the user to specify the outer shadow color * * @returns {CSSObject} the css object for the focus ring style */ /** * A utility to create a canvas style focus ring around your widget. * By default, this mixin will create a 2px focus ring tightly wrapped * to the container (no whitespace). * * @returns {CSSObject} the css object for the focus ring style */ export function focusRing(options: FocusRingOptions = {}, theme?: Theme): CSSObject { const { width = 2, separation = 0, animate = true, // hard code CSS fallbacks for dynamic styles that don't use the static style transform innerColor = cssVar(base.frenchVanilla100, 'rgba(255,255,255,1)'), outerColor = cssVar(brand.common.focusOutline, 'rgba(8,117,225,1)'), inset, } = options; const args = { width: width, separation: separation, innerColor: innerColor, outerColor: outerColor, animate, inset, }; return calculateFocusRing(args); }