Skip to content

Commit 3be27ba

Browse files
[Layout foundations] Update get-props script and refactor types in Box (#7396)
### WHY are these changes introduced? Resolves #7337. The styleguide wasn't parsing the type aliases for our layout components and displaying the TS logic instead of the typed value. ### WHAT is this pull request doing? - Updates the `get-props` script in the style guide to check if the type reference node has `UnionTypes` in the type arguments and, if so, get the parsed type and convert it to a string. - Updates the types in `Box` to no longer use template literals and explicitly declare accepted values in the unions - Updates the types in `Box` with large unions to mitigate values being truncated in the styleguide <details> <summary>Box alpha page — before</summary> <img src="https://user-images.githubusercontent.com/26749317/195697635-45c75746-82bf-4da0-b7bb-00bfa6f4ce3d.png" alt="Box alpha page — before"> </details> <details> <summary>Box alpha page — after</summary> <img src="https://user-images.githubusercontent.com/26749317/195697634-fa3a3e54-44c9-432b-b3c5-4208ea66fa21.png" alt="Box alpha page — after"> </details> <details> <summary>AlphaCard alpha page — before</summary> <img src="https://user-images.githubusercontent.com/26749317/195697631-6e2a49ee-d051-491e-aa3b-4e87db429d5e.png" alt="AlphaCard alpha page — before"> </details> <details> <summary>AlphaCard alpha page — after</summary> <img src="https://user-images.githubusercontent.com/26749317/195697626-e117cf32-f0fe-4c2b-9456-47c664e07640.png" alt="AlphaCard alpha page — after"> </details> <!-- ℹ️ Delete the following for small / trivial changes --> ### How to 🎩 🖥 [Local development instructions](https://github.com/Shopify/polaris/blob/main/README.md#local-development) 🗒 [General tophatting guidelines](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting.md) 📄 [Changelog guidelines](https://github.com/Shopify/polaris/blob/main/.github/CONTRIBUTING.md#changelog) ```script $ yarn && yarn build (in root polaris dir) $ cd polaris.shopify.com $ yarn && yarn dev ``` ### 🎩 checklist - [ ] Tested on [mobile](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting.md#cross-browser-testing) - [ ] Tested on [multiple browsers](https://help.shopify.com/en/manual/shopify-admin/supported-browsers) - [ ] Tested for [accessibility](https://github.com/Shopify/polaris/blob/main/documentation/Accessibility%20testing.md) - [ ] Updated the component's `README.md` with documentation changes - [x] [Tophatted documentation](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting%20documentation.md) changes in the style guide Co-authored-by: Aaron Casanova <[email protected]>
1 parent d462e2e commit 3be27ba

File tree

5 files changed

+1428
-1222
lines changed

5 files changed

+1428
-1222
lines changed

.changeset/dry-moles-lay.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'polaris.shopify.com': minor
3+
'@shopify/polaris': patch
4+
---
5+
6+
Updated alias and scale types in `Box` with type tests to check they exist in our token groups.
7+
Updated `get-props` script to parse utility types with unions.

polaris-react/src/components/Box/Box.tsx

Lines changed: 109 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,123 @@
11
import React, {createElement, forwardRef, ReactNode} from 'react';
22
import type {
3-
ColorsTokenName,
43
DepthShadowAlias,
5-
ShapeTokenName,
64
SpacingSpaceScale,
75
} from '@shopify/polaris-tokens';
86

97
import {classNames, sanitizeCustomProperties} from '../../utilities/css';
108

119
import styles from './Box.scss';
1210

13-
type BackgroundColorTokenScale = Extract<
14-
ColorsTokenName,
15-
| 'background'
16-
| `background-${string}`
17-
| 'surface'
18-
| `surface-${string}`
11+
type Element = 'div' | 'span';
12+
13+
export type BackgroundColorTokenScale =
14+
| 'action-critical'
15+
| 'action-critical-depressed'
16+
| 'action-critical-disabled'
17+
| 'action-critical-hovered'
18+
| 'action-critical-pressed'
19+
| 'action-primary'
20+
| 'action-primary-depressed'
21+
| 'action-primary-disabled'
22+
| 'action-primary-hovered'
23+
| 'action-primary-pressed'
24+
| 'action-secondary'
25+
| 'action-secondary-depressed'
26+
| 'action-secondary-disabled'
27+
| 'action-secondary-hovered'
28+
| 'action-secondary-hovered-dark'
29+
| 'action-secondary-pressed'
30+
| 'action-secondary-pressed-dark'
1931
| 'backdrop'
32+
| 'background'
33+
| 'background-hovered'
34+
| 'background-pressed'
35+
| 'background-selected'
2036
| 'overlay'
21-
| `action-${string}`
22-
>;
23-
type ColorTokenScale = Extract<ColorsTokenName, 'text' | `text-${string}`>;
24-
25-
type BorderShapeTokenScale = ShapeTokenName extends `border-${infer Scale}`
26-
? Scale
27-
: never;
28-
type BorderTokenScale = Exclude<
29-
BorderShapeTokenScale,
30-
`radius-${string}` | `width-${string}`
31-
>;
37+
| 'surface'
38+
| 'surface-attention'
39+
| 'surface-critical'
40+
| 'surface-critical-subdued'
41+
| 'surface-critical-subdued-depressed'
42+
| 'surface-critical-subdued-hovered'
43+
| 'surface-critical-subdued-pressed'
44+
| 'surface-dark'
45+
| 'surface-depressed'
46+
| 'surface-disabled'
47+
| 'surface-highlight'
48+
| 'surface-highlight-subdued'
49+
| 'surface-highlight-subdued-hovered'
50+
| 'surface-highlight-subdued-pressed'
51+
| 'surface-hovered'
52+
| 'surface-hovered-dark'
53+
| 'surface-neutral'
54+
| 'surface-neutral-disabled'
55+
| 'surface-neutral-hovered'
56+
| 'surface-neutral-pressed'
57+
| 'surface-neutral-subdued'
58+
| 'surface-neutral-subdued-dark'
59+
| 'surface-pressed'
60+
| 'surface-pressed-dark'
61+
| 'surface-primary-selected'
62+
| 'surface-primary-selected-hovered'
63+
| 'surface-primary-selected-pressed'
64+
| 'surface-search-field'
65+
| 'surface-search-field-dark'
66+
| 'surface-selected'
67+
| 'surface-selected-hovered'
68+
| 'surface-selected-pressed'
69+
| 'surface-subdued'
70+
| 'surface-success'
71+
| 'surface-success-subdued'
72+
| 'surface-success-subdued-hovered'
73+
| 'surface-success-subdued-pressed'
74+
| 'surface-warning'
75+
| 'surface-warning-subdued'
76+
| 'surface-warning-subdued-hovered'
77+
| 'surface-warning-subdued-pressed';
78+
79+
export type ColorTokenScale =
80+
| 'text'
81+
| 'text-critical'
82+
| 'text-disabled'
83+
| 'text-highlight'
84+
| 'text-on-critical'
85+
| 'text-on-dark'
86+
| 'text-on-interactive'
87+
| 'text-on-primary'
88+
| 'text-primary'
89+
| 'text-primary-hovered'
90+
| 'text-primary-pressed'
91+
| 'text-subdued'
92+
| 'text-subdued-on-dark'
93+
| 'text-success'
94+
| 'text-warning';
95+
96+
export type BorderTokenAlias =
97+
| 'base'
98+
| 'dark'
99+
| 'divider'
100+
| 'divider-on-dark'
101+
| 'transparent';
32102

33103
interface Border {
34-
bottom: BorderTokenScale;
35-
left: BorderTokenScale;
36-
right: BorderTokenScale;
37-
top: BorderTokenScale;
104+
bottom: BorderTokenAlias;
105+
left: BorderTokenAlias;
106+
right: BorderTokenAlias;
107+
top: BorderTokenAlias;
38108
}
39109

40-
type BorderRadiusTokenScale = Extract<
41-
BorderShapeTokenScale,
42-
`radius-${string}`
43-
> extends `radius-${infer Scale}`
44-
? Scale
45-
: never;
110+
export type BorderRadiusTokenScale =
111+
| '05'
112+
| '1'
113+
| '2'
114+
| '3'
115+
| '4'
116+
| '5'
117+
| '6'
118+
| 'base'
119+
| 'large'
120+
| 'half';
46121

47122
interface BorderRadius {
48123
bottomLeft: BorderRadiusTokenScale;
@@ -58,23 +133,21 @@ interface Spacing {
58133
top: SpacingSpaceScale;
59134
}
60135

61-
type Element = 'div' | 'span';
62-
63136
export interface BoxProps {
64137
/** HTML Element type */
65138
as?: Element;
66139
/** Background color */
67140
background?: BackgroundColorTokenScale;
68141
/** Border style */
69-
border?: BorderTokenScale;
142+
border?: BorderTokenAlias;
70143
/** Bottom border style */
71-
borderBottom?: BorderTokenScale;
144+
borderBottom?: BorderTokenAlias;
72145
/** Left border style */
73-
borderLeft?: BorderTokenScale;
146+
borderLeft?: BorderTokenAlias;
74147
/** Right border style */
75-
borderRight?: BorderTokenScale;
148+
borderRight?: BorderTokenAlias;
76149
/** Top border style */
77-
borderTop?: BorderTokenScale;
150+
borderTop?: BorderTokenAlias;
78151
/** Border radius */
79152
borderRadius?: BorderRadiusTokenScale;
80153
/** Bottom left border radius */

polaris-react/src/components/Box/tests/Box.test.tsx

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,62 @@
11
import React from 'react';
22
import {mountWithApp} from 'tests/utilities';
3+
import type {ColorsTokenName, ShapeTokenName} from '@shopify/polaris-tokens';
34

45
import {Box} from '..';
6+
import type {
7+
BackgroundColorTokenScale as BoxBackgroundColorTokenScale,
8+
ColorTokenScale as BoxColorTokenScale,
9+
BorderTokenAlias as BoxBorderTokenAlias,
10+
BorderRadiusTokenScale as BoxBorderRadiusTokenScale,
11+
} from '..';
12+
13+
// Test that type passed in is true
14+
type Expect<T extends true> = T;
15+
// Test each token in TokenTypeAlias to check that it exists in the TokenGroup
16+
type Equal<TokenGroup, TokenTypeAlias> = (<T>() => T extends TokenGroup
17+
? 1
18+
: 2) extends <T>() => T extends TokenTypeAlias ? 1 : 2
19+
? true
20+
: false;
21+
22+
// Extract token scales and aliases from token groups for testing
23+
type BackgroundColorTokenScale = Extract<
24+
ColorsTokenName,
25+
| `action-${string}`
26+
| 'backdrop'
27+
| 'background'
28+
| `background-${string}`
29+
| 'overlay'
30+
| 'surface'
31+
| `surface-${string}`
32+
>;
33+
34+
type ColorTokenScale = Extract<ColorsTokenName, 'text' | `text-${string}`>;
35+
36+
type BorderShapeTokenScale = ShapeTokenName extends `border-${infer Scale}`
37+
? Scale
38+
: never;
39+
type BorderTokenAlias = Exclude<
40+
BorderShapeTokenScale,
41+
`radius-${string}` | `width-${string}`
42+
>;
43+
44+
type BorderRadiusTokenScale = Extract<
45+
BorderShapeTokenScale,
46+
`radius-${string}`
47+
> extends `radius-${infer Scale}`
48+
? Scale
49+
: never;
50+
51+
// Test type aliases to ensure they are valid values from our token groups
52+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
53+
// @ts-ignore
54+
type cases = [
55+
Expect<Equal<BackgroundColorTokenScale, BoxBackgroundColorTokenScale>>,
56+
Expect<Equal<ColorTokenScale, BoxColorTokenScale>>,
57+
Expect<Equal<BorderTokenAlias, BoxBorderTokenAlias>>,
58+
Expect<Equal<BorderRadiusTokenScale, BoxBorderRadiusTokenScale>>,
59+
];
560

661
const text = 'This is a box';
762
const children = <p>{text}</p>;

polaris.shopify.com/scripts/get-props/src/get-props.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,15 @@ const parseTypeAliasDeclaration: NodeParser = (
183183
const description = getSymbolComment(symbol, checker);
184184
const name = symbol.escapedName.toString();
185185
const syntaxKind = ts.SyntaxKind[typeAliasDeclaration.kind];
186+
const typeRefNode = typeAliasDeclaration.type as ts.TypeReferenceNode;
186187
let value = typeAliasDeclaration.type.getText();
187188

189+
for (const typeArg of typeRefNode.typeArguments ?? []) {
190+
if (typeArg.kind === ts.SyntaxKind.UnionType) {
191+
value = checker.typeToString(checker.getTypeAtLocation(typeArg));
192+
}
193+
}
194+
188195
if (typeAliasDeclaration.type.kind === ts.SyntaxKind.UnionType) {
189196
const unionType = typeAliasDeclaration.type as ts.UnionTypeNode;
190197
value = unionType.types.map((type) => type.getText()).join(' | ');

0 commit comments

Comments
 (0)