Skip to content

Commit 68cce11

Browse files
authored
refactor: hyphenate space and position sections (#4973)
Slightly refactored both space and position sections. Moved property maps from scrub and keyboard to dedicated sections. Also fixed keyboard highlighting in space and inset controls.
1 parent 3c8ac56 commit 68cce11

File tree

12 files changed

+232
-178
lines changed

12 files changed

+232
-178
lines changed

apps/builder/app/builder/features/style-panel/sections/position/inset-control.tsx

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
1-
import { Grid, theme } from "@webstudio-is/design-system";
21
import { useRef, useState } from "react";
3-
import { movementMapInset, useKeyboardNavigation } from "../shared/keyboard";
2+
import { Grid, theme } from "@webstudio-is/design-system";
3+
import type { CssProperty, StyleValue } from "@webstudio-is/css-engine";
4+
import { useKeyboardNavigation } from "../shared/keyboard";
45
import { createBatchUpdate, deleteProperty } from "../../shared/use-style-data";
5-
import { getInsetModifiersGroup, useScrub } from "../shared/scrub";
6+
import { useScrub } from "../shared/scrub";
67
import { ValueText } from "../shared/value-text";
7-
import type { StyleValue } from "@webstudio-is/css-engine";
8-
import { InputPopover } from "../shared/input-popover";
9-
import { InsetLayout, type InsetProperty } from "./inset-layout";
10-
import { InsetTooltip } from "./inset-tooltip";
118
import { useComputedStyleDecl, useComputedStyles } from "../../shared/model";
129
import { useModifierKeys, type Modifiers } from "../../shared/modifier-keys";
10+
import { InputPopover } from "../shared/input-popover";
11+
import { InsetLayout, type InsetProperty } from "./inset-layout";
12+
import { getInsetModifiersGroup, InsetTooltip } from "./inset-tooltip";
13+
14+
const movementMapInset = {
15+
top: ["bottom", "right", "bottom", "left"],
16+
right: ["top", "left", "bottom", "left"],
17+
bottom: ["top", "right", "top", "left"],
18+
left: ["top", "right", "bottom", "right"],
19+
} as const;
1320

1421
const Cell = ({
1522
scrubStatus,
@@ -23,7 +30,7 @@ const Cell = ({
2330
onPopoverClose: () => void;
2431
scrubStatus: ReturnType<typeof useScrub>;
2532
property: InsetProperty;
26-
getActiveProperties: (modifiers?: Modifiers) => readonly InsetProperty[];
33+
getActiveProperties: (modifiers?: Modifiers) => CssProperty[];
2734
onHover: (target: HoverTarget | undefined) => void;
2835
}) => {
2936
const styleDecl = useComputedStyleDecl(property);
@@ -93,7 +100,7 @@ export const InsetControl = () => {
93100

94101
const [openProperty, setOpenProperty] = useState<InsetProperty>();
95102
const [activePopoverProperties, setActivePopoverProperties] = useState<
96-
undefined | readonly InsetProperty[]
103+
undefined | CssProperty[]
97104
>();
98105
const modifiers = useModifierKeys();
99106
const handleOpenProperty = (property: undefined | InsetProperty) => {
@@ -111,11 +118,14 @@ export const InsetControl = () => {
111118
});
112119

113120
// by deafult highlight hovered or scrubbed properties
114-
// if keyboard navigation is active, highlight its active property
115121
// if popover is open, highlight its property and hovered properties
116122
const activeProperties = [
117123
...(activePopoverProperties ?? scrubStatus.properties),
118124
];
125+
// if keyboard navigation is active, highlight its active property
126+
if (keyboardNavigation.isActive) {
127+
activeProperties.push(keyboardNavigation.activeProperty);
128+
}
119129
const getActiveProperties = (modifiers?: Modifiers) => {
120130
return modifiers && openProperty
121131
? getInsetModifiersGroup(openProperty, modifiers)

apps/builder/app/builder/features/style-panel/sections/position/inset-layout.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { Grid, Box, theme, styled } from "@webstudio-is/design-system";
21
import type { MouseEvent } from "react";
2+
import { Grid, Box, theme, styled } from "@webstudio-is/design-system";
3+
import type { CssProperty } from "@webstudio-is/css-engine";
34
import type { Modifiers } from "../../shared/modifier-keys";
45

56
const RECT_HEIGHT = 6;
@@ -42,7 +43,7 @@ type InsetLayoutProps = {
4243
onHover: (
4344
args: { element: HTMLElement; property: InsetProperty } | undefined
4445
) => void;
45-
getActiveProperties: (modifiers?: Modifiers) => readonly InsetProperty[];
46+
getActiveProperties: (modifiers?: Modifiers) => CssProperty[];
4647
};
4748
/**
4849
* Grid schema for graphical layout

apps/builder/app/builder/features/style-panel/sections/position/inset-tooltip.tsx

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,36 @@
11
import { useState, type ReactElement } from "react";
22
import { Tooltip } from "@webstudio-is/design-system";
3+
import type { CssProperty } from "@webstudio-is/css-engine";
34
import { useModifierKeys } from "../../shared/modifier-keys";
4-
import { getInsetModifiersGroup } from "../shared/scrub";
55
import { createBatchUpdate } from "../../shared/use-style-data";
66
import type { InsetProperty } from "./inset-layout";
77
import { PropertyInfo } from "../../property-label";
88
import { useComputedStyles } from "../../shared/model";
99

10+
const opposingInsetGroups = [
11+
["top", "bottom"],
12+
["left", "right"],
13+
] satisfies CssProperty[][];
14+
15+
const circleInsetGroups = [
16+
["top", "right", "bottom", "left"],
17+
] satisfies CssProperty[][];
18+
19+
export const getInsetModifiersGroup = (
20+
property: CssProperty,
21+
modifiers: { shiftKey: boolean; altKey: boolean }
22+
) => {
23+
let groups: CssProperty[][] = [];
24+
25+
if (modifiers.shiftKey) {
26+
groups = circleInsetGroups;
27+
} else if (modifiers.altKey) {
28+
groups = opposingInsetGroups;
29+
}
30+
31+
return groups.find((group) => group.includes(property)) ?? [property];
32+
};
33+
1034
const sides = {
1135
top: "top",
1236
right: "left",
@@ -15,7 +39,7 @@ const sides = {
1539
} as const;
1640

1741
const propertyContents: {
18-
properties: InsetProperty[];
42+
properties: CssProperty[];
1943
label: string;
2044
description: string;
2145
}[] = [
@@ -41,9 +65,9 @@ const propertyContents: {
4165
},
4266
];
4367

44-
const isSameUnorderedArrays = (
45-
arrA: readonly string[],
46-
arrB: readonly string[]
68+
const isSameUnorderedArrays = <Item,>(
69+
arrA: readonly Item[],
70+
arrB: readonly Item[]
4771
) => {
4872
if (arrA.length !== arrB.length) {
4973
return false;

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

Lines changed: 7 additions & 7 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 { Grid, theme } from "@webstudio-is/design-system";
33
import { propertyDescriptions } from "@webstudio-is/css-data";
44
import { StyleSection } from "../../shared/style-section";
@@ -13,12 +13,12 @@ import { InsetControl } from "./inset-control";
1313

1414
export const properties = [
1515
"position",
16-
"zIndex",
16+
"z-index",
1717
"top",
1818
"right",
1919
"bottom",
2020
"left",
21-
] satisfies Array<StyleProperty>;
21+
] satisfies CssProperty[];
2222

2323
export const Section = () => {
2424
const position = useComputedStyleDecl("position");
@@ -56,9 +56,9 @@ export const Section = () => {
5656
<PropertyLabel
5757
label="Z Index"
5858
description={propertyDescriptions.zIndex}
59-
properties={["zIndex"]}
59+
properties={["z-index"]}
6060
/>
61-
<TextControl property="zIndex" />
61+
<TextControl property="z-index" />
6262
</>
6363
)}
6464
</Grid>
@@ -69,9 +69,9 @@ export const Section = () => {
6969
<PropertyLabel
7070
label="Z Index"
7171
description={propertyDescriptions.zIndex}
72-
properties={["zIndex"]}
72+
properties={["z-index"]}
7373
/>
74-
<TextControl property="zIndex" />
74+
<TextControl property="z-index" />
7575
</Grid>
7676
</Grid>
7777
)}

apps/builder/app/builder/features/style-panel/sections/shared/input-popover.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
Flex,
99
theme,
1010
} from "@webstudio-is/design-system";
11-
import type { StyleProperty, StyleValue } from "@webstudio-is/css-engine";
11+
import type { CssProperty, StyleValue } from "@webstudio-is/css-engine";
1212
import { propertyDescriptions } from "@webstudio-is/css-data";
1313
import {
1414
CssValueInput,
@@ -34,8 +34,8 @@ const Input = ({
3434
onClosePopover,
3535
}: {
3636
styleSource: StyleValueSourceColor;
37-
property: StyleProperty;
38-
getActiveProperties: (modifiers?: Modifiers) => readonly StyleProperty[];
37+
property: CssProperty;
38+
getActiveProperties: (modifiers?: Modifiers) => CssProperty[];
3939
value: StyleValue;
4040
onClosePopover: () => void;
4141
}) => {
@@ -147,8 +147,8 @@ export const InputPopover = ({
147147
onClose,
148148
}: {
149149
styleSource: StyleValueSourceColor;
150-
property: StyleProperty;
151-
getActiveProperties: (modifiers?: Modifiers) => readonly StyleProperty[];
150+
property: CssProperty;
151+
getActiveProperties: (modifiers?: Modifiers) => CssProperty[];
152152
value: StyleValue;
153153
isOpen: boolean;
154154
onClose: () => void;

apps/builder/app/builder/features/style-panel/sections/shared/keyboard.ts

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,6 @@ const movementKeys = [
99
"ArrowLeft",
1010
] as const;
1111

12-
export const movementMapSpace = {
13-
marginTop: ["marginBottom", "marginRight", "paddingTop", "marginLeft"],
14-
marginRight: ["marginTop", "marginLeft", "marginBottom", "paddingRight"],
15-
marginBottom: ["paddingBottom", "marginRight", "marginTop", "marginLeft"],
16-
marginLeft: ["marginTop", "paddingLeft", "marginBottom", "marginRight"],
17-
paddingTop: ["marginTop", "paddingRight", "paddingBottom", "paddingLeft"],
18-
paddingRight: ["paddingTop", "marginRight", "paddingBottom", "paddingBottom"],
19-
paddingBottom: ["paddingTop", "paddingRight", "marginBottom", "paddingLeft"],
20-
paddingLeft: ["paddingTop", "paddingTop", "paddingBottom", "marginLeft"],
21-
} as const;
22-
23-
export const movementMapInset = {
24-
top: ["bottom", "right", "bottom", "left"],
25-
right: ["top", "left", "bottom", "left"],
26-
bottom: ["top", "right", "top", "left"],
27-
left: ["top", "right", "bottom", "right"],
28-
} as const;
29-
3012
/**
3113
* useFocusWithin does't work with popovers, implement it using debounce
3214
*/

apps/builder/app/builder/features/style-panel/sections/shared/scrub.tsx

Lines changed: 6 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
1+
import { useState, useEffect, useRef } from "react";
12
import type {
2-
StyleProperty,
3+
CssProperty,
34
StyleValue,
45
UnitValue,
56
} from "@webstudio-is/css-engine";
7+
import { toValue } from "@webstudio-is/css-engine";
68
import { numericScrubControl } from "@webstudio-is/design-system";
7-
import { useState, useEffect, useRef } from "react";
9+
import { camelCaseProperty, isValidDeclaration } from "@webstudio-is/css-data";
810
import { useModifierKeys } from "../../shared/modifier-keys";
911
import type { StyleUpdateOptions } from "../../shared/use-style-data";
10-
import type { SpaceStyleProperty } from "../space/types";
11-
import { isValidDeclaration } from "@webstudio-is/css-data";
1212
import { parseIntermediateOrInvalidValue } from "../../shared/css-value-input/parse-intermediate-or-invalid-value";
13-
import { toValue } from "@webstudio-is/css-engine";
1413
import type { CssValueInputValue } from "../../shared/css-value-input/css-value-input";
15-
import type { InsetProperty } from "../position/inset-layout";
1614

1715
type ScrubStatus<P extends string> = {
1816
isActive: boolean;
@@ -34,7 +32,7 @@ type HoverTarget<P> = {
3432
element: HTMLElement | SVGElement;
3533
};
3634

37-
export const useScrub = <P extends StyleProperty>(props: {
35+
export const useScrub = <P extends CssProperty>(props: {
3836
value?: StyleValue;
3937
target: HoverTarget<P> | undefined;
4038
getModifiersGroup: (
@@ -87,7 +85,7 @@ export const useScrub = <P extends StyleProperty>(props: {
8785
} as const;
8886

8987
if (isValidDeclaration(property, toValue(value)) === false) {
90-
value = parseIntermediateOrInvalidValue(property, {
88+
value = parseIntermediateOrInvalidValue(camelCaseProperty(property), {
9189
type: "intermediate",
9290
value: `${value.value}`,
9391
unit: value.unit,
@@ -154,52 +152,3 @@ export const useScrub = <P extends StyleProperty>(props: {
154152
values,
155153
};
156154
};
157-
158-
const opposingSpaceGroups = [
159-
["paddingTop", "paddingBottom"],
160-
["paddingRight", "paddingLeft"],
161-
["marginTop", "marginBottom"],
162-
["marginRight", "marginLeft"],
163-
] as const;
164-
165-
const circleSpaceGroups = [
166-
["paddingTop", "paddingRight", "paddingBottom", "paddingLeft"],
167-
["marginTop", "marginRight", "marginBottom", "marginLeft"],
168-
] as const;
169-
170-
export const getSpaceModifiersGroup = (
171-
property: SpaceStyleProperty,
172-
modifiers: { shiftKey: boolean; altKey: boolean }
173-
) => {
174-
let groups: ReadonlyArray<ReadonlyArray<SpaceStyleProperty>> = [];
175-
176-
if (modifiers.shiftKey) {
177-
groups = circleSpaceGroups;
178-
} else if (modifiers.altKey) {
179-
groups = opposingSpaceGroups;
180-
}
181-
182-
return groups.find((group) => group.includes(property)) ?? [property];
183-
};
184-
185-
const opposingInsetGroups = [
186-
["top", "bottom"],
187-
["left", "right"],
188-
] as const;
189-
190-
const circleInsetGroups = [["top", "right", "bottom", "left"]] as const;
191-
192-
export const getInsetModifiersGroup = (
193-
property: InsetProperty,
194-
modifiers: { shiftKey: boolean; altKey: boolean }
195-
) => {
196-
let groups: ReadonlyArray<ReadonlyArray<InsetProperty>> = [];
197-
198-
if (modifiers.shiftKey) {
199-
groups = circleInsetGroups;
200-
} else if (modifiers.altKey) {
201-
groups = opposingInsetGroups;
202-
}
203-
204-
return groups.find((group) => group.includes(property)) ?? [property];
205-
};

0 commit comments

Comments
 (0)