Skip to content

Commit 707c6a5

Browse files
authored
Sass replace border width (#7613)
<!-- ☝️How to write a good PR title: - Prefix it with [ComponentName] (if applicable), for example: [Button] - Start with a verb, for example: Add, Delete, Improve, Fix… - Give as much context as necessary and as little as possible - Prefix it with [WIP] while it’s a work in progress --> ### WHY are these changes introduced? Fixes <!-- Context about the problem that’s being addressed. --> ### WHAT is this pull request doing? <!-- Summary of the changes committed. Before / after screenshots are appreciated for UI changes. Make sure to include alt text that describes the screenshot. If you include an animated gif showing your change, wrapping it in a details tag is recommended. Gifs usually autoplay, which can cause accessibility issues for people reviewing your PR: <details> <summary>Summary of your gif(s)</summary> <img src="..." alt="Description of what the gif shows"> </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) <!-- Give as much information as needed to experiment with the component in the playground. --> <details> <summary>Copy-paste this code in <code>playground/Playground.tsx</code>:</summary> ```jsx import React from 'react'; import {Page} from '../src'; export function Playground() { return ( <Page title="Playground"> {/* Add the code you want to test in here */} </Page> ); } ``` </details> ### 🎩 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 - [ ] [Tophatted documentation](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting%20documentation.md) changes in the style guide
1 parent d652b52 commit 707c6a5

25 files changed

+691
-323
lines changed

polaris-migrator/README.md

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,32 +155,71 @@ Replace legacy Typography functions and hardcoded lengths with Polaris custom pr
155155
npx @shopify/polaris-migrator styles-tokenize-fonts <path>
156156
```
157157

158-
### `styles-tokenize-fonts`
158+
### `styles-tokenize-shape`
159159

160-
Replace lengths (`px`, `rem`) and legacy Sass functions (`rem()`,`border()`, `border-width()`, `border-radius()`) in border declarations (`border`, `border-width`, and `border-radius`) with the corresponding Polaris [shape](https://polaris.shopify.com/tokens/shape) token.
160+
Replace usage of the legacy Sass `rem()` function and hard-coded lengths (`px`, `rem`) in `border`, `border-width`, and `border-radius` declarations with corresponding Polaris [shape](https://polaris.shopify.com/tokens/shape) token.
161161

162162
```diff
163163
- border: 1px solid transparent;
164164
+ border: var(--p-border-width-1) solid transparent;
165165

166+
- border-width: 0.0625rem;
167+
+ border-width: var(--p-border-width-1);
168+
169+
- border-radius: 4px;
170+
+ border-radius: var(--p-border-radius-1);
171+
```
172+
173+
```sh
174+
npx @shopify/polaris-migrator replace-border-declarations <path>
175+
```
176+
177+
### `sass-replace-border`
178+
179+
Replace usage of the legacy Sass `border()`) function in `border` declarations with corresponding Polaris [shape](https://polaris.shopify.com/tokens/shape) token.
180+
181+
```diff
166182
- border: border();
167183
+ border: var(--p-border-base);
168184

169-
- border-width: 0.0625rem;
185+
- border: border(divider);
186+
+ border: var(--p-border-divider);
187+
```
188+
189+
```sh
190+
npx @shopify/polaris-migrator sass-replace-border <path>
191+
```
192+
193+
### `sass-replace-border-width`
194+
195+
Replace usage of the legacy Sass `border-width()`) function in `border` and `border-width` declarations with corresponding Polaris [shape](https://polaris.shopify.com/tokens/shape) tokens.
196+
197+
```diff
198+
- border-width: border-width();
170199
+ border-width: var(--p-border-width-1);
171200

172201
- border-width: border-width(thick);
173202
+ border-width: var(--p-border-width-2);
203+
```
174204

175-
- border-radius: 4px;
205+
```sh
206+
npx @shopify/polaris-migrator sass-replace-border-width <path>
207+
```
208+
209+
### `sass-replace-border-radius`
210+
211+
Replace usage of the legacy Sass `border-radius()`) function in `border-radius` declarations with corresponding Polaris [shape](https://polaris.shopify.com/tokens/shape) tokens.
212+
213+
```diff
214+
- border-radius: border-radius();
176215
+ border-radius: var(--p-border-radius-1);
177216

178217
- border-radius: border-radius(large);
179218
+ border-radius: var(--p-border-radius-large);
180219
```
181220

182221
```sh
183-
npx @shopify/polaris-migrator styles-tokenize-fonts <path>
222+
npx @shopify/polaris-migrator sass-replace-border-radius <path>
184223
```
185224

186225
### `scss-replace-z-index`
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import type {FileInfo, API, Options} from 'jscodeshift';
2+
import postcss, {Plugin} from 'postcss';
3+
import valueParser from 'postcss-value-parser';
4+
5+
import {POLARIS_MIGRATOR_COMMENT} from '../../constants';
6+
import {
7+
getFunctionArgs,
8+
isNumericOperator,
9+
isSassFunction,
10+
isTransformableLength,
11+
namespace,
12+
NamespaceOptions,
13+
toTransformablePx,
14+
StopWalkingFunctionNodes,
15+
createInlineComment,
16+
} from '../../utilities/sass';
17+
import {isKeyOf} from '../../utilities/type-guards';
18+
19+
export default function sassReplaceBorderRadius(
20+
fileInfo: FileInfo,
21+
_: API,
22+
options: Options,
23+
) {
24+
return postcss(plugin(options)).process(fileInfo.source, {
25+
syntax: require('postcss-scss'),
26+
}).css;
27+
}
28+
29+
const processed = Symbol('processed');
30+
31+
interface PluginOptions extends Options, NamespaceOptions {}
32+
33+
const plugin = (options: PluginOptions = {}): Plugin => {
34+
const namespacedBorderRadius = namespace('border-radius', options);
35+
36+
return {
37+
postcssPlugin: 'sass-replace-border-radius',
38+
Declaration(decl) {
39+
// @ts-expect-error - Skip if processed so we don't process it again
40+
if (decl[processed]) return;
41+
42+
if (!borderRadiusProps.has(decl.prop)) return;
43+
44+
/**
45+
* A collection of transformable values to migrate (e.g. decl lengths, functions, etc.)
46+
*
47+
* Note: This is evaluated at the end of each visitor execution to determine whether
48+
* or not to replace the declaration or insert a comment.
49+
*/
50+
const targets: {replaced: boolean}[] = [];
51+
let hasNumericOperator = false;
52+
const parsedValue = valueParser(decl.value);
53+
54+
handleBorderRadiusProps();
55+
56+
if (targets.some(({replaced}) => !replaced || hasNumericOperator)) {
57+
// Insert comment if the declaration value contains calculations
58+
decl.before(
59+
createInlineComment(POLARIS_MIGRATOR_COMMENT, {prose: true}),
60+
);
61+
decl.before(
62+
createInlineComment(`${decl.prop}: ${parsedValue.toString()};`),
63+
);
64+
} else {
65+
decl.value = parsedValue.toString();
66+
}
67+
68+
//
69+
// Handler
70+
//
71+
72+
function handleBorderRadiusProps() {
73+
parsedValue.walk((node) => {
74+
if (isNumericOperator(node)) {
75+
hasNumericOperator = true;
76+
return;
77+
}
78+
79+
if (node.type === 'function') {
80+
if (isSassFunction(namespacedBorderRadius, node)) {
81+
targets.push({replaced: false});
82+
83+
const args = getFunctionArgs(node);
84+
85+
if (!(args.length === 0 || args.length === 1)) return;
86+
87+
// `border-radius()` args reference:
88+
// https://github.com/shopify/polaris/blob/2b14c0b60097f75d21df7eaa744dfaf84f8f53f7/documentation/guides/legacy-polaris-v8-public-api.scss#L655
89+
const value = args[0] ?? 'base';
90+
91+
if (!isKeyOf(borderRadiusFunctionMap, value)) return;
92+
93+
node.value = 'var';
94+
node.nodes = [
95+
{
96+
type: 'word',
97+
value: borderRadiusFunctionMap[value],
98+
sourceIndex: node.nodes[0]?.sourceIndex ?? 0,
99+
sourceEndIndex: borderRadiusFunctionMap[value].length,
100+
},
101+
];
102+
103+
targets[targets.length - 1]!.replaced = true;
104+
}
105+
106+
return StopWalkingFunctionNodes;
107+
}
108+
});
109+
}
110+
},
111+
};
112+
};
113+
114+
const borderRadiusProps = new Set([
115+
'border-radius',
116+
'border-top-left-radius',
117+
'border-top-right-radius',
118+
'border-bottom-left-radius',
119+
'border-bottom-right-radius',
120+
]);
121+
122+
const borderRadiusFunctionMap = {
123+
'': '--p-border-radius-base',
124+
base: '--p-border-radius-base',
125+
"'base'": '--p-border-radius-base',
126+
large: '--p-border-radius-large',
127+
"'large'": '--p-border-radius-large',
128+
} as const;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/* stylelint-disable */
2+
3+
.border-radius {
4+
/* Migrate */
5+
border-radius: border-radius();
6+
border-radius: border-radius(base);
7+
border-radius: border-radius(large);
8+
9+
/* Ignore */
10+
border-radius: calc(border-radius(base) * 2);
11+
border-radius: calc(border-radius() * rem(1px));
12+
13+
/* Comment */
14+
border-radius: border-radius(base) * 2;
15+
border-radius: border-radius() * rem(1px);
16+
border-top-right-radius: border-radius() * rem(4px);
17+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* stylelint-disable */
2+
3+
.border-radius {
4+
/* Migrate */
5+
border-radius: var(--p-border-radius-base);
6+
border-radius: var(--p-border-radius-base);
7+
border-radius: var(--p-border-radius-large);
8+
9+
/* Ignore */
10+
border-radius: calc(border-radius(base) * 2);
11+
border-radius: calc(border-radius() * rem(1px));
12+
13+
/* Comment */
14+
// polaris-migrator: Unable to migrate the following expression. Please upgrade manually.
15+
// border-radius: var(--p-border-radius-base) * 2;
16+
border-radius: border-radius(base) * 2;
17+
// polaris-migrator: Unable to migrate the following expression. Please upgrade manually.
18+
// border-radius: var(--p-border-radius-base) * rem(1px);
19+
border-radius: border-radius() * rem(1px);
20+
// polaris-migrator: Unable to migrate the following expression. Please upgrade manually.
21+
// border-top-right-radius: var(--p-border-radius-base) * rem(4px);
22+
border-top-right-radius: border-radius() * rem(4px);
23+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {check} from '../../../utilities/testUtils';
22

3-
const migration = 'replace-border-declarations';
4-
const fixtures = ['replace-border-declarations', 'with-namespace'];
3+
const migration = 'sass-replace-border-radius';
4+
const fixtures = ['sass-replace-border-radius', 'with-namespace'];
55

66
for (const fixture of fixtures) {
77
check(__dirname, {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* stylelint-disable */
2+
@use 'global-styles/legacy-polaris-v8';
3+
4+
.border-radius {
5+
/* Migrate */
6+
border-radius: legacy-polaris-v8.border-radius();
7+
border-radius: legacy-polaris-v8.border-radius(base);
8+
border-radius: legacy-polaris-v8.border-radius(large);
9+
10+
/* Ignore */
11+
border-radius: calc(legacy-polaris-v8.border-radius(base) * 2);
12+
border-radius: calc(
13+
legacy-polaris-v8.border-radius() * legacy-polaris-v8.rem(1px)
14+
);
15+
16+
/* Comment */
17+
border-radius: legacy-polaris-v8.border-radius(base) * 2;
18+
border-radius: legacy-polaris-v8.border-radius() * legacy-polaris-v8.rem(1px);
19+
border-top-right-radius: legacy-polaris-v8.border-radius() *
20+
legacy-polaris-v8.rem(4px);
21+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* stylelint-disable */
2+
@use 'global-styles/legacy-polaris-v8';
3+
4+
.border-radius {
5+
/* Migrate */
6+
border-radius: var(--p-border-radius-base);
7+
border-radius: var(--p-border-radius-base);
8+
border-radius: var(--p-border-radius-large);
9+
10+
/* Ignore */
11+
border-radius: calc(legacy-polaris-v8.border-radius(base) * 2);
12+
border-radius: calc(
13+
legacy-polaris-v8.border-radius() * legacy-polaris-v8.rem(1px)
14+
);
15+
16+
/* Comment */
17+
// polaris-migrator: Unable to migrate the following expression. Please upgrade manually.
18+
// border-radius: var(--p-border-radius-base) * 2;
19+
border-radius: legacy-polaris-v8.border-radius(base) * 2;
20+
// polaris-migrator: Unable to migrate the following expression. Please upgrade manually.
21+
// border-radius: var(--p-border-radius-base) * legacy-polaris-v8.rem(1px);
22+
border-radius: legacy-polaris-v8.border-radius() * legacy-polaris-v8.rem(1px);
23+
// polaris-migrator: Unable to migrate the following expression. Please upgrade manually.
24+
// border-top-right-radius: var(--p-border-radius-base) * legacy-polaris-v8.rem(4px);
25+
border-top-right-radius: legacy-polaris-v8.border-radius() *
26+
legacy-polaris-v8.rem(4px);
27+
}

0 commit comments

Comments
 (0)