mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-01 12:02:05 +00:00
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:
parent
5de8a8fbe8
commit
da73223f4a
1 changed files with 81 additions and 72 deletions
|
|
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue