fix(analytics): collapse profile-scope disclaimer into tooltip icon

The disclaimer paragraph rendered as a two-line block under the
controls row, eating vertical real-estate while the cards stayed
empty. Replace it with a small Info icon beside the profile
dropdown that surfaces the same copy in a tooltip on hover/focus.

- Same copy preserved verbatim; no informational loss
- Icon only renders when a non-All profile is selected
- Reclaims ~32px of vertical space on the analytics header

Closes #1390
This commit is contained in:
Tam Nhu Tran
2026-05-23 23:40:02 -04:00
parent 0a482bd2d3
commit 9130c7d869
3 changed files with 38 additions and 22 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

@@ -15,8 +15,9 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { RefreshCw } from 'lucide-react';
import { Info, RefreshCw } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import type { AnalyticsProfileOption } from '../hooks';
interface AnalyticsHeaderProps {
@@ -53,21 +54,42 @@ export function AnalyticsHeader({
<p className="text-sm text-muted-foreground">{t('analytics.subtitle')}</p>
</div>
<div className="flex flex-wrap items-center gap-2 xl:justify-end">
<Select value={selectedProfile} onValueChange={onProfileChange}>
<SelectTrigger className="h-8 w-[190px]" aria-label="Analytics profile">
<SelectValue placeholder="All profiles" />
</SelectTrigger>
<SelectContent>
{profileOptions.map((option) => (
<SelectItem key={option.value} value={option.value} disabled={!option.supported}>
<span className="flex flex-col">
<span>{option.label}</span>
<span className="text-xs text-muted-foreground">{option.description}</span>
</span>
</SelectItem>
))}
</SelectContent>
</Select>
<div className="flex items-center gap-1">
<Select value={selectedProfile} onValueChange={onProfileChange}>
<SelectTrigger className="h-8 w-[190px]" aria-label="Analytics profile">
<SelectValue placeholder="All profiles" />
</SelectTrigger>
<SelectContent>
{profileOptions.map((option) => (
<SelectItem key={option.value} value={option.value} disabled={!option.supported}>
<span className="flex flex-col">
<span>{option.label}</span>
<span className="text-xs text-muted-foreground">{option.description}</span>
</span>
</SelectItem>
))}
</SelectContent>
</Select>
{selectedProfile !== 'all' && (
<TooltipProvider delayDuration={150}>
<Tooltip>
<TooltipTrigger asChild>
<button
type="button"
aria-label="Selected-profile analytics scope"
className="inline-flex size-7 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground"
>
<Info className="size-4" aria-hidden="true" />
</button>
</TooltipTrigger>
<TooltipContent side="bottom" align="start" className="max-w-xs text-xs">
Selected-profile analytics include only default/account data with stable profile
attribution. CLIProxy and native runtime snapshots remain in All profiles.
</TooltipContent>
</Tooltip>
</TooltipProvider>
)}
</div>
<Button
variant={viewMode === 'hourly' ? 'default' : 'outline'}
size="sm"
@@ -106,12 +128,6 @@ export function AnalyticsHeader({
<RefreshCw className={`w-3.5 h-3.5 ${isRefreshing ? 'animate-spin' : ''}`} />
</Button>
</div>
{selectedProfile !== 'all' && (
<p className="text-xs text-muted-foreground xl:text-right">
Selected-profile analytics include only default/account data with stable profile
attribution. CLIProxy and native runtime snapshots remain in All profiles.
</p>
)}
</div>
);
}