From 392e1f0330834da8b24082ab803244ebccfef9de Mon Sep 17 00:00:00 2001 From: ciregenz Date: Fri, 31 Jul 2026 20:22:12 -0700 Subject: [PATCH] [eric] dock: split the four fixed action tiles out, DesktopDock had crossed the 300-line cap --- .../pages/Dashboard/desktop/DesktopDock.tsx | 42 +------------ .../Dashboard/desktop/DockActionTiles.tsx | 62 +++++++++++++++++++ 2 files changed, 65 insertions(+), 39 deletions(-) create mode 100644 frontend/src/app/pages/Dashboard/desktop/DockActionTiles.tsx 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;