diff --git a/frontend/src/app/pages/Dashboard/desktop/DesktopDock.tsx b/frontend/src/app/pages/Dashboard/desktop/DesktopDock.tsx
index 5b696dc1..9e466d69 100644
--- a/frontend/src/app/pages/Dashboard/desktop/DesktopDock.tsx
+++ b/frontend/src/app/pages/Dashboard/desktop/DesktopDock.tsx
@@ -1,13 +1,7 @@
import React, { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
import Box from '@mui/material/Box';
-import Tooltip from '@mui/material/Tooltip';
-import LanguageIcon from '@mui/icons-material/Language';
-import EventRepeatIcon from '@mui/icons-material/EventRepeat';
import KeyboardArrowUpRoundedIcon from '@mui/icons-material/KeyboardArrowUpRounded';
import KeyboardArrowDownRoundedIcon from '@mui/icons-material/KeyboardArrowDownRounded';
-import { openSettingsCard, openWorkflowsApp } from '@/shared/state/dashboardLayoutSlice';
-import SettingsIcon from '@mui/icons-material/Settings';
-import AppsRoundedIcon from '@mui/icons-material/AppsRounded';
import { useAppDispatch } from '@/shared/hooks';
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
import { getWebview } from '@/shared/browserRegistry';
@@ -16,6 +10,7 @@ import { openCardContextMenu } from './openCardContextMenu';
import { dockTileMenuRows } from './dockTileMenuRows';
import { useDockLayout } from './useDockLayout';
import { DockTileIcon } from './DockTileIcon';
+import DockActionTiles, { DOCK_ACTION_COUNT } from './DockActionTiles';
import DockHoverPreview from './DockHoverPreview';
import type { AgentSession } from '@/shared/state/agentsSlice';
import type {
@@ -39,7 +34,6 @@ interface DesktopDockProps {
onAddBrowser: () => void;
}
-const ACTION_COUNT = 4;
const CARET_H = 13;
/** Left-edge desktop dock: one tile per open card, hover previews, click focuses the window. */
@@ -69,7 +63,7 @@ function DesktopDock({
const { dockRef, scrollRef, tile, gap, iconSize, scrolls, scrollHeight, bleed, applyMagnify } = useDockLayout({
cardCount: entries.length,
- actionCount: ACTION_COUNT,
+ actionCount: DOCK_ACTION_COUNT,
dividerCount: entries.length > 0 ? 2 : 1,
});
@@ -240,37 +234,7 @@ function DesktopDock({
{entries.length > 0 && (
)}
- {/* The og toolbar's actions, dock-resident: browser, workflow, then settings + apps below their own divider. New-chat lives in the spawn pill, history on the top island. */}
- {([
- { label: 'New browser', icon: , act: onAddBrowser },
- { label: 'Workflows', icon: , act: () => dispatch(openWorkflowsApp()) },
- { label: 'Settings', icon: , act: () => dispatch(openSettingsCard()), divider: true },
- { label: 'Applications', icon: , act: onApplications, bg: 'linear-gradient(135deg, #3d3d46, #232329)' },
- ] as { label: string; icon: React.ReactNode; act: () => void; divider?: boolean; bg?: string }[]).map((a) => (
-
- {a.divider && }
-
-
- {a.icon}
-
-
-
- ))}
+
{/* Anchored to the root's padding box, whose top edge IS the scroll box's top edge. */}
{carets.map((c) => (
diff --git a/frontend/src/app/pages/Dashboard/desktop/DockActionTiles.tsx b/frontend/src/app/pages/Dashboard/desktop/DockActionTiles.tsx
new file mode 100644
index 00000000..c553a23d
--- /dev/null
+++ b/frontend/src/app/pages/Dashboard/desktop/DockActionTiles.tsx
@@ -0,0 +1,62 @@
+import React from 'react';
+import Box from '@mui/material/Box';
+import Tooltip from '@mui/material/Tooltip';
+import LanguageIcon from '@mui/icons-material/Language';
+import EventRepeatIcon from '@mui/icons-material/EventRepeat';
+import SettingsIcon from '@mui/icons-material/Settings';
+import AppsRoundedIcon from '@mui/icons-material/AppsRounded';
+import { useAppDispatch } from '@/shared/hooks';
+import { openSettingsCard, openWorkflowsApp } from '@/shared/state/dashboardLayoutSlice';
+
+// The dock reserves room for these before it knows what they are, so the count lives with the list.
+export const DOCK_ACTION_COUNT = 4;
+
+interface DockActionTilesProps {
+ tile: number;
+ onAddBrowser: () => void;
+ onApplications: () => void;
+ onHoverAway: () => void;
+}
+
+/** The dock's fixed group: browser, workflows, then settings + applications under their own divider. */
+function DockActionTiles({ tile, onAddBrowser, onApplications, onHoverAway }: DockActionTilesProps): React.ReactElement {
+ const dispatch = useAppDispatch();
+ const actions: { label: string; icon: React.ReactNode; act: () => void; divider?: boolean; bg?: string }[] = [
+ { label: 'New browser', icon: , act: onAddBrowser },
+ { label: 'Workflows', icon: , act: () => dispatch(openWorkflowsApp()) },
+ { label: 'Settings', icon: , act: () => dispatch(openSettingsCard()), divider: true },
+ { label: 'Applications', icon: , act: onApplications, bg: 'linear-gradient(135deg, #3d3d46, #232329)' },
+ ];
+
+ return (
+ <>
+ {actions.map((a) => (
+
+ {a.divider && }
+
+
+ {a.icon}
+
+
+
+ ))}
+ >
+ );
+}
+
+export default DockActionTiles;