refactor: migrate outline section to style object model (#4074)

Ref https://github.com/webstudio-is/webstudio/issues/1536
https://github.com/webstudio-is/webstudio/issues/3399

- refactored outline section into single module for simplicity
- replaced css value input container with text control
- visually aligned color input and length inputs

<img width="253" alt="Screenshot 2024-09-05 at 16 44 37"
src="https://github.com/user-attachments/assets/888335a7-e562-4dc2-b8cb-9c4f568cb688">
<img width="267" alt="Screenshot 2024-09-05 at 16 44 19"
src="https://github.com/user-attachments/assets/fd977d46-3f3f-46a0-a6e7-2ea7cc806b79">
This commit is contained in:
Bogdan Chadkin authored and GitHub committed 2024-09-05 19:14:07 +02:00
1 parent 61eec6815b
commit cafba33352
4 files changed
+57 -183

No files matched your search

@@ -1,54 +0,0 @@
import { propertyDescriptions } from "@webstudio-is/css-data";
import type { StyleProperty, UnitValue } from "@webstudio-is/css-engine";
import { Grid, theme } from "@webstudio-is/design-system";
import { CssValueInputContainer } from "../../shared/css-value-input";
import type { SectionProps } from "../shared/section";
import { styleConfigByName } from "../../shared/configs";
import { getStyleSource } from "../../shared/style-info";
import { PropertyLabel } from "../../property-label";
const property: StyleProperty = "outlineOffset";
const defaultOutlineOffsetValue: UnitValue = {
type: "unit",
value: 0,
unit: "number",
};
export const OutlineOffset = (
props: Pick<SectionProps, "currentStyle" | "setProperty" | "deleteProperty">
) => {
const { deleteProperty, setProperty, currentStyle } = props;
const outlineOffsetValue =
currentStyle[property]?.value ?? defaultOutlineOffsetValue;
const outlineOffsetStyleConfig = styleConfigByName(property);
const outlineOffsetWidthKeywords = outlineOffsetStyleConfig.items.map(
(item) => ({
type: "keyword" as const,
value: item.name,
})
);
return (
<Grid
css={{
gridTemplateColumns: `1fr ${theme.spacing[20]}`,
}}
gap={2}
>
<PropertyLabel
label="Offset"
description={propertyDescriptions.outlineOffset}
properties={["outlineOffset"]}
/>
<CssValueInputContainer
property={property}
styleSource={getStyleSource(currentStyle[property])}
keywords={outlineOffsetWidthKeywords}
setValue={setProperty(property)}
deleteProperty={deleteProperty}
value={outlineOffsetValue}
/>
</Grid>
);
};
@@ -1,39 +0,0 @@
import { Grid, theme, Box } from "@webstudio-is/design-system";
import {
DashBorderIcon,
DashedBorderIcon,
DottedBorderIcon,
SmallXIcon,
} from "@webstudio-is/icons";
import { propertyDescriptions } from "@webstudio-is/css-data";
import { PropertyLabel } from "../../property-label";
import { ToggleGroupControl } from "../../controls/toggle-group/toggle-group-control";
export const OutlineStyle = () => {
return (
<Grid
css={{
gridTemplateColumns: `1fr ${theme.spacing[20]} ${theme.spacing[12]}`,
}}
gap={2}
>
<PropertyLabel
label="Style"
description={propertyDescriptions.outlineStyle}
properties={["outlineStyle"]}
/>
<Box css={{ gridColumn: `span 2`, justifySelf: "end" }}>
<ToggleGroupControl
label="Style"
properties={["outlineStyle"]}
items={[
{ child: <SmallXIcon />, value: "none" },
{ child: <DashBorderIcon />, value: "solid" },
{ child: <DashedBorderIcon />, value: "dashed" },
{ child: <DottedBorderIcon />, value: "dotted" },
]}
/>
</Box>
</Grid>
);
};
@@ -1,47 +0,0 @@
import { propertyDescriptions } from "@webstudio-is/css-data";
import type { StyleProperty } from "@webstudio-is/css-engine";
import { Grid, theme } from "@webstudio-is/design-system";
import type { SectionProps } from "../shared/section";
import { CssValueInputContainer } from "../../shared/css-value-input";
import { styleConfigByName } from "../../shared/configs";
import { getStyleSource } from "../../shared/style-info";
import { PropertyLabel } from "../../property-label";
const property: StyleProperty = "outlineWidth";
export const OutlineWidth = (
props: Pick<SectionProps, "currentStyle" | "setProperty" | "deleteProperty">
) => {
const { deleteProperty, setProperty, currentStyle } = props;
const outlineWidthValue = currentStyle[property]?.value;
const outlineStyleConfig = styleConfigByName(property);
const outlineStyleWidthKeywords = outlineStyleConfig.items.map((item) => ({
type: "keyword" as const,
value: item.name,
}));
return (
<Grid
css={{
gridTemplateColumns: `1fr ${theme.spacing[20]}`,
}}
gap={2}
>
<PropertyLabel
label="Width"
description={propertyDescriptions.outlineWidth}
properties={["outlineWidth"]}
/>
<CssValueInputContainer
key={property}
property={property}
styleSource={getStyleSource(currentStyle[property])}
keywords={outlineStyleWidthKeywords}
setValue={setProperty(property)}
deleteProperty={deleteProperty}
value={outlineWidthValue}
/>
</Grid>
);
};
@@ -1,13 +1,17 @@
import { Flex, Grid, theme, Box } from "@webstudio-is/design-system";
import { theme, Grid, Box } from "@webstudio-is/design-system";
import {
DashBorderIcon,
DashedBorderIcon,
DottedBorderIcon,
SmallXIcon,
} from "@webstudio-is/icons";
import { propertyDescriptions } from "@webstudio-is/css-data";
import type { StyleProperty } from "@webstudio-is/css-engine";
import { ColorControl } from "../../controls";
import { toValue, type StyleProperty } from "@webstudio-is/css-engine";
import { ColorControl, TextControl } from "../../controls";
import { StyleSection } from "../../shared/style-section";
import type { SectionProps } from "../shared/section";
import { OutlineStyle } from "./outline-style";
import { OutlineWidth } from "./outline-width";
import { OutlineOffset } from "./outline-offset";
import { PropertyLabel } from "../../property-label";
import { useComputedStyleDecl } from "../../shared/model";
import { ToggleGroupControl } from "../../controls/toggle-group/toggle-group-control";
export const properties = [
"outlineStyle",
@@ -16,50 +20,60 @@ export const properties = [
"outlineOffset",
] satisfies Array<StyleProperty>;
export const Section = (props: SectionProps) => {
const { currentStyle, setProperty, deleteProperty } = props;
const { outlineStyle } = currentStyle;
if (outlineStyle?.value.type !== "keyword") {
return;
}
export const Section = () => {
const outlineStyle = useComputedStyleDecl("outlineStyle");
const outlineStyleValue = toValue(outlineStyle.cascadedValue);
return (
<StyleSection label="Outline" properties={properties}>
<Flex direction="column" gap={2}>
<OutlineStyle />
{outlineStyle.value.value !== "none" && (
<Grid
css={{
// label gap (input gap expand)
gridTemplateColumns: `1fr calc(${theme.spacing[20]} + ${theme.spacing[5]} + ${theme.spacing[12]})`,
}}
gap={2}
>
<PropertyLabel
label="Style"
description={propertyDescriptions.outlineStyle}
properties={["outlineStyle"]}
/>
<Box css={{ justifySelf: "end" }}>
<ToggleGroupControl
label="Style"
properties={["outlineStyle"]}
items={[
{ child: <SmallXIcon />, value: "none" },
{ child: <DashBorderIcon />, value: "solid" },
{ child: <DashedBorderIcon />, value: "dashed" },
{ child: <DottedBorderIcon />, value: "dotted" },
]}
/>
</Box>
{outlineStyleValue !== "none" && (
<>
<Grid
css={{
gridTemplateColumns: `1fr ${theme.spacing[20]} ${theme.spacing[12]}`,
}}
gapX={2}
>
<PropertyLabel
label="Color"
description={propertyDescriptions.outlineColor}
properties={["outlineColor"]}
/>
<Box css={{ gridColumn: `span 2` }}>
<ColorControl property="outlineColor" />
</Box>
</Grid>
<OutlineWidth
currentStyle={currentStyle}
setProperty={setProperty}
deleteProperty={deleteProperty}
<PropertyLabel
label="Color"
description={propertyDescriptions.outlineColor}
properties={["outlineColor"]}
/>
<OutlineOffset
currentStyle={currentStyle}
setProperty={setProperty}
deleteProperty={deleteProperty}
<ColorControl property="outlineColor" />
<PropertyLabel
label="Width"
description={propertyDescriptions.outlineWidth}
properties={["outlineWidth"]}
/>
<TextControl property="outlineWidth" />
<PropertyLabel
label="Offset"
description={propertyDescriptions.outlineOffset}
properties={["outlineOffset"]}
/>
<TextControl property="outlineOffset" />
</>
)}
</Flex>
</Grid>
</StyleSection>
);
};