Skip to content

Commit b5251e8

Browse files
authored
feat: Refactor Skeleton to use our new styling utilities and new tokens (#3088)
Fixes: #2958 [category:Components] Release Note: We've updated`Skeleton` to use our new Tokens and styling utilities. The React interface has not changed, but CSS variables are now used for dynamic properties.
1 parent b069877 commit b5251e8

10 files changed

+229
-198
lines changed

modules/docs/mdx/13.0-UPGRADE-GUIDE.mdx

+13
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ any questions.
1818

1919
- [Codemod](#codemod)
2020
- [Instructions](#instructions)
21+
- [Component Updates](#component-updates)
22+
- [Styling API and CSS Tokens](#styling-api-and-css-tokens)
2123
- [Troubleshooting](#troubleshooting)
2224
- [Glossary](#glossary)
2325
- [Main](#main)
@@ -86,6 +88,17 @@ yarn remove @workday/canvas-kit-codemod
8688
> your project conventions.
8789
8890

91+
### Styling API and CSS Tokens
92+
93+
Some components have been refactored to use our new
94+
[Canvas Tokens](https://workday.github.io/canvas-tokens/?path=/docs/docs-getting-started--docs) and
95+
[styling API](https://workday.github.io/canvas-kit/?path=/docs/styling-basics--create-modifiers#createstyles-api).
96+
The React interface **has not changed**, but CSS variables are now used for dynamic properties.
97+
98+
> **Note:** These components also support our new `cs` prop for styling. Learn more about styling
99+
> with `cs` in our
100+
> [documentation](https://workday.github.io/canvas-kit/?path=/docs/styling-basics--cs-prop).
101+
89102
## Troubleshooting
90103

91104
## Glossary

modules/react/skeleton/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export {Skeleton} from './lib/skeleton';
1+
export {Skeleton} from './lib/Skeleton';

modules/react/skeleton/lib/skeleton.tsx modules/react/skeleton/lib/Skeleton.tsx

+19-20
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import * as React from 'react';
2-
import {keyframes} from '@emotion/react';
3-
import styled from '@emotion/styled';
42

5-
import {accessibleHide, createComponent, StyledType} from '@workday/canvas-kit-react/common';
3+
import {accessibleHide, createComponent} from '@workday/canvas-kit-react/common';
4+
import {createStencil, handleCsProp, keyframes} from '@workday/canvas-kit-styling';
65

7-
import {SkeletonHeader} from './parts/skeletonHeader';
8-
import {SkeletonShape} from './parts/skeletonShape';
9-
import {SkeletonText} from './parts/skeletonText';
6+
import {SkeletonHeader} from './parts/SkeletonHeader';
7+
import {SkeletonShape} from './parts/SkeletonShape';
8+
import {SkeletonText} from './parts/SkeletonText';
109

1110
export interface SkeletonProps {
1211
/**
@@ -22,21 +21,22 @@ export interface SkeletonProps {
2221
children?: React.ReactNode;
2322
}
2423

25-
const AccessibleHide = styled('div')(accessibleHide);
26-
2724
const fade = keyframes({
2825
from: {opacity: 0.4},
2926
to: {opacity: 1},
3027
});
3128

32-
const animation = `${fade} 0.8s linear infinite alternate`;
33-
34-
const SkeletonAnimator = styled('div')<SkeletonProps & StyledType>({
35-
animation,
36-
overflow: 'hidden',
37-
width: '100%',
38-
height: '100%',
39-
position: 'relative',
29+
export const skeletonStencil = createStencil({
30+
base: () => ({
31+
animation: `${fade} 0.8s linear infinite alternate`,
32+
position: 'relative',
33+
overflow: 'hidden',
34+
height: '100%',
35+
width: '100%',
36+
'& [data-part="skeleton-accessible-hide"]': {
37+
...accessibleHide,
38+
},
39+
}),
4040
});
4141

4242
/**
@@ -59,11 +59,10 @@ export const Skeleton = createComponent('div')({
5959
ref,
6060
Element
6161
) => (
62-
<SkeletonAnimator ref={ref} as={Element} {...elemProps}>
63-
<AccessibleHide>{loadingAriaLabel}</AccessibleHide>
64-
62+
<Element ref={ref} {...handleCsProp(elemProps, skeletonStencil())}>
63+
<div data-part="skeleton-accessible-hide">{loadingAriaLabel}</div>
6564
<div aria-hidden={true}>{children}</div>
66-
</SkeletonAnimator>
65+
</Element>
6766
),
6867
subComponents: {
6968
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import * as React from 'react';
2+
3+
import {createComponent} from '@workday/canvas-kit-react/common';
4+
import {
5+
createStencil,
6+
handleCsProp,
7+
px2rem,
8+
cssVar,
9+
calc,
10+
CSProps,
11+
} from '@workday/canvas-kit-styling';
12+
import {system} from '@workday/canvas-tokens-web';
13+
import {SkeletonShape} from './SkeletonShape';
14+
15+
export interface SkeletonHeaderProps extends CSProps {
16+
/**
17+
* The background color of the skeleton
18+
* @default `system.color.bg.alt.strong`
19+
*/
20+
backgroundColor?: string;
21+
/**
22+
* The height of the shape in `px` or `%`.
23+
* @default 28px
24+
*/
25+
height?: number | string;
26+
/**
27+
* The width of the shape in `px` or `%`.
28+
* @default 100%
29+
*/
30+
width?: number | string;
31+
}
32+
33+
export const skeletonHeaderStencil = createStencil({
34+
vars: {
35+
width: '',
36+
height: '',
37+
backgroundColor: '',
38+
},
39+
base: ({width, backgroundColor, height}) => ({
40+
backgroundColor: cssVar(backgroundColor, system.color.bg.alt.strong),
41+
borderRadius: 0,
42+
height: cssVar(height, calc.multiply(system.space.x1, 7)),
43+
width: width,
44+
marginBottom: system.space.x4,
45+
}),
46+
});
47+
48+
export const SkeletonHeader = createComponent('div')<SkeletonHeaderProps>({
49+
displayName: 'Skeleton.Header',
50+
Component: (
51+
{width = '100%', backgroundColor, height, ...elemProps}: SkeletonHeaderProps,
52+
ref,
53+
Element
54+
) => (
55+
<SkeletonShape
56+
ref={ref}
57+
as={Element}
58+
{...handleCsProp(
59+
elemProps,
60+
skeletonHeaderStencil({
61+
width: typeof width === 'number' ? px2rem(width) : width,
62+
backgroundColor: backgroundColor,
63+
height: typeof height === 'number' ? px2rem(height) : height,
64+
})
65+
)}
66+
/>
67+
),
68+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import * as React from 'react';
2+
3+
import {createComponent} from '@workday/canvas-kit-react/common';
4+
import {createStencil, CSProps, cssVar, handleCsProp, px2rem} from '@workday/canvas-kit-styling';
5+
import {system} from '@workday/canvas-tokens-web';
6+
7+
export interface SkeletonShapeProps extends CSProps {
8+
/**
9+
* The width of the shape in `px` or `%`.
10+
* @default 100%
11+
*/
12+
width?: number | string;
13+
/**
14+
* The height of the shape in `px` or `%`.
15+
* @default 100%
16+
*/
17+
height?: number | string;
18+
/**
19+
* The borderRadius of the shape in `px` or `%`.
20+
* @default 0
21+
*/
22+
borderRadius?: number | string;
23+
/**
24+
* The background color of the skeleton
25+
* @default `system.color.bg.alt.strong`
26+
*/
27+
backgroundColor?: string;
28+
}
29+
30+
export const skeletonShapeStencil = createStencil({
31+
vars: {
32+
width: '',
33+
height: '',
34+
borderRadius: '',
35+
backgroundColor: '',
36+
},
37+
base: ({width, height, borderRadius, backgroundColor}) => ({
38+
backgroundColor: cssVar(backgroundColor, system.color.bg.alt.strong),
39+
borderRadius: cssVar(borderRadius, system.space.zero),
40+
height: cssVar(height, '100%'),
41+
width: width,
42+
marginBottom: system.space.x4,
43+
}),
44+
});
45+
46+
export const SkeletonShape = createComponent('div')({
47+
displayName: 'Skeleton.Shape',
48+
Component: (
49+
{width = '100%', height, backgroundColor, borderRadius, ...elemProps}: SkeletonShapeProps,
50+
ref,
51+
Element
52+
) => {
53+
return (
54+
<Element
55+
ref={ref}
56+
{...handleCsProp(
57+
elemProps,
58+
skeletonShapeStencil({
59+
width: typeof width === 'number' ? px2rem(width) : width,
60+
height: typeof height === 'number' ? px2rem(height) : height,
61+
backgroundColor,
62+
borderRadius: typeof borderRadius === 'number' ? px2rem(borderRadius) : borderRadius,
63+
})
64+
)}
65+
/>
66+
);
67+
},
68+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import * as React from 'react';
2+
3+
import {createComponent} from '@workday/canvas-kit-react/common';
4+
import {createStencil, cssVar, handleCsProp, px2rem} from '@workday/canvas-kit-styling';
5+
import {system} from '@workday/canvas-tokens-web';
6+
7+
export interface SkeletonTextProps {
8+
/**
9+
* The number of "lines" that SkeletonText will display. If there is more than one line, the last line will have a width of `60%`.
10+
* @default 2
11+
*/
12+
lineCount?: number;
13+
/**
14+
* The background color of the skeleton
15+
* @default `system.color.bg.alt.strong`
16+
*/
17+
backgroundColor?: string;
18+
}
19+
20+
export const skeletonTextStencil = createStencil({
21+
vars: {
22+
backgroundColor: '',
23+
},
24+
base: ({backgroundColor}) => ({
25+
marginBottom: system.space.x6,
26+
'& [data-part="skeleton-text-lines"]': {
27+
backgroundColor: cssVar(backgroundColor, system.color.bg.alt.strong),
28+
height: px2rem(21),
29+
marginBlockEnd: system.space.x3,
30+
borderRadius: system.shape.half,
31+
width: '100%',
32+
},
33+
'& [data-part="skeleton-text-lines"]:last-child': {
34+
width: '60%',
35+
},
36+
}),
37+
});
38+
39+
export const SkeletonText = createComponent('div')({
40+
displayName: 'Skeleton.Text',
41+
Component: ({backgroundColor, lineCount = 2, ...elemProps}: SkeletonTextProps, ref, Element) => {
42+
const lines = new Array(lineCount).fill(null);
43+
return lineCount <= 0 ? null : (
44+
<Element
45+
ref={ref}
46+
{...handleCsProp(
47+
elemProps,
48+
skeletonTextStencil({
49+
backgroundColor,
50+
})
51+
)}
52+
>
53+
{lines.map((_value, index) => (
54+
<div data-part={'skeleton-text-lines'} key={index}></div>
55+
))}
56+
</Element>
57+
);
58+
},
59+
});

modules/react/skeleton/lib/parts/skeletonHeader.tsx

-48
This file was deleted.

0 commit comments

Comments
 (0)