Skip to content

Commit 6a453b9

Browse files
authored
refactor: migrate border and outline to hyphenated properties (#4960)
Migrated two more sections and made ComputedStyleDecl['property'] more strict instead of just a string, now can get rid from `as StyleProperty` casting all over the codebase.
1 parent dc9eb34 commit 6a453b9

File tree

12 files changed

+88
-91
lines changed

12 files changed

+88
-91
lines changed

apps/builder/app/builder/features/navigator/css-preview.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
hyphenateProperty,
1212
mergeStyles,
1313
} from "@webstudio-is/css-engine";
14-
import type { StyleMap, StyleProperty } from "@webstudio-is/css-engine";
14+
import type { StyleMap } from "@webstudio-is/css-engine";
1515
import { CollapsibleSection } from "~/builder/shared/collapsible-section";
1616
import { highlightCss } from "~/builder/shared/code-highlight";
1717
import type { ComputedStyleDecl } from "~/shared/style-object-model";
@@ -37,7 +37,7 @@ const getCssText = (
3737

3838
// Aggregate styles by category so we can group them when rendering.
3939
for (const styleDecl of definedComputedStyles) {
40-
const property = hyphenateProperty(styleDecl.property) as StyleProperty;
40+
const property = hyphenateProperty(styleDecl.property);
4141
let group;
4242
if (
4343
styleDecl.source.name === "local" ||

apps/builder/app/builder/features/style-panel/sections/borders/border-color.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { toValue, type StyleProperty } from "@webstudio-is/css-engine";
1+
import { toValue, type CssProperty } from "@webstudio-is/css-engine";
22
import { Box, Grid } from "@webstudio-is/design-system";
33
import { styleConfigByName } from "../../shared/configs";
44
import { rowCss } from "./utils";
@@ -11,13 +11,13 @@ import {
1111
import { createBatchUpdate } from "../../shared/use-style-data";
1212

1313
export const properties = [
14-
"borderTopColor",
15-
"borderRightColor",
16-
"borderBottomColor",
17-
"borderLeftColor",
18-
] satisfies [StyleProperty, ...StyleProperty[]];
14+
"border-top-color",
15+
"border-right-color",
16+
"border-bottom-color",
17+
"border-left-color",
18+
] satisfies [CssProperty, ...CssProperty[]];
1919

20-
const { items } = styleConfigByName("borderTopColor");
20+
const { items } = styleConfigByName("border-top-color");
2121

2222
export const BorderColor = () => {
2323
const styles = useComputedStyles(properties);
@@ -54,7 +54,7 @@ export const BorderColor = () => {
5454
<ColorPicker
5555
disabled={isAdvanced}
5656
currentColor={currentColor}
57-
property={local.property as StyleProperty}
57+
property={local.property}
5858
value={value}
5959
getOptions={() => [
6060
...items.map((item) => ({

apps/builder/app/builder/features/style-panel/sections/borders/border-property.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { type ReactNode } from "react";
2-
import type { StyleProperty } from "@webstudio-is/css-engine";
3-
import { toValue } from "@webstudio-is/css-engine";
2+
import type { CssProperty } from "@webstudio-is/css-engine";
3+
import { hyphenateProperty, toValue } from "@webstudio-is/css-engine";
44
import { Box, Grid, ToggleButton } from "@webstudio-is/design-system";
55
import { CssValueInputContainer } from "../../shared/css-value-input";
66
import { styleConfigByName } from "../../shared/configs";
@@ -25,14 +25,14 @@ export const BorderProperty = ({
2525
}: {
2626
individualModeIcon?: ReactNode;
2727
borderPropertyOptions: Partial<{
28-
[property in StyleProperty]: { icon?: ReactNode };
28+
[property in CssProperty]: { icon?: ReactNode };
2929
}>;
3030
label: string;
3131
description: string;
3232
}) => {
3333
const borderProperties = Object.keys(borderPropertyOptions) as [
34-
StyleProperty,
35-
...StyleProperty[],
34+
CssProperty,
35+
...CssProperty[],
3636
];
3737
const styles = useComputedStyles(borderProperties);
3838
const styleValueSourceColor = getPriorityStyleValueSource(styles);
@@ -118,9 +118,10 @@ export const BorderProperty = ({
118118
<CssValueInputContainer
119119
key={styleDecl.property}
120120
icon={
121-
borderPropertyOptions[styleDecl.property as StyleProperty]?.icon
121+
borderPropertyOptions[hyphenateProperty(styleDecl.property)]
122+
?.icon
122123
}
123-
property={styleDecl.property as StyleProperty}
124+
property={styleDecl.property}
124125
styleSource={styleDecl.source.name}
125126
getOptions={() =>
126127
styleConfigByName(firstPropertyName).items.map((item) => ({
@@ -129,7 +130,7 @@ export const BorderProperty = ({
129130
}))
130131
}
131132
value={styleDecl.cascadedValue}
132-
setValue={setProperty(styleDecl.property as StyleProperty)}
133+
setValue={setProperty(styleDecl.property)}
133134
deleteProperty={deleteProperty}
134135
/>
135136
))}

apps/builder/app/builder/features/style-panel/sections/borders/border-radius.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { StyleProperty } from "@webstudio-is/css-engine";
1+
import type { CssProperty } from "@webstudio-is/css-engine";
22
import {
33
BorderRadiusIndividualIcon,
44
BorderRadiusBottomRightIcon,
@@ -9,26 +9,26 @@ import {
99
import { BorderProperty } from "./border-property";
1010

1111
export const properties = [
12-
"borderTopLeftRadius",
13-
"borderTopRightRadius",
14-
"borderBottomLeftRadius",
15-
"borderBottomRightRadius",
16-
] satisfies Array<StyleProperty>;
12+
"border-top-left-radius",
13+
"border-top-right-radius",
14+
"border-bottom-left-radius",
15+
"border-bottom-right-radius",
16+
] satisfies Array<CssProperty>;
1717

1818
const borderPropertyOptions = {
19-
borderTopLeftRadius: {
19+
"border-top-left-radius": {
2020
icon: <BorderRadiusTopLeftIcon />,
2121
},
22-
borderTopRightRadius: {
22+
"border-top-right-radius": {
2323
icon: <BorderRadiusTopRightIcon />,
2424
},
25-
borderBottomLeftRadius: {
25+
"border-bottom-left-radius": {
2626
icon: <BorderRadiusBottomLeftIcon />,
2727
},
28-
borderBottomRightRadius: {
28+
"border-bottom-right-radius": {
2929
icon: <BorderRadiusBottomRightIcon />,
3030
},
31-
} as const satisfies Partial<{ [property in StyleProperty]: unknown }>;
31+
} as const satisfies Partial<{ [property in CssProperty]: unknown }>;
3232

3333
export const BorderRadius = () => {
3434
return (

apps/builder/app/builder/features/style-panel/sections/borders/border-style.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { StyleProperty } from "@webstudio-is/css-engine";
1+
import type { CssProperty } from "@webstudio-is/css-engine";
22
import { Box, Grid } from "@webstudio-is/design-system";
33
import {
44
MinusIcon,
@@ -14,11 +14,11 @@ import {
1414
import { rowCss } from "./utils";
1515
import { PropertyLabel } from "../../property-label";
1616

17-
export const properties: [StyleProperty, ...StyleProperty[]] = [
18-
"borderTopStyle",
19-
"borderRightStyle",
20-
"borderLeftStyle",
21-
"borderBottomStyle",
17+
export const properties: [CssProperty, ...CssProperty[]] = [
18+
"border-top-style",
19+
"border-right-style",
20+
"border-left-style",
21+
"border-bottom-style",
2222
];
2323

2424
export const BorderStyle = () => {

apps/builder/app/builder/features/style-panel/sections/borders/border-width.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { StyleProperty } from "@webstudio-is/css-engine";
1+
import type { CssProperty } from "@webstudio-is/css-engine";
22
import {
33
BorderWidthIndividualIcon,
44
BorderWidthTopIcon,
@@ -9,26 +9,26 @@ import {
99
import { BorderProperty } from "./border-property";
1010

1111
export const properties = [
12-
"borderTopWidth",
13-
"borderRightWidth",
14-
"borderBottomWidth",
15-
"borderLeftWidth",
16-
] satisfies Array<StyleProperty>;
12+
"border-top-width",
13+
"border-right-width",
14+
"border-bottom-width",
15+
"border-left-width",
16+
] satisfies CssProperty[];
1717

1818
const borderPropertyOptions = {
19-
borderTopWidth: {
19+
"border-top-width": {
2020
icon: <BorderWidthTopIcon />,
2121
},
22-
borderRightWidth: {
22+
"border-right-width": {
2323
icon: <BorderWidthRightIcon />,
2424
},
25-
borderLeftWidth: {
25+
"border-left-width": {
2626
icon: <BorderWidthLeftIcon />,
2727
},
28-
borderBottomWidth: {
28+
"border-bottom-width": {
2929
icon: <BorderWidthBottomIcon />,
3030
},
31-
} as const satisfies Partial<{ [property in StyleProperty]: unknown }>;
31+
} as const satisfies Partial<{ [property in CssProperty]: unknown }>;
3232

3333
export const BorderWidth = () => {
3434
return (

apps/builder/app/builder/features/style-panel/sections/borders/borders.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { StyleProperty } from "@webstudio-is/css-engine";
1+
import type { CssProperty } from "@webstudio-is/css-engine";
22
import { StyleSection } from "../../shared/style-section";
33
import {
44
BorderRadius,
@@ -22,7 +22,7 @@ export const properties = [
2222
...borderRadiusProperties,
2323
...borderStyleProperties,
2424
...borderWidthProperties,
25-
] satisfies Array<StyleProperty>;
25+
] satisfies CssProperty[];
2626

2727
export const Section = () => {
2828
return (

apps/builder/app/builder/features/style-panel/sections/outline/outline.tsx

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@ import {
66
XSmallIcon,
77
} from "@webstudio-is/icons";
88
import { propertyDescriptions } from "@webstudio-is/css-data";
9-
import { toValue, type StyleProperty } from "@webstudio-is/css-engine";
9+
import { toValue, type CssProperty } from "@webstudio-is/css-engine";
1010
import { ColorControl, TextControl } from "../../controls";
1111
import { StyleSection } from "../../shared/style-section";
1212
import { PropertyLabel } from "../../property-label";
1313
import { useComputedStyleDecl } from "../../shared/model";
1414
import { ToggleGroupControl } from "../../controls/toggle-group/toggle-group-control";
1515

1616
export const properties = [
17-
"outlineStyle",
18-
"outlineColor",
19-
"outlineWidth",
20-
"outlineOffset",
21-
] satisfies Array<StyleProperty>;
17+
"outline-style",
18+
"outline-color",
19+
"outline-width",
20+
"outline-offset",
21+
] satisfies CssProperty[];
2222

2323
export const Section = () => {
24-
const outlineStyle = useComputedStyleDecl("outlineStyle");
24+
const outlineStyle = useComputedStyleDecl("outline-style");
2525
const outlineStyleValue = toValue(outlineStyle.cascadedValue);
2626

2727
return (
@@ -35,11 +35,11 @@ export const Section = () => {
3535
<PropertyLabel
3636
label="Style"
3737
description={propertyDescriptions.outlineStyle}
38-
properties={["outlineStyle"]}
38+
properties={["outline-style"]}
3939
/>
4040
<ToggleGroupControl
4141
label="Style"
42-
properties={["outlineStyle"]}
42+
properties={["outline-style"]}
4343
items={[
4444
{ child: <XSmallIcon />, value: "none" },
4545
{ child: <MinusIcon />, value: "solid" },
@@ -53,21 +53,21 @@ export const Section = () => {
5353
<PropertyLabel
5454
label="Color"
5555
description={propertyDescriptions.outlineColor}
56-
properties={["outlineColor"]}
56+
properties={["outline-color"]}
5757
/>
58-
<ColorControl property="outlineColor" />
58+
<ColorControl property="outline-color" />
5959
<PropertyLabel
6060
label="Width"
6161
description={propertyDescriptions.outlineWidth}
62-
properties={["outlineWidth"]}
62+
properties={["outline-width"]}
6363
/>
64-
<TextControl property="outlineWidth" />
64+
<TextControl property="outline-width" />
6565
<PropertyLabel
6666
label="Offset"
6767
description={propertyDescriptions.outlineOffset}
68-
properties={["outlineOffset"]}
68+
properties={["outline-offset"]}
6969
/>
70-
<TextControl property="outlineOffset" />
70+
<TextControl property="outline-offset" />
7171
</>
7272
)}
7373
</Grid>

apps/builder/app/builder/features/style-panel/shared/repeated-style.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
toValue,
55
type CssProperty,
66
type LayersValue,
7-
type StyleProperty,
87
type StyleValue,
98
type TupleValue,
109
type UnparsedValue,
@@ -37,7 +36,7 @@ const isRepeatedValue = (
3736
styleValue.type === "layers" || styleValue.type === "tuple";
3837

3938
const reparseComputedValue = (styleDecl: ComputedStyleDecl) => {
40-
const property = styleDecl.property as StyleProperty;
39+
const property = styleDecl.property;
4140
const serialized = toValue(styleDecl.computedValue);
4241
return parseCssValue(property, serialized);
4342
};
@@ -76,7 +75,7 @@ const isItemHidden = (styleValue: StyleValue, index: number) => {
7675
*/
7776
const getComputedValue = (styleDecl: ComputedStyleDecl) => {
7877
if (styleDecl.cascadedValue.type === "var") {
79-
const property = styleDecl.property as StyleProperty;
78+
const property = styleDecl.property;
8079
const serialized = toValue(styleDecl.computedValue);
8180
return parseCssValue(property, serialized);
8281
}
@@ -128,7 +127,7 @@ export const addRepeatedStyleItem = (
128127
}
129128
const batch = createBatchUpdate();
130129
const currentStyles = new Map(
131-
styles.map((styleDecl) => [styleDecl.property as StyleProperty, styleDecl])
130+
styles.map((styleDecl) => [styleDecl.property, styleDecl])
132131
);
133132
const primaryValue = styles[0].cascadedValue;
134133
let primaryCount = 0;
@@ -233,7 +232,7 @@ export const setRepeatedStyleItem = (
233232
const newItems: StyleValue[] = repeatUntil(oldItems, index);
234233
// unpack item when layers or tuple is provided
235234
newItems[index] = newItem.type === valueType ? newItem.value[0] : newItem;
236-
batch.setProperty(styleDecl.property as StyleProperty)({
235+
batch.setProperty(styleDecl.property)({
237236
type: valueType,
238237
value: newItems as UnparsedValue[],
239238
});
@@ -250,7 +249,7 @@ export const deleteRepeatedStyleItem = (
250249
? primaryValue.value.length
251250
: index + 1;
252251
for (const styleDecl of styles) {
253-
const property = styleDecl.property as StyleProperty;
252+
const property = styleDecl.property;
254253
const newValue = structuredClone(styleDecl.cascadedValue);
255254
if (isRepeatedValue(newValue)) {
256255
newValue.value = repeatUntil(newValue.value, primaryCount);
@@ -281,7 +280,7 @@ export const toggleRepeatedStyleItem = (
281280
: index + 1;
282281
const isHidden = isItemHidden(primaryValue, index);
283282
for (const styleDecl of styles) {
284-
const property = styleDecl.property as StyleProperty;
283+
const property = styleDecl.property;
285284
const newValue = structuredClone(styleDecl.cascadedValue);
286285
if (newValue.type === "var") {
287286
newValue.hidden = !isHidden;
@@ -320,7 +319,7 @@ export const swapRepeatedStyleItems = (
320319
newValue.value.splice(oldIndex, 1);
321320
newValue.value.splice(newIndex, 0, oldItem);
322321
}
323-
batch.setProperty(styleDecl.property as StyleProperty)(newValue);
322+
batch.setProperty(styleDecl.property)(newValue);
324323
}
325324
batch.publish();
326325
};

apps/builder/app/shared/style-object-model.test.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from "@webstudio-is/sdk";
1212
import { $, renderData } from "@webstudio-is/template";
1313
import { camelCaseProperty, parseCss } from "@webstudio-is/css-data";
14-
import type { StyleValue } from "@webstudio-is/css-engine";
14+
import type { StyleProperty, StyleValue } from "@webstudio-is/css-engine";
1515
import {
1616
type StyleObjectModel,
1717
getComputedStyleDecl,
@@ -990,14 +990,14 @@ test("work with unknown or invalid properties", () => {
990990
getComputedStyleDecl({
991991
model,
992992
instanceSelector,
993-
property: "unknownProperty",
993+
property: "unknownProperty" as StyleProperty,
994994
}).usedValue
995995
).toEqual({ type: "unparsed", value: "[object Object]" });
996996
expect(
997997
getComputedStyleDecl({
998998
model,
999999
instanceSelector,
1000-
property: "undefinedProperty",
1000+
property: "undefinedProperty" as StyleProperty,
10011001
}).usedValue
10021002
).toEqual({ type: "invalid", value: "" });
10031003
});

0 commit comments

Comments
 (0)