fix(desktop): show statusbar item tooltips on hover

Statusbar items declared a 'title' string (e.g. YOLO, gateway health,
agents, cron, version, context usage) that was populated by
use-statusbar-items.tsx but never forwarded to the rendered DOM in
StatusbarControls — so every statusbar button/menu/text/link had no
hover hint.

Wrap the four render branches (menu trigger, text, link, action) in
the existing 'Tip' component from components/ui/tooltip.tsx. Tip is
self-contained (carries its own Provider), instant (delayDuration=0),
themed (bg-foreground/text-background, auto-inverts per theme), and
already in use elsewhere in the desktop shell. Renders the child
untouched when label is falsy, so items without a title stay
zero-cost.
This commit is contained in:
David Metcalfe 2026-06-21 10:27:16 -07:00 committed by ethernet
parent 5de8a8fbe8
commit da73223f4a

View file

@ -2,6 +2,7 @@ import type { ComponentProps, ReactNode } from 'react'
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu' import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'
import { Tip } from '@/components/ui/tooltip'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
// Shared chrome styling for interactive statusbar items (button / link / menu // Shared chrome styling for interactive statusbar items (button / link / menu
@ -97,93 +98,101 @@ function StatusbarItemView({ item, navigate }: { item: StatusbarItem; navigate:
if (item.variant === 'menu' && (item.menuContent || (item.menuItems && item.menuItems.length > 0))) { if (item.variant === 'menu' && (item.menuContent || (item.menuItems && item.menuItems.length > 0))) {
return ( return (
<DropdownMenu> <Tip label={item.title}>
<DropdownMenuTrigger asChild> <DropdownMenu>
<button className={cn(STATUSBAR_ACTION_CLASS, item.className)} disabled={item.disabled} type="button"> <DropdownMenuTrigger asChild>
{content} <button className={cn(STATUSBAR_ACTION_CLASS, item.className)} disabled={item.disabled} type="button">
</button> {content}
</DropdownMenuTrigger> </button>
<DropdownMenuContent </DropdownMenuTrigger>
align={item.menuAlign ?? 'start'} <DropdownMenuContent
className={cn('w-56', item.menuContent && 'p-0', item.menuClassName)} align={item.menuAlign ?? 'start'}
side="top" className={cn('w-56', item.menuContent && 'p-0', item.menuClassName)}
sideOffset={8} side="top"
> sideOffset={8}
{item.menuContent >
? item.menuContent {item.menuContent
: (item.menuItems ?? []) ? item.menuContent
.filter(menuItem => !menuItem.hidden) : (item.menuItems ?? [])
.map(menuItem => ( .filter(menuItem => !menuItem.hidden)
<DropdownMenuItem .map(menuItem => (
className={cn('gap-2 text-foreground focus:bg-accent [&_svg]:size-4', menuItem.className)} <DropdownMenuItem
disabled={menuItem.disabled} className={cn('gap-2 text-foreground focus:bg-accent [&_svg]:size-4', menuItem.className)}
key={menuItem.id} disabled={menuItem.disabled}
onSelect={() => { key={menuItem.id}
if (menuItem.to) { onSelect={() => {
navigate(menuItem.to) if (menuItem.to) {
} navigate(menuItem.to)
}
menuItem.onSelect?.() menuItem.onSelect?.()
}} }}
> >
{menuItem.href ? ( {menuItem.href ? (
<a <a
className="inline-flex w-full items-center gap-2" className="inline-flex w-full items-center gap-2"
href={menuItem.href} href={menuItem.href}
rel="noreferrer" rel="noreferrer"
target="_blank" target="_blank"
> >
{menuItem.icon} {menuItem.icon}
<span className="truncate">{menuItem.label}</span> <span className="truncate">{menuItem.label}</span>
</a> </a>
) : ( ) : (
<> <>
{menuItem.icon} {menuItem.icon}
<span className="truncate">{menuItem.label}</span> <span className="truncate">{menuItem.label}</span>
</> </>
)} )}
</DropdownMenuItem> </DropdownMenuItem>
))} ))}
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
</Tip>
) )
} }
if (item.variant === 'text' && !item.onSelect && !item.to && !item.href) { if (item.variant === 'text' && !item.onSelect && !item.to && !item.href) {
return ( return (
<div <Tip label={item.title}>
className={cn( <div
'inline-flex h-full items-center gap-1 px-1.5 text-[0.6875rem] text-(--ui-text-tertiary)', className={cn(
item.className 'inline-flex h-full items-center gap-1 px-1.5 text-[0.6875rem] text-(--ui-text-tertiary)',
)} item.className
> )}
{content} >
</div> {content}
</div>
</Tip>
) )
} }
if (item.href || item.variant === 'link') { if (item.href || item.variant === 'link') {
return ( return (
<a className={cn(STATUSBAR_ACTION_CLASS, item.className)} href={item.href} rel="noreferrer" target="_blank"> <Tip label={item.title}>
{content} <a className={cn(STATUSBAR_ACTION_CLASS, item.className)} href={item.href} rel="noreferrer" target="_blank">
</a> {content}
</a>
</Tip>
) )
} }
return ( return (
<button <Tip label={item.title}>
className={cn(STATUSBAR_ACTION_CLASS, item.className)} <button
disabled={item.disabled} className={cn(STATUSBAR_ACTION_CLASS, item.className)}
onClick={event => { disabled={item.disabled}
if (item.to) { onClick={event => {
navigate(item.to) if (item.to) {
} navigate(item.to)
}
item.onSelect?.({ shiftKey: event.shiftKey }) item.onSelect?.({ shiftKey: event.shiftKey })
}} }}
type="button" type="button"
> >
{content} {content}
</button> </button>
</Tip>
) )
} }