diff --git a/packages/studio/src/components/editor/propertyPanelFlatLayoutSection.test.tsx b/packages/studio/src/components/editor/propertyPanelFlatLayoutSection.test.tsx
index db80e32ba..827f9fad4 100644
--- a/packages/studio/src/components/editor/propertyPanelFlatLayoutSection.test.tsx
+++ b/packages/studio/src/components/editor/propertyPanelFlatLayoutSection.test.tsx
@@ -3,7 +3,11 @@
import React, { act } from "react";
import { createRoot } from "react-dom/client";
import { afterEach, describe, expect, it, vi } from "vitest";
-import { LayoutGeometryRows } from "./propertyPanelFlatLayoutSection";
+import {
+ LayoutFlexBlock,
+ LayoutGeometryRows,
+ LayoutZIndexRow,
+} from "./propertyPanelFlatLayoutSection";
(globalThis as unknown as { IS_REACT_ACT_ENVIRONMENT: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
@@ -107,3 +111,55 @@ describe("LayoutGeometryRows", () => {
act(() => root.unmount());
});
});
+
+describe("LayoutZIndexRow", () => {
+ it("renders the current z-index at the default tier and commits edits", () => {
+ const onSetStyle = vi.fn();
+ const { host, root } = renderInto(
+ ,
+ );
+ expect(host.textContent).toContain("Z-index");
+ const input = host.querySelector("input");
+ if (!input) throw new Error("expected an input");
+ expect(input.value).toBe("3");
+ const setter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")!.set!;
+ act(() => {
+ setter.call(input, "5");
+ input.dispatchEvent(new Event("input", { bubbles: true }));
+ input.dispatchEvent(new Event("focusout", { bubbles: true }));
+ });
+ expect(onSetStyle).toHaveBeenCalledWith("z-index", "5");
+ act(() => root.unmount());
+ });
+});
+
+describe("LayoutFlexBlock", () => {
+ it("renders nothing when the element is not flex", () => {
+ const { host, root } = renderInto(
+ ,
+ );
+ expect(host.textContent).toBe("");
+ act(() => root.unmount());
+ });
+
+ it("renders direction/justify/align/gap and commits a direction change", () => {
+ const onSetStyle = vi.fn();
+ const { host, root } = renderInto(
+ ,
+ );
+ expect(host.textContent).toContain("Flex");
+ const columnOption = Array.from(host.querySelectorAll('[data-flat-segment="true"]')).find(
+ (el) => el.textContent === "Column",
+ );
+ if (!columnOption) throw new Error("expected a Column segment option");
+ act(() =>
+ (columnOption as HTMLElement).dispatchEvent(new MouseEvent("click", { bubbles: true })),
+ );
+ expect(onSetStyle).toHaveBeenCalledWith("flex-direction", "column");
+ act(() => root.unmount());
+ });
+});
diff --git a/packages/studio/src/components/editor/propertyPanelFlatLayoutSection.tsx b/packages/studio/src/components/editor/propertyPanelFlatLayoutSection.tsx
index d5c8d5db9..477893d4e 100644
--- a/packages/studio/src/components/editor/propertyPanelFlatLayoutSection.tsx
+++ b/packages/studio/src/components/editor/propertyPanelFlatLayoutSection.tsx
@@ -1,7 +1,8 @@
-import { FlatRow } from "./propertyPanelFlatPrimitives";
+import { FlatRow, FlatSegmentedRow, FlatSelectRow } from "./propertyPanelFlatPrimitives";
import { KeyframeNavigation } from "./KeyframeNavigation";
import { formatPxMetricValue } from "./propertyPanelHelpers";
import { STUDIO_KEYFRAMES_ENABLED } from "./manualEditingAvailability";
+import { resolveValueTier } from "./propertyPanelValueTier";
type KeyframeEntry = Array<{
percentage: number;
@@ -156,3 +157,81 @@ export function LayoutGeometryRows({
>
);
}
+
+export function LayoutZIndexRow({
+ styles,
+ onSetStyle,
+}: {
+ styles: Record;
+ onSetStyle: (prop: string, value: string) => void | Promise;
+}) {
+ const zIndex = String(parseInt(styles["z-index"] || "auto", 10) || 0);
+ return (
+ void onSetStyle("z-index", next)}
+ />
+ );
+}
+
+export function LayoutFlexBlock({
+ styles,
+ onSetStyle,
+ disabled,
+}: {
+ styles: Record;
+ onSetStyle: (prop: string, value: string) => void | Promise;
+ disabled: boolean;
+}) {
+ const isFlex = styles.display === "flex" || styles.display === "inline-flex";
+ if (!isFlex) return null;
+ const direction = styles["flex-direction"] || "row";
+ return (
+
+
+ Flex
+
+
void onSetStyle("flex-direction", next)}
+ />
+ void onSetStyle("justify-content", next)}
+ />
+ void onSetStyle("align-items", next)}
+ />
+ void onSetStyle("gap", next.endsWith("px") ? next : `${next}px`)}
+ />
+
+ );
+}