diff --git a/packages/editor/src/components/editor/editor-layout-v2.tsx b/packages/editor/src/components/editor/editor-layout-v2.tsx index a30602a231..3adfdd0072 100644 --- a/packages/editor/src/components/editor/editor-layout-v2.tsx +++ b/packages/editor/src/components/editor/editor-layout-v2.tsx @@ -77,6 +77,11 @@ function LeftColumn({ // up to the minimum so the panel always returns to a usable size. const handleRailClick = useCallback( (id: string) => { + // noPanel tabs drive the stage, not the panel — leave collapse state alone. + if (tabs.find((t) => t.id === id)?.noPanel) { + setActivePanel(id) + return + } if (isCollapsed) { setIsCollapsed(false) if (width < SIDEBAR_MIN_WIDTH) setWidth(SIDEBAR_MIN_WIDTH) @@ -89,7 +94,7 @@ function LeftColumn({ } setActivePanel(id) }, - [isCollapsed, width, activePanel, setIsCollapsed, setWidth, setActivePanel], + [tabs, isCollapsed, width, activePanel, setIsCollapsed, setWidth, setActivePanel], ) useEffect(() => { @@ -126,7 +131,7 @@ function LeftColumn({ onIconClick={handleRailClick} tabs={tabs} /> - {!isCollapsed && ( + {!isCollapsed && !tabs.find((t) => t.id === activePanel)?.noPanel && (
!t.noPanel)} viewerContent={viewerContent} viewerToolbarLeft={viewerToolbarLeft} viewerToolbarRight={viewerToolbarRight} diff --git a/packages/editor/src/components/editor/index.tsx b/packages/editor/src/components/editor/index.tsx index 59f60bed43..1650377fd0 100644 --- a/packages/editor/src/components/editor/index.tsx +++ b/packages/editor/src/components/editor/index.tsx @@ -1393,12 +1393,13 @@ export default function Editor({ } const tabBarTabs = [ - ...(sidebarTabs?.map(({ id, label, mobileDefaultSnap, mobileIcon, icon }) => ({ + ...(sidebarTabs?.map(({ id, label, mobileDefaultSnap, mobileIcon, icon, noPanel }) => ({ id, label, mobileDefaultSnap, mobileIcon, icon, + noPanel, })) ?? []), // Host panels appear after the explicit tabs in the rail. The icon // doubles as the mobile icon; a half-height sheet is a sensible default. diff --git a/packages/editor/src/components/ui/sidebar/tab-bar.tsx b/packages/editor/src/components/ui/sidebar/tab-bar.tsx index 42bd61608e..8d86a1234b 100644 --- a/packages/editor/src/components/ui/sidebar/tab-bar.tsx +++ b/packages/editor/src/components/ui/sidebar/tab-bar.tsx @@ -13,6 +13,12 @@ export type SidebarTab = { mobileIcon?: ReactNode /** Desktop icon shown in the vertical rail (v2 layout). */ icon?: ReactNode + /** + * Rail entry that drives the stage instead of opening a sidebar panel: + * activating it hides the panel column (preserving its collapse state) and + * keeps the icon highlighted regardless of collapse. + */ + noPanel?: boolean } interface TabBarProps { @@ -75,7 +81,7 @@ export function IconRail({ tabs, activeTab, collapsed, onIconClick }: IconRailPr const pluginTabs = tabs.filter((tab) => pluginPanelIds.has(tab.id) || tab.id === 'plugins') const renderTab = (tab: SidebarTab) => { - const showActive = activeTab === tab.id && !collapsed + const showActive = activeTab === tab.id && (!collapsed || tab.noPanel === true) return (