From 31849d62e2cba67a08b8a4da1c2f496a57f77474 Mon Sep 17 00:00:00 2001 From: Vance Ingalls Date: Thu, 9 Jul 2026 17:31:23 -0700 Subject: [PATCH] feat(studio): add PinnedGroupRow always-open pinned-group primitive --- .../propertyPanelFlatPrimitives.test.tsx | 19 ++++++++ .../editor/propertyPanelFlatPrimitives.tsx | 44 +++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/packages/studio/src/components/editor/propertyPanelFlatPrimitives.test.tsx b/packages/studio/src/components/editor/propertyPanelFlatPrimitives.test.tsx index 6ff132760..dccf1aa23 100644 --- a/packages/studio/src/components/editor/propertyPanelFlatPrimitives.test.tsx +++ b/packages/studio/src/components/editor/propertyPanelFlatPrimitives.test.tsx @@ -10,6 +10,7 @@ import { FlatSelectRow, FlatSlider, FlatToggle, + PinnedGroupRow, PinnedZoneDivider, } from "./propertyPanelFlatPrimitives"; @@ -456,3 +457,21 @@ describe("FlatToggle", () => { act(() => root.unmount()); }); }); + +describe("PinnedGroupRow", () => { + it("renders a 'Pinned' badge, filled pin icon, and always shows children", () => { + const onUnpin = vi.fn(); + const { host, root } = renderInto( + +
body
+
, + ); + expect(host.textContent).toContain("Pinned"); + expect(host.textContent).toContain("Motion"); + expect(host.querySelector('[data-testid="body"]')).not.toBeNull(); + const unpin = host.querySelector('[data-pinned-group-unpin="true"]'); + act(() => unpin?.dispatchEvent(new MouseEvent("click", { bubbles: true }))); + expect(onUnpin).toHaveBeenCalledTimes(1); + act(() => root.unmount()); + }); +}); diff --git a/packages/studio/src/components/editor/propertyPanelFlatPrimitives.tsx b/packages/studio/src/components/editor/propertyPanelFlatPrimitives.tsx index 078845bd1..21f02295f 100644 --- a/packages/studio/src/components/editor/propertyPanelFlatPrimitives.tsx +++ b/packages/studio/src/components/editor/propertyPanelFlatPrimitives.tsx @@ -449,3 +449,47 @@ export function FlatToggle({ ); } + +/* ------------------------------------------------------------------ */ +/* PinnedGroupRow — always-open pinned group (design_handoff #8a) */ +/* ------------------------------------------------------------------ */ + +export function PinnedGroupRow({ + title, + accessory, + onUnpin, + children, +}: { + title: string; + accessory?: ReactNode; + onUnpin: () => void; + children: ReactNode; +}) { + return ( +
+
+ + + Pinned + + {title} + + + {accessory} + + +
+ {children} +
+ ); +}