diff --git a/apps/builder/app/builder/features/style-panel/sections/grid-child/grid-child.tsx b/apps/builder/app/builder/features/style-panel/sections/grid-child/grid-child.tsx
index a68eb59bfc..47ba3e8f51 100644
--- a/apps/builder/app/builder/features/style-panel/sections/grid-child/grid-child.tsx
+++ b/apps/builder/app/builder/features/style-panel/sections/grid-child/grid-child.tsx
@@ -13,6 +13,7 @@ import {
} from "@webstudio-is/design-system";
import type { CssProperty, StyleValue } from "@webstudio-is/css-engine";
import { toValue } from "@webstudio-is/css-engine";
+import { parseGridAreas, type AreaInfo } from "@webstudio-is/css-data";
import { StyleSection } from "../../shared/style-section";
import { PropertyLabel } from "../../property-label";
import { ToggleGroupTooltip } from "../../controls/toggle-group/toggle-group-control";
@@ -30,8 +31,8 @@ import {
deleteProperty,
resetEphemeralStyles,
} from "../../shared/use-style-data";
-import { parseGridAreas } from "@webstudio-is/css-data";
import { getGridDimensions } from "../layout/shared/grid-areas";
+import { GridAreaPicker } from "../layout/shared/grid-area-picker";
import {
GridPositionInputs,
type GridPosition,
@@ -41,6 +42,7 @@ import { AlignSelfControl, JustifySelfControl } from "../shared/align-self";
import { OrderControl } from "../shared/order";
import { useStore } from "@nanostores/react";
import { $selectedInstancePath, selectInstance } from "~/shared/awareness";
+import { $isStylePanelGridVisible } from "~/builder/shared/nano-states";
import { ExternalLinkIcon } from "@webstudio-is/icons";
export const properties = [
@@ -112,6 +114,19 @@ const derivePositionMode = (
return "auto";
};
+/**
+ * Shows grid guides on the canvas while this component is mounted.
+ */
+const GridChildGuides = () => {
+ useEffect(() => {
+ $isStylePanelGridVisible.set(true);
+ return () => {
+ $isStylePanelGridVisible.set(false);
+ };
+ }, []);
+ return null;
+};
+
export const Section = () => {
const [columnStart, columnEnd, rowStart, rowEnd] = useComputedStyles([
"grid-column-start",
@@ -221,6 +236,7 @@ export const Section = () => {
)
}
>
+
{
batch.publish({ isEphemeral: true });
};
+ const handlePickerChange = (area: AreaInfo) => {
+ const newPosition: GridPosition = {
+ columnStart: area.columnStart,
+ columnEnd: area.columnEnd,
+ rowStart: area.rowStart,
+ rowEnd: area.rowEnd,
+ };
+ localValue.set(newPosition);
+ handleChange(newPosition);
+ localValue.save();
+ resetEphemeralStyles();
+ };
+
return (
-
-
- {
- localValue.save();
- resetEphemeralStyles();
+
+
+
+ {
+ localValue.save();
+ resetEphemeralStyles();
+ }}
+ gridColumns={gridColumns}
+ gridRows={gridRows}
+ />
+
+
-
+
);
};
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 edfcfdd696..0f26d00e0d 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
@@ -61,7 +61,7 @@ import { FlexAlignment } from "./shared/flex-alignment";
import { GridGenerator } from "./shared/grid-generator";
import { GridSettings } from "./shared/grid-settings";
import { GridAlignment } from "./shared/grid-alignment";
-import { $openGridEditorPanel } from "~/builder/shared/nano-states";
+import { $isStylePanelGridVisible } from "~/builder/shared/nano-states";
import { humanizeString } from "~/shared/string-utils";
import { DEFAULT_GRID_TRACK_COUNT, DEFAULT_GRID_GAP } from "./shared/constants";
@@ -573,21 +573,27 @@ const applyDefaultGridStyles = (columnsValue: string, rowsValue: string) => {
};
const LayoutSectionGrid = () => {
- const openPanel = useStore($openGridEditorPanel);
+ const [openPanel, setOpenPanel] = useState({
+ generator: false,
+ settings: false,
+ });
+
+ useEffect(() => {
+ $isStylePanelGridVisible.set(true);
+ return () => {
+ $isStylePanelGridVisible.set(false);
+ };
+ }, []);
return (
- $openGridEditorPanel.set({ ...openPanel, generator: open })
- }
+ onOpenChange={(open) => setOpenPanel({ ...openPanel, generator: open })}
/>
- $openGridEditorPanel.set({ ...openPanel, settings: open })
- }
+ onOpenChange={(open) => setOpenPanel({ ...openPanel, settings: open })}
/>
{
const instances = useStore($instances);
const scale = useStore($scale);
const clampingRect = useStore($clampingRect);
- const openGridEditorPanel = useStore($openGridEditorPanel);
+ const isStylePanelGridVisible = useStore($isStylePanelGridVisible);
if (!canvasToolsVisible) {
return;
@@ -86,9 +86,7 @@ export const CanvasTools = () => {
<>
{isPreviewMode === false && (
<>
- {(openGridEditorPanel.generator || openGridEditorPanel.settings) && (
-
- )}
+ {isStylePanelGridVisible && }
diff --git a/apps/builder/app/builder/shared/nano-states.ts b/apps/builder/app/builder/shared/nano-states.ts
index f59312ae81..ea7395e788 100644
--- a/apps/builder/app/builder/shared/nano-states.ts
+++ b/apps/builder/app/builder/shared/nano-states.ts
@@ -168,12 +168,6 @@ export type GridEditingArea = {
export const $gridEditingArea = atom(undefined);
-// Which grid editor panels are open.
-// Used to conditionally show grid guides on the canvas.
-export const $openGridEditorPanel = atom<{
- generator: boolean;
- settings: boolean;
-}>({
- generator: false,
- settings: false,
-});
+// Whether a grid-related section is visible in the style panel.
+// Grid guides are shown on the canvas when true.
+export const $isStylePanelGridVisible = atom(false);