diff --git a/modules/react/skeleton/index.ts b/modules/react/skeleton/index.ts index 70518ef655..5ed9bc842d 100644 --- a/modules/react/skeleton/index.ts +++ b/modules/react/skeleton/index.ts @@ -1 +1 @@ -export {Skeleton} from './lib/skeleton'; +export {Skeleton} from './lib/Skeleton'; diff --git a/modules/react/skeleton/lib/skeleton.tsx b/modules/react/skeleton/lib/Skeleton.tsx similarity index 71% rename from modules/react/skeleton/lib/skeleton.tsx rename to modules/react/skeleton/lib/Skeleton.tsx index 5a9942a8a3..4ddb1436aa 100644 --- a/modules/react/skeleton/lib/skeleton.tsx +++ b/modules/react/skeleton/lib/Skeleton.tsx @@ -1,12 +1,11 @@ import * as React from 'react'; -import {keyframes} from '@emotion/react'; -import styled from '@emotion/styled'; -import {accessibleHide, createComponent, StyledType} from '@workday/canvas-kit-react/common'; +import {accessibleHide, createComponent} from '@workday/canvas-kit-react/common'; +import {createStencil, handleCsProp, keyframes} from '@workday/canvas-kit-styling'; -import {SkeletonHeader} from './parts/skeletonHeader'; -import {SkeletonShape} from './parts/skeletonShape'; -import {SkeletonText} from './parts/skeletonText'; +import {SkeletonHeader} from './parts/SkeletonHeader'; +import {SkeletonShape} from './parts/SkeletonShape'; +import {SkeletonText} from './parts/SkeletonText'; export interface SkeletonProps { /** @@ -22,21 +21,22 @@ export interface SkeletonProps { children?: React.ReactNode; } -const AccessibleHide = styled('div')(accessibleHide); - const fade = keyframes({ from: {opacity: 0.4}, to: {opacity: 1}, }); -const animation = `${fade} 0.8s linear infinite alternate`; - -const SkeletonAnimator = styled('div')({ - animation, - overflow: 'hidden', - width: '100%', - height: '100%', - position: 'relative', +const skeletonStencil = createStencil({ + base: () => ({ + animation: `${fade} 0.8s linear infinite alternate`, + position: 'relative', + overflow: 'hidden', + height: '100%', + width: '100%', + '& [data-part="skeleton-accessible-hide"]': { + ...accessibleHide, + }, + }), }); /** @@ -59,11 +59,10 @@ export const Skeleton = createComponent('div')({ ref, Element ) => ( - - {loadingAriaLabel} - + +
{loadingAriaLabel}
{children}
-
+ ), subComponents: { /** diff --git a/modules/react/skeleton/lib/parts/SkeletonHeader.tsx b/modules/react/skeleton/lib/parts/SkeletonHeader.tsx new file mode 100644 index 0000000000..9de73f533b --- /dev/null +++ b/modules/react/skeleton/lib/parts/SkeletonHeader.tsx @@ -0,0 +1,68 @@ +import * as React from 'react'; + +import {createComponent} from '@workday/canvas-kit-react/common'; +import { + createStencil, + handleCsProp, + px2rem, + cssVar, + calc, + CSProps, +} from '@workday/canvas-kit-styling'; +import {system} from '@workday/canvas-tokens-web'; +import {SkeletonShape} from './SkeletonShape'; + +export interface SkeletonHeaderProps extends CSProps { + /** + * The background color of the skeleton + * @default `system.color.bg.alt.strong` + */ + backgroundColor?: string; + /** + * The height of the shape in `px` or `%`. + * @default 28px + */ + height?: number | string; + /** + * The width of the shape in `px` or `%`. + * @default 100% + */ + width?: number | string; +} + +export const skeletonHeaderStencil = createStencil({ + vars: { + width: '', + height: '', + backgroundColor: '', + }, + base: ({width, backgroundColor, height}) => ({ + backgroundColor: cssVar(backgroundColor, system.color.bg.alt.strong), + borderRadius: 0, + height: cssVar(height, calc.add(system.space.x6, '4px')), + width: width, + marginBottom: system.space.x4, + }), +}); + +export const SkeletonHeader = createComponent('div')({ + displayName: 'Skeleton.Header', + Component: ( + {width = '100%', backgroundColor, height, ...elemProps}: SkeletonHeaderProps, + ref, + Element + ) => ( + + ), +}); diff --git a/modules/react/skeleton/lib/parts/SkeletonShape.tsx b/modules/react/skeleton/lib/parts/SkeletonShape.tsx new file mode 100644 index 0000000000..3b34e559b5 --- /dev/null +++ b/modules/react/skeleton/lib/parts/SkeletonShape.tsx @@ -0,0 +1,68 @@ +import * as React from 'react'; + +import {createComponent} from '@workday/canvas-kit-react/common'; +import {createStencil, CSProps, cssVar, handleCsProp, px2rem} from '@workday/canvas-kit-styling'; +import {system} from '@workday/canvas-tokens-web'; + +export interface SkeletonShapeProps extends CSProps { + /** + * The width of the shape in `px` or `%`. + * @default 100% + */ + width?: number | string; + /** + * The height of the shape in `px` or `%`. + * @default 100% + */ + height?: number | string; + /** + * The borderRadius of the shape in `px` or `%`. + * @default 0 + */ + borderRadius?: number | string; + /** + * The background color of the skeleton + * @default `system.color.bg.alt.strong` + */ + backgroundColor?: string; +} + +const skeletonShapeStencil = createStencil({ + vars: { + width: '', + height: '', + borderRadius: '', + backgroundColor: '', + }, + base: ({width, height, borderRadius, backgroundColor}) => ({ + backgroundColor: cssVar(backgroundColor, system.color.bg.alt.strong), + borderRadius: cssVar(borderRadius, system.space.zero), + height: cssVar(height, '100%'), + width: width, + marginBottom: system.space.x4, + }), +}); + +export const SkeletonShape = createComponent('div')({ + displayName: 'Skeleton.Shape', + Component: ( + {width = '100%', height, backgroundColor, borderRadius, ...elemProps}: SkeletonShapeProps, + ref, + Element + ) => { + return ( + + ); + }, +}); diff --git a/modules/react/skeleton/lib/parts/SkeletonText.tsx b/modules/react/skeleton/lib/parts/SkeletonText.tsx new file mode 100644 index 0000000000..369a99df40 --- /dev/null +++ b/modules/react/skeleton/lib/parts/SkeletonText.tsx @@ -0,0 +1,101 @@ +import * as React from 'react'; + +import {createComponent} from '@workday/canvas-kit-react/common'; +import { + calc, + createStencil, + CSProps, + cssVar, + handleCsProp, + px2rem, +} from '@workday/canvas-kit-styling'; +import {system} from '@workday/canvas-tokens-web'; + +export interface SkeletonTextProps { + /** + * The number of "lines" that SkeletonText will display. If there is more than one line, the last line will have a width of `60%`. + * @default 2 + */ + lineCount?: number; + /** + * The background color of the skeleton + * @default `system.color.bg.alt.strong` + */ + backgroundColor?: string; +} + +export interface SkeletonTextLineProps extends CSProps { + /** + * The width of the line in `px` or `%`. + */ + width?: number | string; + /** + * The background color of the skeleton + * @default `system.color.bg.alt.strong` + */ + backgroundColor?: string; + /** + * The borderRadius of the shape in `px` or `%`. + * @default 2px + */ + borderRadius?: number | string; +} + +const skeletonTextLineStencil = createStencil({ + vars: { + width: '', + backgroundColor: '', + borderRadius: '', + }, + base: ({width, borderRadius, backgroundColor}) => ({ + backgroundColor: cssVar(backgroundColor, system.color.bg.alt.strong), + borderRadius: cssVar(borderRadius, calc.divide(system.space.x1, 2)), // borderRadius.s // 2px + height: cssVar(calc.subtract(system.space.x6, px2rem(3))), + width: width, + marginBottom: system.space.x3, + }), +}); + +const textContainerStencil = createStencil({ + base: () => ({ + marginBottom: system.space.x4, + }), +}); + +const Line = createComponent('div')({ + displayName: 'Skeleton.TextLine', + Component: ({width, backgroundColor, ...elemProps}, ref, Element) => ( + + ), +}); + +const createTextLines = (lineCount: number, backgroundColor?: string) => { + const lines = new Array(lineCount).fill(null); + + return lines.map((_value, index) => ( + + )); +}; + +export const SkeletonText = createComponent('div')({ + displayName: 'Skeleton.Text', + Component: ({backgroundColor, lineCount = 2, ...elemProps}: SkeletonTextProps, ref, Element) => + lineCount <= 0 ? null : ( + + {createTextLines(lineCount, backgroundColor)} + + ), +}); diff --git a/modules/react/skeleton/lib/parts/skeletonHeader.tsx b/modules/react/skeleton/lib/parts/skeletonHeader.tsx deleted file mode 100644 index 6aea9c0431..0000000000 --- a/modules/react/skeleton/lib/parts/skeletonHeader.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import * as React from 'react'; - -import {createComponent} from '@workday/canvas-kit-react/common'; -import {borderRadius, colors} from '@workday/canvas-kit-react/tokens'; - -import {SkeletonShape} from './skeletonShape'; - -export interface SkeletonHeaderProps { - /** - * The background color of the skeleton - * @default soap200 - */ - backgroundColor?: string; - /** - * The height of the shape in `px` or `%`. - * @default 28px - */ - height?: number | string; - /** - * The width of the shape in `px` or `%`. - * @default 100% - */ - width?: number | string; -} - -export const SkeletonHeader = createComponent('div')({ - displayName: 'Skeleton.Header', - Component: ( - { - backgroundColor = colors.soap200, - height = '28px', - width = '100%', - ...elemProps - }: SkeletonHeaderProps, - ref, - Element - ) => ( - - ), -}); diff --git a/modules/react/skeleton/lib/parts/skeletonShape.tsx b/modules/react/skeleton/lib/parts/skeletonShape.tsx deleted file mode 100644 index 40a090c726..0000000000 --- a/modules/react/skeleton/lib/parts/skeletonShape.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import * as React from 'react'; -import styled from '@emotion/styled'; - -import {createComponent, StyledType} from '@workday/canvas-kit-react/common'; -import {colors, space} from '@workday/canvas-kit-react/tokens'; - -export interface SkeletonShapeProps { - /** - * The width of the shape in `px` or `%`. - * @default 100% - */ - width?: number | string; - /** - * The height of the shape in `px` or `%`. - * @default 100% - */ - height?: number | string; - /** - * The borderRadius of the shape in `px` or `%`. - * @default 0 - */ - borderRadius?: number | string; - /** - * The background color of the skeleton - * @default soap200 - */ - backgroundColor?: string; -} - -const Shape = styled('div')( - ({backgroundColor, borderRadius, height, width}) => ({ - backgroundColor, - borderRadius, - height, - width, - marginBottom: space.s, - }) -); - -export const SkeletonShape = createComponent('div')({ - displayName: 'Skeleton.Shape', - Component: ( - { - backgroundColor = colors.soap200, - borderRadius = 0, - height = '100%', - width = '100%', - ...elemProps - }: SkeletonShapeProps, - ref, - Element - ) => ( - - ), -}); diff --git a/modules/react/skeleton/lib/parts/skeletonText.tsx b/modules/react/skeleton/lib/parts/skeletonText.tsx deleted file mode 100644 index 744ccc5c5f..0000000000 --- a/modules/react/skeleton/lib/parts/skeletonText.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import * as React from 'react'; -import styled from '@emotion/styled'; - -import {createComponent, filterOutProps, StyledType} from '@workday/canvas-kit-react/common'; -import {borderRadius, colors, space} from '@workday/canvas-kit-react/tokens'; - -const TextContainer = styled('div')({ - marginBottom: space.m, -}); - -export interface SkeletonTextProps { - /** - * The number of "lines" that SkeletonText will display. If there is more than one line, the last line will have a width of `60%`. - * @default 2 - */ - lineCount?: number; - /** - * The background color of the skeleton - * @default soap200 - */ - backgroundColor?: string; -} - -const Line = styled('div', { - shouldForwardProp: filterOutProps(['backgroundColor', 'width']), -})< - { - backgroundColor: string; - width: number | string; - } & StyledType ->(({backgroundColor, width}) => { - return { - backgroundColor, - width, - borderRadius: borderRadius.s, - height: '21px', - marginBottom: space.xs, - }; -}); - -const createTextLines = (lineCount: number, backgroundColor: string) => { - const lines = new Array(lineCount).fill(null); - - return lines.map((_value, index) => ( - - )); -}; - -export const SkeletonText = createComponent('div')({ - displayName: 'Skeleton.Text', - Component: ( - {backgroundColor = colors.soap200, lineCount = 2, ...elemProps}: SkeletonTextProps, - ref, - Element - ) => - lineCount <= 0 ? null : ( - - {createTextLines(lineCount, backgroundColor)} - - ), -}); diff --git a/modules/react/skeleton/spec/skeleton.spec.tsx b/modules/react/skeleton/spec/skeleton.spec.tsx index 8d7bde279c..ccb7523e5b 100644 --- a/modules/react/skeleton/spec/skeleton.spec.tsx +++ b/modules/react/skeleton/spec/skeleton.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import {render} from '@testing-library/react'; -import {Skeleton} from '../lib/skeleton'; +import {Skeleton} from '../lib/Skeleton'; describe('Skeleton', () => { it('should render', () => {