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 (