diff --git a/apps/builder/app/builder/features/style-panel/sections/layout/layout.tsx b/apps/builder/app/builder/features/style-panel/sections/layout/layout.tsx
index 930d8abc28..ab4d2b5ca8 100644
--- a/apps/builder/app/builder/features/style-panel/sections/layout/layout.tsx
+++ b/apps/builder/app/builder/features/style-panel/sections/layout/layout.tsx
@@ -1,10 +1,11 @@
-import { useState } from "react";
+import { useState, type ReactNode } from "react";
import {
Box,
EnhancedTooltip,
Flex,
Grid,
SmallToggleButton,
+ Tooltip,
} from "@webstudio-is/design-system";
import { propertyDescriptions } from "@webstudio-is/css-data";
import type { StyleProperty, StyleValue } from "@webstudio-is/css-engine";
@@ -41,18 +42,18 @@ import type { SectionProps } from "../shared/section";
import { FlexGrid } from "./shared/flex-grid";
import { MenuControl, SelectControl } from "../../controls";
import { styleConfigByName } from "../../shared/configs";
-import type { CreateBatchUpdate } from "../../shared/use-style-data";
-import { getStyleSource, type StyleInfo } from "../../shared/style-info";
import { CollapsibleSection } from "../../shared/collapsible-section";
+import { createBatchUpdate, deleteProperty } from "../../shared/use-style-data";
import {
type IntermediateStyleValue,
CssValueInput,
} from "../../shared/css-value-input";
import { theme } from "@webstudio-is/design-system";
-import { TooltipContent } from "../../../style-panel/shared/property-name";
import { isFeatureEnabled } from "@webstudio-is/feature-flags";
import { ToggleControl } from "../../controls/toggle/toggle-control";
-import { PropertyLabel } from "../../property-label";
+import { PropertyInfo, PropertyLabel } from "../../property-label";
+import { useComputedStyles } from "../../shared/model";
+import type { ComputedStyleDecl } from "~/shared/style-object-model";
const GapLinked = ({
isLinked,
@@ -71,10 +72,58 @@ const GapLinked = ({
);
+const GapTooltip = ({
+ label,
+ styleDecl,
+ onReset,
+ children,
+}: {
+ label: string;
+ styleDecl: ComputedStyleDecl;
+ onReset: () => void;
+ children: ReactNode;
+}) => {
+ const [isOpen, setIsOpen] = useState(false);
+ const description =
+ propertyDescriptions[
+ styleDecl.property as keyof typeof propertyDescriptions
+ ];
+ return (
+ event.preventDefault()}
+ triggerProps={{
+ onClick: (event) => {
+ if (event.altKey) {
+ event.preventDefault();
+ onReset();
+ return;
+ }
+ },
+ }}
+ content={
+ {
+ onReset();
+ setIsOpen(false);
+ }}
+ />
+ }
+ >
+ {children}
+
+ );
+};
+
const GapInput = ({
icon,
- style,
property,
+ styleDecl,
intermediateValue,
onIntermediateChange,
onPreviewChange,
@@ -82,8 +131,8 @@ const GapInput = ({
onReset,
}: {
icon: JSX.Element;
- style: StyleInfo;
property: StyleProperty;
+ styleDecl: ComputedStyleDecl;
intermediateValue?: StyleValue | IntermediateStyleValue;
onIntermediateChange: (value?: StyleValue | IntermediateStyleValue) => void;
onPreviewChange: (value?: StyleValue) => void;
@@ -95,23 +144,14 @@ const GapInput = ({
return (
- }
- >
+
{icon}
-
+
}
property={property}
- value={style[property]?.value}
+ value={styleDecl.cascadedValue}
intermediateValue={intermediateValue}
keywords={items.map((item) => ({
type: "keyword",
@@ -146,20 +186,11 @@ const GapInput = ({
);
};
-const FlexGap = ({
- style,
- createBatchUpdate,
- deleteProperty,
-}: {
- style: StyleInfo;
- createBatchUpdate: CreateBatchUpdate;
- deleteProperty: SectionProps["deleteProperty"];
-}) => {
- const batchUpdate = createBatchUpdate();
-
- const [isLinked, setIsLinked] = useState(() => {
- return toValue(style.columnGap?.value) === toValue(style.rowGap?.value);
- });
+const FlexGap = () => {
+ const [columnGap, rowGap] = useComputedStyles(["columnGap", "rowGap"]);
+ const [isLinked, setIsLinked] = useState(
+ () => toValue(columnGap.cascadedValue) === toValue(rowGap.cascadedValue)
+ );
const [intermediateColumnGap, setIntermediateColumnGap] = useState<
StyleValue | IntermediateStyleValue
@@ -195,8 +226,8 @@ const FlexGap = ({
}}
/>
}
- style={style}
property="columnGap"
+ styleDecl={columnGap}
intermediateValue={intermediateColumnGap}
onIntermediateChange={(value) => {
setIntermediateColumnGap(value);
@@ -205,32 +236,35 @@ const FlexGap = ({
}
}}
onReset={() => {
- batchUpdate.deleteProperty("columnGap");
+ const batch = createBatchUpdate();
+ batch.deleteProperty("columnGap");
if (isLinked) {
- batchUpdate.deleteProperty("rowGap");
+ batch.deleteProperty("rowGap");
}
- batchUpdate.publish();
+ batch.publish();
}}
onPreviewChange={(value) => {
+ const batch = createBatchUpdate();
if (value === undefined) {
- batchUpdate.deleteProperty("columnGap");
+ batch.deleteProperty("columnGap");
if (isLinked) {
- batchUpdate.deleteProperty("rowGap");
+ batch.deleteProperty("rowGap");
}
} else {
- batchUpdate.setProperty("columnGap")(value);
+ batch.setProperty("columnGap")(value);
if (isLinked) {
- batchUpdate.setProperty("rowGap")(value);
+ batch.setProperty("rowGap")(value);
}
}
- batchUpdate.publish({ isEphemeral: true });
+ batch.publish({ isEphemeral: true });
}}
onChange={(value) => {
- batchUpdate.setProperty("columnGap")(value);
+ const batch = createBatchUpdate();
+ batch.setProperty("columnGap")(value);
if (isLinked) {
- batchUpdate.setProperty("rowGap")(value);
+ batch.setProperty("rowGap")(value);
}
- batchUpdate.publish();
+ batch.publish();
}}
/>
@@ -240,9 +274,23 @@ const FlexGap = ({
isLinked={isLinked}
onChange={(isLinked) => {
setIsLinked(isLinked);
- if (isLinked && style.columnGap?.value) {
- batchUpdate.setProperty("rowGap")(style.columnGap.value);
- batchUpdate.publish();
+ if (isLinked === false) {
+ return;
+ }
+ const isColumnGapDefined =
+ columnGap.source.name === "local" ||
+ columnGap.source.name === "overwritten";
+ const isRowGapDefined =
+ rowGap.source.name === "local" ||
+ rowGap.source.name === "overwritten";
+ if (isColumnGapDefined) {
+ const batch = createBatchUpdate();
+ batch.setProperty("rowGap")(columnGap.cascadedValue);
+ batch.publish();
+ } else if (isRowGapDefined) {
+ const batch = createBatchUpdate();
+ batch.setProperty("columnGap")(rowGap.cascadedValue);
+ batch.publish();
}
}}
/>
@@ -263,8 +311,8 @@ const FlexGap = ({
}}
/>
}
- style={style}
property="rowGap"
+ styleDecl={rowGap}
intermediateValue={intermediateRowGap}
onIntermediateChange={(value) => {
setIntermediateRowGap(value);
@@ -273,32 +321,35 @@ const FlexGap = ({
}
}}
onReset={() => {
- batchUpdate.deleteProperty("rowGap");
+ const batch = createBatchUpdate();
+ batch.deleteProperty("rowGap");
if (isLinked) {
- batchUpdate.deleteProperty("columnGap");
+ batch.deleteProperty("columnGap");
}
- batchUpdate.publish();
+ batch.publish();
}}
onPreviewChange={(value) => {
+ const batch = createBatchUpdate();
if (value === undefined) {
- batchUpdate.deleteProperty("rowGap");
+ batch.deleteProperty("rowGap");
if (isLinked) {
- batchUpdate.deleteProperty("columnGap");
+ batch.deleteProperty("columnGap");
}
} else {
- batchUpdate.setProperty("rowGap")(value);
+ batch.setProperty("rowGap")(value);
if (isLinked) {
- batchUpdate.setProperty("columnGap")(value);
+ batch.setProperty("columnGap")(value);
}
}
- batchUpdate.publish({ isEphemeral: true });
+ batch.publish({ isEphemeral: true });
}}
onChange={(value) => {
- batchUpdate.setProperty("rowGap")(value);
+ const batch = createBatchUpdate();
+ batch.setProperty("rowGap")(value);
if (isLinked) {
- batchUpdate.setProperty("columnGap")(value);
+ batch.setProperty("columnGap")(value);
}
- batchUpdate.publish();
+ batch.publish();
}}
/>
@@ -308,11 +359,9 @@ const FlexGap = ({
const LayoutSectionFlex = ({
currentStyle,
- deleteProperty,
createBatchUpdate,
}: {
currentStyle: SectionProps["currentStyle"];
- deleteProperty: SectionProps["deleteProperty"];
createBatchUpdate: SectionProps["createBatchUpdate"];
}) => {
const batchUpdate = createBatchUpdate();
@@ -410,11 +459,7 @@ const LayoutSectionFlex = ({
-
+
);
};
@@ -443,11 +488,7 @@ export const properties = [
"columnGap",
] satisfies Array;
-export const Section = ({
- currentStyle,
- deleteProperty,
- createBatchUpdate,
-}: SectionProps) => {
+export const Section = ({ currentStyle, createBatchUpdate }: SectionProps) => {
const value = toValue(currentStyle.display?.value);
return (
@@ -478,7 +519,6 @@ export const Section = ({
{(value === "flex" || value === "inline-flex") && (
)}