Skip to content

Commit 7dab7ee

Browse files
williamjstantonjosh-bagwellmanuel.carrera
authored
chore: Expandable component style refactor (#3128)
Fixes: #2954 Expandable style re-factor is needed with the new cs prop. We will need to update this component to use the new system level tokens via CSS variables. [category:Tokens] Release Note: - The `ExpandableTarget` component is now rendering the `BaseButton` component, and may have some small impact on the visual styling of the keyboard focus ring. - The `ExpandableIcon` stencil is extending the `SystemIcon` stencil, and may have had an impact on the chevron icon color. - Fixed an accessibility bug in the `Avatar` component where an `aria-label` string was rendered on a generic HTML element that did not have an explicit or implicit `role` Co-authored-by: @josh-bagwell <[email protected]> Co-authored-by: manuel.carrera <[email protected]>
1 parent 1d31c5b commit 7dab7ee

File tree

9 files changed

+157
-131
lines changed

9 files changed

+157
-131
lines changed

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ yarn remove @workday/canvas-kit-codemod
9393

9494
### Styling API and CSS Tokens
9595

96-
**PRs:** [#3101](https://github.com/Workday/canvas-kit/pull/3101), [#3088](https://github.com/Workday/canvas-kit/pull/3088), [#3114](https://github.com/Workday/canvas-kit/pull/3114), [#3119](https://github.com/Workday/canvas-kit/pull/3119), [#3120](https://github.com/Workday/canvas-kit/pull/3120), [#3164](https://github.com/Workday/canvas-kit/pull/3164)
96+
**PRs:** [#3101](https://github.com/Workday/canvas-kit/pull/3101), [#3088](https://github.com/Workday/canvas-kit/pull/3088), [#3114](https://github.com/Workday/canvas-kit/pull/3114), [#3119](https://github.com/Workday/canvas-kit/pull/3119), [#3120](https://github.com/Workday/canvas-kit/pull/3120), [#3164](https://github.com/Workday/canvas-kit/pull/3164), [#3128](https://github.com/Workday/canvas-kit/pull/3128)
9797

9898
Several components have been refactored to use our
9999
[Canvas Tokens](https://workday.github.io/canvas-tokens/?path=/docs/docs-getting-started--docs) and
@@ -106,6 +106,7 @@ The React interface **has not changed**, but CSS variables are now used for dyna
106106
107107
The following components are affected:
108108

109+
- `Expandable`
109110
- `ExternalHyperlink`
110111
- `LoadingSparkles`
111112
- `Menu`
@@ -135,7 +136,7 @@ The following components are affected:
135136

136137
**PR:** [#3119](https://github.com/Workday/canvas-kit/pull/3119)
137138

138-
- The `disabled` icon color has been updated to use `system.color.fg.disabled`. This has made the icon darker for better contrast.
139+
- The `disabled` icon color has been updated to use `system.color.fg.disabled`. This has made the icon darker for better contrast.
139140

140141
**Note:** There should be no developer impact and the visual changes are safe to accept.
141142

modules/labs-react/expandable/lib/Expandable.tsx

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import React from 'react';
22

33
import {createContainer, ExtractProps} from '@workday/canvas-kit-react/common';
4-
import {Flex} from '@workday/canvas-kit-react/layout';
4+
import {Flex, mergeStyles} from '@workday/canvas-kit-react/layout';
55

66
import {ExpandableContent} from './ExpandableContent';
77
import {ExpandableTarget} from './ExpandableTarget';
88
import {ExpandableIcon} from './ExpandableIcon';
99
import {ExpandableTitle} from './ExpandableTitle';
1010
import {ExpandableAvatar} from './ExpandableAvatar';
1111
import {useExpandableModel} from './hooks/useExpandableModel';
12+
import {createStencil} from '@workday/canvas-kit-styling';
13+
import {system} from '@workday/canvas-tokens-web';
1214

1315
export interface ExpandableProps extends ExtractProps<typeof Flex, never> {
1416
/**
@@ -18,11 +20,20 @@ export interface ExpandableProps extends ExtractProps<typeof Flex, never> {
1820
children?: React.ReactNode;
1921
}
2022

23+
export const expandableContainerStencil = createStencil({
24+
base: {
25+
display: 'flex',
26+
flexDirection: 'column',
27+
padding: system.space.x2,
28+
},
29+
});
30+
2131
/**
2232
* `Expandable` wraps an `Expandable.Target` and an `Expandable.Content`. By default, it provides a
2333
* `DisclosureModel` for its subcomponents. Alternatively, a model may be passed in using the
2434
* hoisted model pattern.
2535
*/
36+
2637
export const Expandable = createContainer('div')({
2738
displayName: 'Expandable',
2839
modelHook: useExpandableModel,
@@ -62,7 +73,5 @@ export const Expandable = createContainer('div')({
6273
Content: ExpandableContent,
6374
},
6475
})<ExpandableProps>(({children, ...elementProps}, Element) => (
65-
<Flex as={Element} flexDirection={'column'} padding={'xxs'} {...elementProps}>
66-
{children}
67-
</Flex>
76+
<Element {...mergeStyles(elementProps, expandableContainerStencil())}>{children}</Element>
6877
));

modules/labs-react/expandable/lib/ExpandableAvatar.tsx

+12-8
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
11
import React from 'react';
22

33
import {createComponent} from '@workday/canvas-kit-react/common';
4-
import {Avatar, AvatarProps} from '@workday/canvas-kit-react/avatar';
4+
import {Avatar, AvatarProps, avatarStencil} from '@workday/canvas-kit-react/avatar';
55
import {system} from '@workday/canvas-tokens-web';
6-
import {createStyles} from '@workday/canvas-kit-styling';
6+
import {createStencil} from '@workday/canvas-kit-styling';
7+
import {mergeStyles} from '@workday/canvas-kit-react/layout';
78

89
export interface ExpandableAvatarProps extends AvatarProps {}
910

10-
const expandableAvatarStyles = createStyles({
11-
marginRight: system.space.x2,
12-
flexShrink: 0,
11+
export const expandableAvatarStencil = createStencil({
12+
extends: avatarStencil,
13+
base: {
14+
marginInlineEnd: system.space.x2,
15+
flexShrink: 0,
16+
},
1317
});
1418

1519
// When the component is created, it needs to be a button element to match AvatarProps.
1620
// Once Avatar becomes a `createComponent` we can default the element type to a `div`
1721
// and the types should be properly extracted
22+
// Setting altText prop to a default empty string for decorative purposes
1823
export const ExpandableAvatar = createComponent('div')({
1924
displayName: 'Expandable.Avatar',
20-
Component: ({altText, ...elemProps}: ExpandableAvatarProps, ref, Element) => {
25+
Component: ({altText = '', ...elemProps}: ExpandableAvatarProps, ref, Element) => {
2126
return (
2227
<Avatar
23-
cs={expandableAvatarStyles}
2428
as={Element}
2529
altText={altText}
2630
ref={ref}
2731
size="medium"
28-
{...elemProps}
32+
{...mergeStyles(elemProps, expandableAvatarStencil())}
2933
/>
3034
);
3135
},
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import React from 'react';
22

3-
import {space} from '@workday/canvas-kit-react/tokens';
43
import {createSubcomponent, ExtractProps} from '@workday/canvas-kit-react/common';
5-
import {Box} from '@workday/canvas-kit-react/layout';
4+
import {Box, mergeStyles} from '@workday/canvas-kit-react/layout';
65

76
import {useExpandableContent} from './hooks/useExpandableContent';
87
import {useExpandableModel} from './hooks/useExpandableModel';
8+
import {createStencil} from '@workday/canvas-kit-styling';
9+
import {system} from '@workday/canvas-tokens-web';
910

1011
export interface ExpandableContentProps extends ExtractProps<typeof Box, never> {
1112
/**
@@ -15,18 +16,16 @@ export interface ExpandableContentProps extends ExtractProps<typeof Box, never>
1516
children?: React.ReactNode;
1617
}
1718

19+
export const expandableContentStencil = createStencil({
20+
base: {
21+
background: system.color.bg.transparent,
22+
padding: `${system.space.x4} ${system.space.x2} ${system.space.x2}`,
23+
},
24+
});
25+
1826
export const ExpandableContent = createSubcomponent('div')({
1927
modelHook: useExpandableModel,
2028
elemPropsHook: useExpandableContent,
2129
})<ExpandableContentProps>(({children, ...elementProps}, Element) => {
22-
return (
23-
<Box
24-
as={Element}
25-
background="none"
26-
padding={`${space.s} ${space.xxs} ${space.xxs}`}
27-
{...elementProps}
28-
>
29-
{children}
30-
</Box>
31-
);
30+
return <Element {...mergeStyles(elementProps, expandableContentStencil())}>{children}</Element>;
3231
});
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
11
import React from 'react';
22

3-
import {
4-
createSubcomponent,
5-
ExtractProps,
6-
filterOutProps,
7-
styled,
8-
StyledType,
9-
} from '@workday/canvas-kit-react/common';
10-
import {chevronUpIcon, chevronDownIcon} from '@workday/canvas-system-icons-web';
3+
import {createSubcomponent, ExtractProps} from '@workday/canvas-kit-react/common';
4+
import {chevronUpIcon} from '@workday/canvas-system-icons-web';
115
import {CanvasSystemIcon} from '@workday/design-assets-types';
126
import {useExpandableIcon} from './hooks/useExpandableIcon';
13-
import {SystemIcon} from '@workday/canvas-kit-react/icon';
7+
import {SystemIcon, systemIconStencil} from '@workday/canvas-kit-react/icon';
148
import {IconPositions} from '@workday/canvas-kit-react/button';
15-
import {colors, space} from '@workday/canvas-kit-react/tokens';
16-
179
import {useExpandableModel} from './hooks/useExpandableModel';
10+
import {createStencil} from '@workday/canvas-kit-styling';
11+
import {mergeStyles} from '@workday/canvas-kit-react/layout';
12+
import {system} from '@workday/canvas-tokens-web';
1813

1914
export interface ExpandableIconProps extends Omit<ExtractProps<typeof SystemIcon, never>, 'icon'> {
2015
/**
@@ -30,51 +25,70 @@ export interface ExpandableIconProps extends Omit<ExtractProps<typeof SystemIcon
3025
iconPosition?: IconPositions;
3126
}
3227

33-
const StyledEndIcon = styled(SystemIcon, {
34-
shouldForwardProp: filterOutProps(['visible']),
35-
})<{visible: boolean} & StyledType>(
36-
{
37-
marginLeft: 'auto',
28+
export const expandableIconStencil = createStencil({
29+
extends: systemIconStencil,
30+
base: {
31+
padding: system.space.x1,
3832
},
39-
({visible}) => ({
40-
transform: !visible ? 'rotate(-180deg)' : undefined,
41-
padding: !visible
42-
? `${space.xxxs} ${space.xs} ${space.xxxs} ${space.xxxs}`
43-
: `${space.xxxs} ${space.xxxs} ${space.xxxs} ${space.xs}`,
44-
})
45-
);
46-
47-
const StyledStartIcon = styled(SystemIcon, {
48-
shouldForwardProp: filterOutProps(['visible']),
49-
})<{visible: boolean} & StyledType>(
50-
{
51-
margin: `0 ${space.xxs} 0 0`,
52-
padding: space.xxxs,
33+
modifiers: {
34+
isExpanded: {
35+
true: {},
36+
false: {},
37+
},
38+
position: {
39+
start: {},
40+
end: {},
41+
only: {},
42+
},
5343
},
54-
({visible}) => ({
55-
transform: !visible ? 'rotate(-90deg)' : undefined,
56-
})
57-
);
44+
compound: [
45+
{
46+
modifiers: {position: 'end', isExpanded: false},
47+
styles: {
48+
marginInlineStart: 'auto',
49+
transform: 'rotate(180deg)',
50+
paddingInlineEnd: system.space.x3,
51+
},
52+
},
53+
{
54+
modifiers: {position: 'end', isExpanded: true},
55+
styles: {
56+
marginInlineStart: 'auto',
57+
paddingInlineStart: system.space.x3,
58+
},
59+
},
60+
{
61+
modifiers: {position: 'start', isExpanded: false},
62+
styles: {
63+
marginInlineEnd: system.space.x2,
64+
transform: 'rotate(90deg)',
65+
':dir(rtl)': {
66+
transform: 'rotate(-90deg)',
67+
},
68+
},
69+
},
70+
{
71+
modifiers: {position: 'start', isExpanded: true},
72+
styles: {
73+
marginInlineEnd: system.space.x2,
74+
transform: 'rotate(180deg)',
75+
},
76+
},
77+
],
78+
});
5879

5980
export const ExpandableIcon = createSubcomponent('span')({
6081
modelHook: useExpandableModel,
6182
elemPropsHook: useExpandableIcon,
62-
})<ExpandableIconProps>(({icon, visible, iconPosition = 'start', ...elementProps}, Element) =>
63-
iconPosition === 'end' ? (
64-
<StyledEndIcon
83+
})<ExpandableIconProps>(({icon, visible, iconPosition = 'start', ...elementProps}, Element) => {
84+
return (
85+
<SystemIcon
6586
as={Element}
66-
fill={colors.licorice200}
6787
icon={icon || chevronUpIcon}
68-
visible={visible}
69-
{...elementProps}
70-
/>
71-
) : (
72-
<StyledStartIcon
73-
as={Element}
74-
fill={colors.licorice200}
75-
icon={icon || chevronDownIcon}
76-
visible={visible}
77-
{...elementProps}
88+
{...mergeStyles(
89+
elementProps,
90+
expandableIconStencil({position: iconPosition, isExpanded: visible})
91+
)}
7892
/>
79-
)
80-
);
93+
);
94+
});
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
import React from 'react';
22

3-
import {
4-
createSubcomponent,
5-
ExtractProps,
6-
focusRing,
7-
styled,
8-
StyledType,
9-
} from '@workday/canvas-kit-react/common';
10-
import {Flex} from '@workday/canvas-kit-react/layout';
11-
import {colors} from '@workday/canvas-kit-react/tokens';
12-
3+
import {createSubcomponent, ExtractProps} from '@workday/canvas-kit-react/common';
4+
import {Flex, mergeStyles} from '@workday/canvas-kit-react/layout';
5+
import {Heading} from '@workday/canvas-kit-react/text';
6+
import {createStencil} from '@workday/canvas-kit-styling';
7+
import {system} from '@workday/canvas-tokens-web';
138
import {useExpandableTarget} from './hooks/useExpandableTarget';
149
import {useExpandableModel} from './hooks/useExpandableModel';
1510

@@ -28,38 +23,38 @@ export interface ExpandableTargetProps extends ExtractProps<typeof Flex, never>
2823
headingLevel?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
2924
}
3025

31-
const StyledButton = styled(Flex.as('button'))<StyledType>({
32-
cursor: 'pointer',
33-
'&:focus-visible, &.focus': {
34-
...focusRing(),
35-
},
36-
'&:hover': {
37-
background: colors.soap300,
26+
export const expandableTargetStencil = createStencil({
27+
base: {
28+
background: system.color.bg.transparent,
29+
borderColor: system.color.bg.transparent,
30+
borderRadius: system.shape.x1,
31+
borderWidth: 0,
32+
display: 'flex',
33+
alignItems: 'flex-start',
34+
flexDirection: 'row',
35+
justifyContent: 'start',
36+
padding: system.space.x2,
37+
cursor: 'pointer',
38+
width: '100%',
39+
'&:hover, &.hover': {
40+
backgroundColor: system.color.bg.alt.default,
41+
},
3842
},
3943
});
4044

41-
const Heading = styled('h1')<StyledType>({
42-
margin: 0,
43-
});
44-
4545
export const ExpandableTarget = createSubcomponent('button')({
4646
modelHook: useExpandableModel,
4747
elemPropsHook: useExpandableTarget,
4848
})<ExpandableTargetProps>(({children, headingLevel, ...elementProps}, Element) => {
4949
const button = (
50-
<StyledButton
51-
as={Element}
52-
background="none"
53-
border="none"
54-
borderRadius="m"
55-
flexDirection="row"
56-
padding="xxs"
57-
width="100%"
58-
{...elementProps}
59-
>
60-
{children}
61-
</StyledButton>
50+
<Element {...mergeStyles(elementProps, expandableTargetStencil())}>{children}</Element>
6251
);
6352

64-
return !!headingLevel ? <Heading as={headingLevel}>{button}</Heading> : button;
53+
return headingLevel ? (
54+
<Heading size="small" as={headingLevel} margin="0">
55+
{button}
56+
</Heading>
57+
) : (
58+
button
59+
);
6560
});

0 commit comments

Comments
 (0)