feat: Standardize bottom bar component styling and add responsive design

- Add consistent text labels to all bottom bar components:
  - Action button: now shows 'Actions' text
  - Attach button: now shows 'Attach' text
  - Goosehints button: now shows 'Hints' text
  - All components now follow icon + text pattern

- Standardize spacing across all bottom bar components:
  - Display components (Directory, Cost, Model, Mode): px-1 padding
  - Action buttons (Actions, Attach, Hints): px-0 padding
  - Consistent visual hierarchy based on component behavior

- Add responsive design at 1050px breakpoint:
  - Under 1050px: Show icons only for compact mobile/tablet view
  - 1050px and above: Show icons + text for desktop view
  - Smooth transitions with proper icon spacing adjustments

- Improve visual consistency:
  - Uniform hover states and transitions
  - Consistent icon sizing (w-4 h-4) and spacing (mr-1)
  - Professional appearance across all screen sizes

Components updated:
- ChatInput.tsx - Action, Attach, and Hints buttons
- DirSwitcher.tsx - Directory display
- CostTracker.tsx - Cost display
- ModelsBottomBar.tsx - Model selector
- BottomMenuModeSelection.tsx - Mode selector
This commit is contained in:
spencrmartin
2025-09-24 16:17:48 -04:00
parent e28db8b139
commit 8bae7fdbe4
5 changed files with 42 additions and 43 deletions
+26 -27
View File
@@ -1665,7 +1665,7 @@ export default function ChatInput({
{/* Secondary actions and controls row below input */}
<div className="flex flex-row items-center gap-1 p-2 relative">
{/* Directory path */}
<DirSwitcher className="mr-0" />
<DirSwitcher />
<div className="w-px h-4 bg-border-default mx-2" />
{/* Action button */}
@@ -1676,9 +1676,10 @@ export default function ChatInput({
onClick={handleActionButtonClick}
variant="ghost"
size="sm"
className="flex items-center justify-center text-text-default/70 hover:text-text-default text-xs cursor-pointer transition-colors"
className="flex items-center text-text-default/70 hover:text-text-default text-xs cursor-pointer transition-colors px-0"
>
<Action className="w-4 h-4" />
<Action className="w-4 h-4 min-[1050px]:mr-1" />
<span className="text-xs hidden min-[1050px]:inline">Actions</span>
</Button>
</TooltipTrigger>
<TooltipContent>Quick Actions</TooltipContent>
@@ -1693,9 +1694,10 @@ export default function ChatInput({
onClick={handleFileSelect}
variant="ghost"
size="sm"
className="flex items-center justify-center text-text-default/70 hover:text-text-default text-xs cursor-pointer transition-colors"
className="flex items-center text-text-default/70 hover:text-text-default text-xs cursor-pointer transition-colors px-0"
>
<Attach className="w-4 h-4" />
<Attach className="w-4 h-4 min-[1050px]:mr-1" />
<span className="text-xs hidden min-[1050px]:inline">Attach</span>
</Button>
</TooltipTrigger>
<TooltipContent>Attach file or directory</TooltipContent>
@@ -1707,13 +1709,11 @@ export default function ChatInput({
{/* Cost Tracker */}
{COST_TRACKING_ENABLED && (
<>
<div className="flex items-center h-full ml-1 mr-1">
<CostTracker
inputTokens={inputTokens}
outputTokens={outputTokens}
sessionCosts={sessionCosts}
/>
</div>
<CostTracker
inputTokens={inputTokens}
outputTokens={outputTokens}
sessionCosts={sessionCosts}
/>
</>
)}
<Tooltip>
@@ -1731,21 +1731,20 @@ export default function ChatInput({
<div className="w-px h-4 bg-border-default mx-2" />
<BottomMenuModeSelection />
<div className="w-px h-4 bg-border-default mx-2" />
<div className="flex items-center h-full">
<Tooltip>
<TooltipTrigger asChild>
<Button
onClick={() => setIsGoosehintsModalOpen?.(true)}
variant="ghost"
size="sm"
className="flex items-center justify-center text-text-default/70 hover:text-text-default text-xs cursor-pointer"
>
<FolderKey size={16} />
</Button>
</TooltipTrigger>
<TooltipContent>Configure goosehints</TooltipContent>
</Tooltip>
</div>
<Tooltip>
<TooltipTrigger asChild>
<Button
onClick={() => setIsGoosehintsModalOpen?.(true)}
variant="ghost"
size="sm"
className="flex items-center text-text-default/70 hover:text-text-default text-xs cursor-pointer transition-colors px-0"
>
<FolderKey size={16} className="min-[1050px]:mr-1" />
<span className="text-xs hidden min-[1050px]:inline">Hints</span>
</Button>
</TooltipTrigger>
<TooltipContent>Configure goosehints</TooltipContent>
</Tooltip>
</div>
<MentionPopover
@@ -56,10 +56,10 @@ export const BottomMenuModeSelection = () => {
<div title={`Current mode: ${getValueByKey(gooseMode)} - ${getModeDescription(gooseMode)}`}>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<span className="flex items-center cursor-pointer [&_svg]:size-4 text-text-default/70 hover:text-text-default hover:scale-100 hover:bg-transparent text-xs">
<Tornado className="mr-1 h-4 w-4" />
{getValueByKey(gooseMode).toLowerCase()}
</span>
<button className="flex items-center cursor-pointer text-text-default/70 hover:text-text-default transition-colors text-xs px-1">
<Tornado className="min-[1050px]:mr-1 h-4 w-4" />
<span className="text-xs hidden min-[1050px]:inline">{getValueByKey(gooseMode)}</span>
</button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-64" side="top" align="center">
{all_goose_modes.map((mode) => (
@@ -185,8 +185,8 @@ export function CostTracker({ inputTokens = 0, outputTokens = 0, sessionCosts }:
if (isLoading) {
return (
<>
<div className="flex items-center justify-center h-full text-textSubtle translate-y-[1px]">
<span className="text-xs font-mono">...</span>
<div className="flex items-center justify-center h-full text-textSubtle translate-y-[1px] px-1">
<span className="text-xs font-mono hidden min-[1050px]:inline">...</span>
</div>
<div className="w-px h-4 bg-border-default mx-2" />
</>
@@ -205,9 +205,9 @@ export function CostTracker({ inputTokens = 0, outputTokens = 0, sessionCosts }:
<>
<Tooltip>
<TooltipTrigger asChild>
<div className="flex items-center justify-center h-full text-text-default/70 hover:text-text-default transition-colors cursor-default translate-y-[1px]">
<div className="flex items-center justify-center h-full text-text-default/70 hover:text-text-default transition-colors cursor-default translate-y-[1px] px-1">
<CoinIcon className="mr-1" size={16} />
<span className="text-xs font-mono">0.0000</span>
<span className="text-xs font-mono hidden min-[1050px]:inline">0.0000</span>
</div>
</TooltipTrigger>
<TooltipContent>
@@ -234,7 +234,7 @@ export function CostTracker({ inputTokens = 0, outputTokens = 0, sessionCosts }:
<TooltipTrigger asChild>
<div className="flex items-center justify-center h-full transition-colors cursor-default translate-y-[1px] text-text-default/70 hover:text-text-default">
<CoinIcon className="mr-1" size={16} />
<span className="text-xs font-mono">0.0000</span>
<span className="text-xs font-mono hidden min-[1050px]:inline">0.0000</span>
</div>
</TooltipTrigger>
<TooltipContent>{getUnavailableTooltip()}</TooltipContent>
@@ -291,7 +291,7 @@ export function CostTracker({ inputTokens = 0, outputTokens = 0, sessionCosts }:
<TooltipTrigger asChild>
<div className="flex items-center justify-center h-full transition-colors cursor-default translate-y-[1px] text-text-default/70 hover:text-text-default">
<CoinIcon className="mr-1" size={16} />
<span className="text-xs font-mono">{formatCost(totalCost)}</span>
<span className="text-xs font-mono hidden min-[1050px]:inline">{formatCost(totalCost)}</span>
</div>
</TooltipTrigger>
<TooltipContent>{getTooltipContent()}</TooltipContent>
@@ -31,11 +31,11 @@ export const DirSwitcher: React.FC<DirSwitcherProps> = ({ className = '' }) => {
<Tooltip open={isTooltipOpen} onOpenChange={setIsTooltipOpen}>
<TooltipTrigger asChild>
<button
className={`z-[100] hover:cursor-pointer text-text-default/70 hover:text-text-default text-xs flex items-center transition-colors pl-1 [&>svg]:size-4 ${className}`}
className={`z-[100] hover:cursor-pointer text-text-default/70 hover:text-text-default text-xs flex items-center transition-colors px-1 [&>svg]:size-4 ${className}`}
onClick={handleDirectoryClick}
>
<FolderDot className="mr-1" size={16} />
<div className="max-w-[200px] truncate [direction:rtl]">
<FolderDot className="min-[1050px]:mr-1" size={16} />
<div className="max-w-[200px] truncate [direction:rtl] hidden min-[1050px]:block">
{String(window.appConfig.get('GOOSE_WORKING_DIR'))}
</div>
</button>
@@ -228,10 +228,10 @@ export default function ModelsBottomBar({
<div className="relative flex items-center" ref={dropdownRef}>
<BottomMenuAlertPopover alerts={alerts} />
<DropdownMenu>
<DropdownMenuTrigger className="flex items-center hover:cursor-pointer max-w-[180px] md:max-w-[200px] lg:max-w-[380px] min-w-0 text-text-default/70 hover:text-text-default transition-colors">
<DropdownMenuTrigger className="flex items-center hover:cursor-pointer max-w-[180px] md:max-w-[200px] lg:max-w-[380px] min-w-0 text-text-default/70 hover:text-text-default transition-colors px-1">
<div className="flex items-center truncate max-w-[130px] md:max-w-[200px] lg:max-w-[360px] min-w-0">
<Bot className="mr-1 h-4 w-4 flex-shrink-0" />
<span className="truncate text-xs">
<Bot className="min-[1050px]:mr-1 h-4 w-4 flex-shrink-0" />
<span className="truncate text-xs hidden min-[1050px]:inline">
{displayModel}
{isLeadWorkerActive && modelMode && (
<span className="ml-1 text-[10px] opacity-60">({modelMode})</span>