| 'use client'; |
|
|
| import * as Tooltip from '@radix-ui/react-tooltip'; |
| import { motion, AnimatePresence } from 'framer-motion'; |
| import { cn } from '@/lib/utils'; |
| import { useState, type ReactNode } from 'react'; |
|
|
| export interface GlassTooltipProps { |
| content: ReactNode; |
| children: ReactNode; |
| side?: 'top' | 'right' | 'bottom' | 'left'; |
| align?: 'start' | 'center' | 'end'; |
| delayDuration?: number; |
| className?: string; |
| severity?: 'critical' | 'warning' | 'suggestion'; |
| } |
|
|
| const severityStyles = { |
| critical: { |
| bg: 'bg-[var(--critical-bg-glass)]', |
| border: 'border-[var(--critical-border)]', |
| arrow: 'fill-[var(--critical-bg)]', |
| }, |
| warning: { |
| bg: 'bg-[var(--warning-bg-glass)]', |
| border: 'border-[var(--warning-border)]', |
| arrow: 'fill-[var(--warning-bg)]', |
| }, |
| suggestion: { |
| bg: 'bg-[var(--suggestion-bg-glass)]', |
| border: 'border-[var(--suggestion-border)]', |
| arrow: 'fill-[var(--suggestion-bg)]', |
| }, |
| }; |
|
|
| export function GlassTooltip({ |
| content, |
| children, |
| side = 'top', |
| align = 'center', |
| delayDuration = 300, |
| className, |
| severity, |
| }: GlassTooltipProps) { |
| const [open, setOpen] = useState(false); |
| const severityStyle = severity ? severityStyles[severity] : null; |
|
|
| return ( |
| <Tooltip.Provider delayDuration={delayDuration}> |
| <Tooltip.Root open={open} onOpenChange={setOpen}> |
| <Tooltip.Trigger asChild>{children}</Tooltip.Trigger> |
| <AnimatePresence> |
| {open && ( |
| <Tooltip.Portal forceMount> |
| <Tooltip.Content |
| asChild |
| side={side} |
| align={align} |
| sideOffset={6} |
| className="z-50" |
| > |
| <motion.div |
| initial={{ opacity: 0, scale: 0.95 }} |
| animate={{ opacity: 1, scale: 1 }} |
| exit={{ opacity: 0, scale: 0.95 }} |
| transition={{ duration: 0.1, ease: 'easeOut' }} |
| className={cn( |
| 'px-3 py-2 rounded-lg', |
| 'backdrop-blur-xl backdrop-saturate-150', |
| 'text-sm text-[var(--foreground)]', |
| 'max-w-xs', |
| 'shadow-lg', |
| severityStyle |
| ? cn(severityStyle.bg, 'border', severityStyle.border) |
| : 'glass-elevated', |
| className |
| )} |
| > |
| {content} |
| <Tooltip.Arrow |
| className={cn( |
| severityStyle |
| ? severityStyle.arrow |
| : 'fill-[var(--glass-bg-elevated)]' |
| )} |
| /> |
| </motion.div> |
| </Tooltip.Content> |
| </Tooltip.Portal> |
| )} |
| </AnimatePresence> |
| </Tooltip.Root> |
| </Tooltip.Provider> |
| ); |
| } |
|
|