Migrate all auth pages, modals, and shared UI components from Discord visual language to Aether Drift design tokens. Zero discord-* classes or raw Tailwind palette colors remain in components/auth/, modals/, ui/. - Avatar: status dots use status-online/idle/dnd/offline tokens - Tooltip, ContextMenu, UserProfilePopout: z-index raised to z-[200] - LoginPage, RegisterPage: warm bg-surface-base with lavender glow - All modals: inputs use surface-input, buttons use accent-primary - Toggles: bg-status-online (on), bg-surface-input (off) - ServerSettings: slider tracks, pills, danger zone fully tokenized - Purged raw Tailwind green-500 leak in StreamingLimitsPanel success msg
49 lines
1.4 KiB
TypeScript
49 lines
1.4 KiB
TypeScript
import React, { useState, useRef, useEffect } from 'react';
|
|
|
|
interface TooltipProps {
|
|
content: string;
|
|
children: React.ReactNode;
|
|
position?: 'top' | 'right' | 'bottom' | 'left';
|
|
delay?: number;
|
|
}
|
|
|
|
export function Tooltip({ content, children, position = 'right', delay = 200 }: TooltipProps) {
|
|
const [isVisible, setIsVisible] = useState(false);
|
|
const timeoutRef = useRef<ReturnType<typeof setTimeout>>();
|
|
|
|
const show = () => {
|
|
timeoutRef.current = setTimeout(() => setIsVisible(true), delay);
|
|
};
|
|
|
|
const hide = () => {
|
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
setIsVisible(false);
|
|
};
|
|
|
|
useEffect(() => {
|
|
return () => {
|
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
};
|
|
}, []);
|
|
|
|
const positionClasses: Record<string, string> = {
|
|
top: 'bottom-full left-1/2 -translate-x-1/2 mb-2',
|
|
right: 'left-full top-1/2 -translate-y-1/2 ml-2',
|
|
bottom: 'top-full left-1/2 -translate-x-1/2 mt-2',
|
|
left: 'right-full top-1/2 -translate-y-1/2 mr-2',
|
|
};
|
|
|
|
return (
|
|
<div className="relative inline-flex" onMouseEnter={show} onMouseLeave={hide}>
|
|
{children}
|
|
{isVisible && (
|
|
<div
|
|
className={`absolute z-[200] px-3 py-1.5 text-sm font-medium text-txt-primary bg-surface-elevated rounded-md shadow-elevation-high whitespace-nowrap pointer-events-none ${positionClasses[position]}`}
|
|
>
|
|
{content}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|