Skip to content

Commit

Permalink
Style Refactor Skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
thunguyen19 committed Jan 14, 2025
1 parent b069877 commit 54842d8
Show file tree
Hide file tree
Showing 9 changed files with 258 additions and 198 deletions.
2 changes: 1 addition & 1 deletion modules/react/skeleton/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export {Skeleton} from './lib/skeleton';
export {Skeleton} from './lib/Skeleton';
Original file line number Diff line number Diff line change
@@ -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 {
/**
Expand All @@ -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')<SkeletonProps & StyledType>({
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,
},
}),
});

/**
Expand All @@ -59,11 +59,10 @@ export const Skeleton = createComponent('div')({
ref,
Element
) => (
<SkeletonAnimator ref={ref} as={Element} {...elemProps}>
<AccessibleHide>{loadingAriaLabel}</AccessibleHide>

<Element ref={ref} {...handleCsProp(elemProps, skeletonStencil())}>
<div data-part="skeleton-accessible-hide">{loadingAriaLabel}</div>
<div aria-hidden={true}>{children}</div>
</SkeletonAnimator>
</Element>
),
subComponents: {
/**
Expand Down
68 changes: 68 additions & 0 deletions modules/react/skeleton/lib/parts/SkeletonHeader.tsx
Original file line number Diff line number Diff line change
@@ -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')<SkeletonHeaderProps>({
displayName: 'Skeleton.Header',
Component: (
{width = '100%', backgroundColor, height, ...elemProps}: SkeletonHeaderProps,
ref,
Element
) => (
<SkeletonShape
ref={ref}
as={Element}
{...handleCsProp(
elemProps,
skeletonHeaderStencil({
width: typeof width === 'number' ? px2rem(width) : width,
backgroundColor: backgroundColor,
height: typeof height === 'number' ? px2rem(height) : height,
})
)}
/>
),
});
68 changes: 68 additions & 0 deletions modules/react/skeleton/lib/parts/SkeletonShape.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Element
ref={ref}
{...handleCsProp(
elemProps,
skeletonShapeStencil({
width: typeof width === 'number' ? px2rem(width) : width,
height: typeof height === 'number' ? px2rem(height) : height,
backgroundColor,
borderRadius: typeof borderRadius === 'number' ? px2rem(borderRadius) : borderRadius,
})
)}
/>
);
},
});
101 changes: 101 additions & 0 deletions modules/react/skeleton/lib/parts/SkeletonText.tsx
Original file line number Diff line number Diff line change
@@ -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')<SkeletonTextLineProps>({
displayName: 'Skeleton.TextLine',
Component: ({width, backgroundColor, ...elemProps}, ref, Element) => (
<Element
ref={ref}
{...handleCsProp(
elemProps,
skeletonTextLineStencil({
width: typeof width === 'number' ? px2rem(width) : width,
backgroundColor,
})
)}
/>
),
});

const createTextLines = (lineCount: number, backgroundColor?: string) => {
const lines = new Array(lineCount).fill(null);

return lines.map((_value, index) => (
<Line
key={index}
backgroundColor={backgroundColor}
width={index < lineCount - 1 || lineCount === 1 ? '100%' : '60%'}
/>
));
};

export const SkeletonText = createComponent('div')({
displayName: 'Skeleton.Text',
Component: ({backgroundColor, lineCount = 2, ...elemProps}: SkeletonTextProps, ref, Element) =>
lineCount <= 0 ? null : (
<Element ref={ref} {...handleCsProp(elemProps, textContainerStencil())}>
{createTextLines(lineCount, backgroundColor)}
</Element>
),
});
48 changes: 0 additions & 48 deletions modules/react/skeleton/lib/parts/skeletonHeader.tsx

This file was deleted.

Loading

0 comments on commit 54842d8

Please sign in to comment.