Skip to content

Commit 7bde57a

Browse files
authored
feat!: Add Sana styles to Side Panel (#4107)
Fixes: #3979 Updated styles for Side Panel [category:Components] Release Note: Side Panel (main) `alternate` variant has been renamed to `overlay` to match Figma library. New variant `alternative` has been added to Side Panel (main). ### BREAKING CHANGES Side Panel (main) `alternate` variant has been renamed to `overlay` to match Figma library. New variant `alternative` has been added to Side Panel (main).
1 parent fa29f86 commit 7bde57a

15 files changed

Lines changed: 532 additions & 133 deletions

File tree

cypress/component/SidePanel.spec.tsx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,29 @@ describe('Side Panel', () => {
5050
});
5151

5252
context('the button', () => {
53-
it(`should have an aria-pressed attribute of 'false'`, () => {
53+
it(`should still have an aria-pressed attribute of 'false' while collapsing`, () => {
5454
cy.findByRole('button', {name}).should('have.attr', 'aria-pressed', 'false');
5555
});
5656
});
57+
58+
context(`when the panel's width transition finishes`, () => {
59+
beforeEach(() => {
60+
// Transitions are disabled for Cypress in `component-index.html`, so the width
61+
// transition never runs and `transitionend` never fires on its own. Dispatch it so the
62+
// model settles from `collapsing` into `collapsed`. `eventConstructor` matters here:
63+
// the default `Event` cannot carry `propertyName`, which the model checks for.
64+
cy.findByRole(story.role, {name}).trigger('transitionend', {
65+
eventConstructor: 'TransitionEvent',
66+
propertyName: 'width',
67+
});
68+
});
69+
70+
context('the button', () => {
71+
it(`should have an aria-pressed attribute of 'true'`, () => {
72+
cy.findByRole('button', {name}).should('have.attr', 'aria-pressed', 'true');
73+
});
74+
});
75+
});
5776
});
5877
});
5978
});

modules/codemod/lib/v16/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ import {Transform} from 'jscodeshift';
22

33
import updateCardVariant from './updateCardVariant';
44
import updateHyperlinkProps from './updateHyperlinkProps';
5+
import updateSidePanelVariant from './updateSidePanelVariant';
56

67
const transform: Transform = (file, api, options) => {
78
// These will run in order. If your transform depends on others, place yours after dependent transforms
8-
const fixes: Transform[] = [updateHyperlinkProps, updateCardVariant];
9+
const fixes: Transform[] = [updateHyperlinkProps, updateCardVariant, updateSidePanelVariant];
910

1011
return fixes.reduce((source, fix) => fix({...file, source}, api, options) as string, file.source);
1112
};
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import {stripIndent} from 'common-tags';
2+
3+
import transform from '../updateSidePanelVariant';
4+
import {expectTransformFactory} from './expectTransformFactory';
5+
6+
const expectTransform = expectTransformFactory(transform);
7+
8+
describe('updateSidePanelVariant', () => {
9+
it('should convert variant="alternate" to variant="overlay" on package root imports', () => {
10+
const input = stripIndent`
11+
import {SidePanel} from '@workday/canvas-kit-react'
12+
<SidePanel variant="alternate">Content</SidePanel>
13+
`;
14+
15+
const expected = stripIndent`
16+
import {SidePanel} from '@workday/canvas-kit-react'
17+
<SidePanel variant="overlay">Content</SidePanel>
18+
`;
19+
expectTransform(input, expected);
20+
});
21+
22+
it('should convert variant="alternate" to variant="overlay" on slash imports', () => {
23+
const input = stripIndent`
24+
import {SidePanel} from '@workday/canvas-kit-react/side-panel'
25+
<SidePanel variant="alternate">Content</SidePanel>
26+
`;
27+
28+
const expected = stripIndent`
29+
import {SidePanel} from '@workday/canvas-kit-react/side-panel'
30+
<SidePanel variant="overlay">Content</SidePanel>
31+
`;
32+
expectTransform(input, expected);
33+
});
34+
35+
it('should transform aliased imports', () => {
36+
const input = stripIndent`
37+
import {SidePanel as Panel} from '@workday/canvas-kit-react/side-panel'
38+
<Panel variant="alternate">Content</Panel>
39+
`;
40+
41+
const expected = stripIndent`
42+
import {SidePanel as Panel} from '@workday/canvas-kit-react/side-panel'
43+
<Panel variant="overlay">Content</Panel>
44+
`;
45+
expectTransform(input, expected);
46+
});
47+
48+
it('should handle variant={"alternate"} expression values', () => {
49+
const input = stripIndent`
50+
import {SidePanel} from '@workday/canvas-kit-react/side-panel'
51+
<SidePanel variant={'alternate'}>Content</SidePanel>
52+
`;
53+
54+
const expected = stripIndent`
55+
import {SidePanel} from '@workday/canvas-kit-react/side-panel'
56+
<SidePanel variant="overlay">Content</SidePanel>
57+
`;
58+
expectTransform(input, expected);
59+
});
60+
61+
it('should transform styled-wrapped components', () => {
62+
const input = stripIndent`
63+
import styled from '@emotion/styled';
64+
import {SidePanel} from '@workday/canvas-kit-react/side-panel'
65+
const StyledPanel = styled(SidePanel)({color: '#000'});
66+
<StyledPanel variant="alternate">Content</StyledPanel>
67+
`;
68+
69+
const expected = stripIndent`
70+
import styled from '@emotion/styled';
71+
import {SidePanel} from '@workday/canvas-kit-react/side-panel'
72+
const StyledPanel = styled(SidePanel)({color: '#000'});
73+
<StyledPanel variant="overlay">Content</StyledPanel>
74+
`;
75+
expectTransform(input, expected);
76+
});
77+
78+
it('should transform styled-wrapped components from package root imports', () => {
79+
const input = stripIndent`
80+
import styled from '@emotion/styled';
81+
import {SidePanel} from '@workday/canvas-kit-react'
82+
const StyledPanel = styled(SidePanel)({color: '#000'});
83+
<StyledPanel variant="alternate">Content</StyledPanel>
84+
`;
85+
86+
const expected = stripIndent`
87+
import styled from '@emotion/styled';
88+
import {SidePanel} from '@workday/canvas-kit-react'
89+
const StyledPanel = styled(SidePanel)({color: '#000'});
90+
<StyledPanel variant="overlay">Content</StyledPanel>
91+
`;
92+
expectTransform(input, expected);
93+
});
94+
95+
it('should not transform variant="standard"', () => {
96+
const input = stripIndent`
97+
import {SidePanel} from '@workday/canvas-kit-react/side-panel'
98+
<SidePanel variant="standard">Content</SidePanel>
99+
`;
100+
101+
const expected = stripIndent`
102+
import {SidePanel} from '@workday/canvas-kit-react/side-panel'
103+
<SidePanel variant="standard">Content</SidePanel>
104+
`;
105+
expectTransform(input, expected);
106+
});
107+
108+
it('should not transform when SidePanel is not imported', () => {
109+
const input = stripIndent`
110+
import {Button} from '@workday/canvas-kit-react'
111+
<Button variant="alternate">Click me</Button>
112+
`;
113+
114+
const expected = stripIndent`
115+
import {Button} from '@workday/canvas-kit-react'
116+
<Button variant="alternate">Click me</Button>
117+
`;
118+
expectTransform(input, expected);
119+
});
120+
121+
it('should not transform SidePanel imported from the preview package', () => {
122+
const input = stripIndent`
123+
import {SidePanel} from '@workday/canvas-kit-preview-react/side-panel'
124+
<SidePanel variant="alternate">Content</SidePanel>
125+
`;
126+
127+
const expected = stripIndent`
128+
import {SidePanel} from '@workday/canvas-kit-preview-react/side-panel'
129+
<SidePanel variant="alternate">Content</SidePanel>
130+
`;
131+
expectTransform(input, expected);
132+
});
133+
});
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import {API, FileInfo, JSXAttribute, JSXElement, Options} from 'jscodeshift';
2+
3+
import {hasImportSpecifiers} from '../v6/utils';
4+
import {getImportRenameMap} from './utils/getImportRenameMap';
5+
6+
const packages = ['@workday/canvas-kit-react', '@workday/canvas-kit-react/side-panel'];
7+
const packageImports = ['SidePanel'];
8+
9+
function getVariantValue(attr: JSXAttribute): string | null {
10+
if (!attr.value) {
11+
return null;
12+
}
13+
14+
if (attr.value.type === 'StringLiteral') {
15+
return attr.value.value;
16+
}
17+
18+
if (
19+
attr.value.type === 'JSXExpressionContainer' &&
20+
(attr.value.expression.type === 'Literal' || attr.value.expression.type === 'StringLiteral')
21+
) {
22+
return String(attr.value.expression.value);
23+
}
24+
25+
return null;
26+
}
27+
28+
export default function transformer(file: FileInfo, api: API, _options: Options) {
29+
const j = api.jscodeshift;
30+
31+
const root = j(file.source);
32+
33+
if (!hasImportSpecifiers(api, root, packages, packageImports)) {
34+
return file.source;
35+
}
36+
37+
const {importMap, styledMap} = getImportRenameMap(j, root, '@workday/canvas-kit-react');
38+
39+
const componentNames = new Set([importMap.SidePanel, styledMap.SidePanel].filter(Boolean));
40+
41+
const components = root.find(
42+
j.JSXElement,
43+
(value: JSXElement) =>
44+
value.openingElement.name.type === 'JSXIdentifier' &&
45+
componentNames.has(value.openingElement.name.name)
46+
);
47+
48+
components.forEach(component => {
49+
const attributes = component.value.openingElement.attributes;
50+
if (!attributes) {
51+
return;
52+
}
53+
54+
const variantProp = attributes.find(
55+
attr => attr.type === 'JSXAttribute' && attr.name.name === 'variant'
56+
) as JSXAttribute | undefined;
57+
if (!variantProp) {
58+
return;
59+
}
60+
61+
const variantValue = getVariantValue(variantProp);
62+
if (variantValue !== 'alternate') {
63+
return;
64+
}
65+
66+
variantProp.value = j.stringLiteral('overlay');
67+
});
68+
69+
return root.toSource();
70+
}

0 commit comments

Comments
 (0)