UNPKG

@workday/canvas-kit-react

Version:

The parent module that contains all Workday Canvas Kit React components

106 lines (105 loc) 4.14 kB
/** @jsxRuntime classic */ /** @jsx jsx */ import { jsx } from '@emotion/react'; import { borderRadius, space, type } from '@workday/canvas-kit-react/tokens'; import { createContainer, focusRing, useIsRTL } from '@workday/canvas-kit-react/common'; import { Flex } from '@workday/canvas-kit-react/layout'; import { useBannerModel, useThemedPalette } from './hooks'; import { BannerIcon } from './BannerIcon'; import { BannerLabel } from './BannerLabel'; import { BannerActionText } from './BannerActionText'; import { px2rem } from '@workday/canvas-kit-styling'; import { system } from '@workday/canvas-tokens-web'; const styles = { cursor: 'pointer', transition: 'background-color 120ms', outline: `${system.space.x1} solid transparent`, '&:focus-visible, &.focus': { outline: `${px2rem(4)} double transparent`, ...focusRing({ separation: 2 }), }, }; /** * `Banner` is a container component rendered as a `<button>` element that is responsible for creating * a `BannerModel` and sharing it with its subcomponents using React context. * * ```tsx * <Banner * isSticky={true} * hasError={true} * id='custom-banner-id' * onClick={() => console.log('clicked banner')} * > * {Child components} * </Banner> * ``` * * Alternatively, you may pass in a model using the hoisted model pattern. * * ```tsx * const model = useBannerModel({ * isSticky: true, * hasError: true, * id: 'custom-banner-id', * }); * * return ( * <Banner onClick={() => console.log('clicked banner')} model={model}> * {Child components} * </Banner> * ); * ``` */ export const Banner = createContainer('button')({ displayName: 'Banner', modelHook: useBannerModel, subComponents: { /** * `Banner.Icon` is a styled {@link SystemIcon}. The icon defaults to exclamationTriangleIcon or * exclamationCircleIcon when the model's hasError is true. * * ```tsx * <Banner.Icon /> * ``` */ Icon: BannerIcon, /** * `Banner.Label` is a styled {@link Flex}. This component will get an id that will be used for * the aria-describedby on the top level `<button>`. * * ```tsx * <Banner.Label>3 Warnings</Banner.Label> * ``` */ Label: BannerLabel, /** * `Banner.ActionText` is a styled {@link Box}. This component will get an id that will be used * for the aria-labelledby on the top level `<button>`. This component will be visually hidden * when the model's `isSticky` prop is set to true. * * ```tsx * <Banner.ActionText>Custom call to action</Banner.ActionText> * ``` */ ActionText: BannerActionText, }, })(({ children, ...elemProps }, Element, model) => { const palette = useThemedPalette(model.state.hasError ? 'error' : 'alert'); const themedBackgroundStyles = { '&:hover': { backgroundColor: palette.hover, }, }; const isRTL = useIsRTL(); const borderBottomLeftRadius = isRTL ? 'borderBottomRightRadius' : 'borderBottomLeftRadius'; const borderTopLeftRadius = isRTL ? 'borderTopRightRadius' : 'borderTopLeftRadius'; const borderBottomRightRadius = isRTL ? 'borderBottomLeftRadius' : 'borderBottomRightRadius'; const borderTopRightRadius = isRTL ? 'borderTopLeftRadius' : 'borderTopRightRadius'; const borderStyleProps = { [borderBottomLeftRadius]: borderRadius.m, [borderTopLeftRadius]: borderRadius.m, [borderBottomRightRadius]: model.state.isSticky ? 0 : borderRadius.m, [borderTopRightRadius]: model.state.isSticky ? 0 : borderRadius.m, }; return (jsx(Flex, { as: Element, ...type.levels.subtext.large, fontWeight: "medium", textAlign: "left", width: model.state.isSticky ? '222px' : '328px', backgroundColor: palette.normal, color: palette.contrast, padding: `${space.xxs} ${space.s}`, border: "0", display: "flex", alignItems: "center", ...borderStyleProps, css: [styles, themedBackgroundStyles], ...elemProps }, children)); });