fix: hoist TooltipProvider to app root, remove per-component instances

This commit is contained in:
2026-07-10 00:25:04 +02:00
parent 5d4622e046
commit 306f4489fd
4 changed files with 47 additions and 60 deletions

View File

@@ -1,4 +1,4 @@
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip" import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
import { timeAgo, shortDate } from "@/lib/date" import { timeAgo, shortDate } from "@/lib/date"
type TimeAgoProps = { type TimeAgoProps = {
@@ -8,13 +8,11 @@ type TimeAgoProps = {
export function TimeAgo({ date, className }: TimeAgoProps) { export function TimeAgo({ date, className }: TimeAgoProps) {
return ( return (
<TooltipProvider> <Tooltip>
<Tooltip> <TooltipTrigger asChild>
<TooltipTrigger asChild> <time dateTime={date} className={className}>{timeAgo(date)}</time>
<time dateTime={date} className={className}>{timeAgo(date)}</time> </TooltipTrigger>
</TooltipTrigger> <TooltipContent>{shortDate(date)}</TooltipContent>
<TooltipContent>{shortDate(date)}</TooltipContent> </Tooltip>
</Tooltip>
</TooltipProvider>
) )
} }

View File

@@ -1,11 +1,6 @@
import { useTranslation } from "react-i18next" import { useTranslation } from "react-i18next"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
import { WATCH_MEDIUMS } from "@/lib/watch-mediums" import { WATCH_MEDIUMS } from "@/lib/watch-mediums"
@@ -22,15 +17,13 @@ export function WatchMediumBadge({ medium, className }: WatchMediumBadgeProps) {
const Icon = entry.icon const Icon = entry.icon
return ( return (
<TooltipProvider> <Tooltip>
<Tooltip> <TooltipTrigger asChild>
<TooltipTrigger asChild> <Button type="button" variant="ghost" size="icon" className={cn("size-6", className)} aria-label={t(entry.labelKey)}>
<Button type="button" variant="ghost" size="icon" className={cn("size-6", className)} aria-label={t(entry.labelKey)}> <Icon className="size-3.5 text-muted-foreground" />
<Icon className="size-3.5 text-muted-foreground" /> </Button>
</Button> </TooltipTrigger>
</TooltipTrigger> <TooltipContent>{t(entry.labelKey)}</TooltipContent>
<TooltipContent>{t(entry.labelKey)}</TooltipContent> </Tooltip>
</Tooltip>
</TooltipProvider>
) )
} }

View File

@@ -1,11 +1,6 @@
import { useTranslation } from "react-i18next" import { useTranslation } from "react-i18next"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
import { WATCH_MEDIUMS } from "@/lib/watch-mediums" import { WATCH_MEDIUMS } from "@/lib/watch-mediums"
@@ -22,34 +17,32 @@ export function WatchMediumPicker({ value, onChange }: WatchMediumPickerProps) {
<p className="mb-2 text-xs uppercase tracking-wide text-muted-foreground"> <p className="mb-2 text-xs uppercase tracking-wide text-muted-foreground">
{t("watchMedium.label")} {t("watchMedium.label")}
</p> </p>
<TooltipProvider> <div className="flex flex-wrap gap-1.5">
<div className="flex flex-wrap gap-1.5"> {WATCH_MEDIUMS.map(({ value: val, icon: Icon, labelKey }) => {
{WATCH_MEDIUMS.map(({ value: val, icon: Icon, labelKey }) => { const selected = value === val
const selected = value === val return (
return ( <Tooltip key={val}>
<Tooltip key={val}> <TooltipTrigger asChild>
<TooltipTrigger asChild> <Button
<Button type="button"
type="button" variant="outline"
variant="outline" size="icon"
size="icon" className={cn(
className={cn( "size-8",
"size-8", selected && "border-[var(--aero-primary)] bg-[var(--aero-primary)] text-white shadow-[0_0_8px_var(--aero-primary-glow)]",
selected && "border-[var(--aero-primary)] bg-[var(--aero-primary)] text-white shadow-[0_0_8px_var(--aero-primary-glow)]", )}
)} aria-label={t(labelKey)}
aria-label={t(labelKey)} aria-pressed={selected}
aria-pressed={selected} onClick={() => onChange(selected ? undefined : val)}
onClick={() => onChange(selected ? undefined : val)} >
> <Icon className="size-4" />
<Icon className="size-4" /> </Button>
</Button> </TooltipTrigger>
</TooltipTrigger> <TooltipContent sideOffset={4}>{t(labelKey)}</TooltipContent>
<TooltipContent sideOffset={4}>{t(labelKey)}</TooltipContent> </Tooltip>
</Tooltip> )
) })}
})} </div>
</div>
</TooltipProvider>
</div> </div>
) )
} }

View File

@@ -1,5 +1,6 @@
import { createRootRoute, Outlet } from "@tanstack/react-router" import { createRootRoute, Outlet } from "@tanstack/react-router"
import { ThemeProvider } from "@/components/theme-provider" import { ThemeProvider } from "@/components/theme-provider"
import { TooltipProvider } from "@/components/ui/tooltip"
export const Route = createRootRoute({ export const Route = createRootRoute({
component: RootLayout, component: RootLayout,
@@ -8,7 +9,9 @@ export const Route = createRootRoute({
function RootLayout() { function RootLayout() {
return ( return (
<ThemeProvider> <ThemeProvider>
<Outlet /> <TooltipProvider>
<Outlet />
</TooltipProvider>
</ThemeProvider> </ThemeProvider>
) )
} }