kanban / src /components /preview /FAQDialog.tsx
Leon4gr45's picture
Deploy magic-resume as Docker Space (port 3000)
c30ea2a verified
Raw
History Blame Contribute Delete
6.22 kB
import React, { useState } from "react";
import { HelpCircle } from "lucide-react";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
import { FAQ_KEYS } from "@/config/faq";
import { cn } from "@/lib/utils";
import { useTranslations } from "@/i18n/compat/client";
const DynamicHelpIcon = React.forwardRef<HTMLButtonElement, React.ButtonHTMLAttributes<HTMLButtonElement>>(
(props, ref) => (
<button
ref={ref}
{...props}
className={cn(
"relative group flex items-center justify-center focus:outline-none focus:ring-2 focus:ring-primary/40 rounded-full",
// Floating bounce animation to attract attention
"animate-[bounce_5s_ease-in-out_infinite]",
props.className
)}
>
{/* Ambient Glow - Uses theme primary color */}
<div className="absolute inset-0 rounded-full bg-primary/10 blur-xl group-hover:bg-primary/30 transition-all duration-700 animate-[pulse_4s_ease-in-out_infinite]" />
{/* Glass Container */}
<div className="absolute inset-0 rounded-full bg-background/40 dark:bg-zinc-900/40 backdrop-blur-md border border-primary/20 group-hover:border-primary/50 transition-colors duration-500 shadow-lg" />
<svg
viewBox="0 0 100 100"
className="relative w-10 h-10 md:w-11 md:h-11 origin-center transition-transform duration-500 group-hover:scale-110 overflow-visible"
>
<defs>
<radialGradient id="magicGlow" cx="50%" cy="50%" r="50%">
<stop offset="0%" stopColor="var(--primary)" stopOpacity="0.4" />
<stop offset="100%" stopColor="var(--primary)" stopOpacity="0" />
</radialGradient>
</defs>
{/* Outer concentric rings - Thin and elegant */}
<circle
cx="50"
cy="50"
r="45"
fill="none"
stroke="currentColor"
strokeWidth="0.5"
className="text-primary/20 origin-center animate-[spin_20s_linear_infinite]"
/>
<circle
cx="50"
cy="50"
r="40"
fill="none"
stroke="currentColor"
strokeWidth="1"
strokeDasharray="2 10"
className="text-primary/40 origin-center animate-[spin_15s_linear_infinite_reverse]"
/>
{/* Orbiting dots */}
<g className="origin-center animate-[spin_8s_linear_infinite]">
<circle cx="50" cy="5" r="2" className="fill-primary drop-shadow-[0_0_5px_var(--primary)]" />
</g>
<g className="origin-center animate-[spin_12s_linear_infinite_reverse]">
<circle cx="95" cy="50" r="1.5" className="fill-primary/60" />
</g>
{/* Inner glowing core */}
<circle
cx="50"
cy="50"
r="28"
fill="url(#magicGlow)"
className="animate-[pulse_3s_ease-in-out_infinite]"
/>
<circle
cx="50"
cy="50"
r="20"
fill="none"
stroke="currentColor"
strokeWidth="1.5"
className="text-primary/80"
/>
{/* Question mark - Clean typography */}
<text
x="50"
y="52"
textAnchor="middle"
dominantBaseline="central"
className="fill-primary font-bold text-[32px] select-none pointer-events-none"
style={{ fontFamily: "Inter, system-ui, sans-serif" }}
>
?
</text>
{/* Subtle Sparkles */}
<g className="text-primary">
<circle cx="20" cy="20" r="1" className="animate-pulse">
<animate attributeName="opacity" values="0;1;0" dur="2s" repeatCount="indefinite" />
</circle>
<circle cx="80" cy="30" r="0.8" className="animate-pulse">
<animate attributeName="opacity" values="0;1;0" dur="3s" begin="1s" repeatCount="indefinite" />
</circle>
<circle cx="30" cy="80" r="1.2" className="animate-pulse">
<animate attributeName="opacity" values="0;1;0" dur="2.5s" begin="0.5s" repeatCount="indefinite" />
</circle>
</g>
</svg>
</button>
)
);
DynamicHelpIcon.displayName = "DynamicHelpIcon";
export const FAQDialog = () => {
const [open, setOpen] = useState(false);
const t = useTranslations("faqDialog");
return (
<Dialog open={open} onOpenChange={setOpen}>
<TooltipProvider delayDuration={0}>
<Tooltip>
<TooltipTrigger asChild>
<DialogTrigger asChild>
<DynamicHelpIcon />
</DialogTrigger>
</TooltipTrigger>
<TooltipContent side="left" sideOffset={16}>
<p>{t("title")}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<DialogContent className="sm:max-w-[500px]">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-primary/10 text-primary">
<HelpCircle className="h-5 w-5" />
</div>
{t("title")}
</DialogTitle>
<DialogDescription>
{t("description")}
</DialogDescription>
</DialogHeader>
<div className="mt-4 max-h-[60vh] overflow-y-auto pr-2">
<Accordion type="single" collapsible className="w-full">
{FAQ_KEYS.map((key) => (
<AccordionItem key={key} value={key}>
<AccordionTrigger className="text-left text-[15px] font-medium">
{t(`items.${key}.question`)}
</AccordionTrigger>
<AccordionContent className="text-muted-foreground leading-relaxed whitespace-pre-wrap">
{t(`items.${key}.answer`)}
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</div>
</DialogContent>
</Dialog>
);
};