diff --git a/frontend/src/app/pages/Dashboard/DashboardToolbar.tsx b/frontend/src/app/pages/Dashboard/DashboardToolbar.tsx index dfa27b66..28bca414 100644 --- a/frontend/src/app/pages/Dashboard/DashboardToolbar.tsx +++ b/frontend/src/app/pages/Dashboard/DashboardToolbar.tsx @@ -9,10 +9,10 @@ import { styled } from '@mui/material/styles'; import AddRounded from '@mui/icons-material/AddRounded'; import HistoryRounded from '@mui/icons-material/HistoryRounded'; -// Custom rounded speech bubble with a small tail at the bottom-left, -// outlined in currentColor with the bubble interior knocked out so the -// orange button fill shows through. Matches Image #57 exactly; MUI's -// rounded chat icons are either filled or tail-less. +// Custom near-circular speech bubble with a teardrop tail at the +// bottom-left. The bubble body is a rounded square with corner radius +// ~half the body size, so it reads as a circle. Matches Image #57; MUI +// rounded chat glyphs either fill the bubble or omit the tail. function ChatBubbleTeardrop(props: { sx?: { fontSize?: number } }) { const size = props.sx?.fontSize ?? 18; return ( @@ -22,7 +22,7 @@ function ChatBubbleTeardrop(props: { sx?: { fontSize?: number } }) { strokeLinecap="round" strokeLinejoin="round" style={{ display: 'block' }} > - + ); } @@ -406,52 +406,61 @@ const DashboardToolbar = React.forwardRef( return ( <> {(inputOpen || historyOpen) && ( - // Image #54: paired mode pills float above the composer/popover. - // `+ New Chat` is decorative-active while inputOpen; clicking it - // from history mode closes the popover and re-focuses the input. - // `History` toggles the SchedulePopover. - + // Image #54: paired mode pills above the composer/popover. + // The two states are mutually exclusive: opening one closes the + // other so the body underneath only renders one thing at a time. + { - if (historyOpen) handleCloseHistory(); - if (!inputOpen) onNewAgent(); + if (historyOpen) { + handleCloseHistory(); + onNewAgent(); + } + // If already in inputOpen, this is a no-op (we're already + // in new chat). The visible active styling tells the user + // that. Clicking again does nothing intentionally. }} role="button" sx={{ - display: 'inline-flex', alignItems: 'center', gap: 0.4, - fontSize: '0.82rem', fontWeight: 600, + display: 'inline-flex', alignItems: 'center', gap: 0.3, + fontSize: '0.74rem', fontWeight: 600, color: c.text.primary, bgcolor: c.bg.surface, border: `1px solid ${inputOpen && !historyOpen ? c.border.medium : c.border.subtle}`, boxShadow: inputOpen && !historyOpen ? c.shadow.sm : 'none', - px: 1.1, py: 0.45, borderRadius: 999, - cursor: 'pointer', - '&:hover': { bgcolor: c.bg.elevated }, + px: 0.85, py: 0.3, borderRadius: 999, + cursor: historyOpen ? 'pointer' : 'default', + '&:hover': historyOpen ? { bgcolor: c.bg.elevated } : {}, }}> - + New Chat { - if (historyOpen) handleCloseHistory(); - else { - setPopoverMode('search'); - setHistoryOpen(true); + if (historyOpen) { + handleCloseHistory(); + return; } + // Close the composer first; inputOpen takes precedence in + // the render branch below so the popover would be hidden + // behind it otherwise. + if (inputOpen) onCancel(); + setPopoverMode('search'); + setHistoryOpen(true); }} role="button" sx={{ - display: 'inline-flex', alignItems: 'center', gap: 0.4, - fontSize: '0.82rem', fontWeight: 600, + display: 'inline-flex', alignItems: 'center', gap: 0.3, + fontSize: '0.74rem', fontWeight: 600, color: historyOpen ? c.text.primary : c.text.secondary, bgcolor: c.bg.surface, border: `1px solid ${historyOpen ? c.border.medium : c.border.subtle}`, boxShadow: historyOpen ? c.shadow.sm : 'none', - px: 1.1, py: 0.45, borderRadius: 999, + px: 0.85, py: 0.3, borderRadius: 999, cursor: 'pointer', '&:hover': { bgcolor: c.bg.elevated }, }}> - + History