tahamajs/IE / Projects /front /src /components /common /ContextHelpPanel.tsx
tahamajs's picture
download
raw
4.28 kB
import { ReactNode } from "react";
import { X, Lightbulb, CheckCircle2 } from "lucide-react";
import { AnimatePresence, motion } from "framer-motion";
export interface HelpPoint {
title: string;
text: string;
}
interface ContextHelpPanelProps {
open: boolean;
title: string;
intro: string;
steps: HelpPoint[];
tips?: HelpPoint[];
onClose: () => void;
footer?: ReactNode;
}
export function ContextHelpPanel({ open, title, intro, steps, tips, onClose, footer }: ContextHelpPanelProps) {
return (
<AnimatePresence>
{open && (
<>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 z-50 bg-black/40 backdrop-blur-sm"
onClick={onClose}
/>
<motion.aside
initial={{ opacity: 0, x: 40 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: 40 }}
transition={{ duration: 0.25 }}
className="fixed right-4 top-4 z-50 w-[min(92vw,28rem)] overflow-hidden rounded-[1.75rem] border border-white/60 bg-white/95 shadow-[0_30px_80px_rgba(15,23,42,0.25)] backdrop-blur-xl dark:border-white/10 dark:bg-slate-950/95"
>
<div className="flex items-start justify-between gap-4 border-b border-gray-200 px-5 py-4 dark:border-gray-800">
<div>
<div className="inline-flex items-center gap-2 rounded-full bg-primary/10 px-3 py-1 text-xs font-semibold text-primary">
<Lightbulb className="h-3.5 w-3.5" />
Quick Guide
</div>
<h3 className="mt-3 text-xl font-bold text-gray-900 dark:text-white">{title}</h3>
<p className="mt-2 text-sm leading-relaxed text-gray-600 dark:text-gray-400">{intro}</p>
</div>
<button
onClick={onClose}
className="rounded-full p-2 text-gray-400 transition hover:bg-gray-100 hover:text-gray-700 dark:hover:bg-gray-800 dark:hover:text-gray-200"
aria-label="Close help panel"
>
<X className="h-4 w-4" />
</button>
</div>
<div className="max-h-[70vh] space-y-5 overflow-y-auto px-5 py-5">
<div className="space-y-3">
{steps.map((step, index) => (
<div key={step.title} className="rounded-2xl border border-gray-200 bg-gray-50 p-4 dark:border-gray-800 dark:bg-white/5">
<div className="flex items-start gap-3">
<div className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-r from-primary to-secondary text-xs font-bold text-white">
{index + 1}
</div>
<div>
<div className="font-semibold text-gray-900 dark:text-white">{step.title}</div>
<p className="mt-1 text-sm leading-relaxed text-gray-600 dark:text-gray-400">{step.text}</p>
</div>
</div>
</div>
))}
</div>
{tips && tips.length > 0 && (
<div className="rounded-2xl border border-emerald-200 bg-emerald-50 p-4 dark:border-emerald-900/50 dark:bg-emerald-950/25">
<div className="mb-3 flex items-center gap-2 text-sm font-semibold text-emerald-700 dark:text-emerald-300">
<CheckCircle2 className="h-4 w-4" />
Helpful Tips
</div>
<div className="space-y-3">
{tips.map((tip) => (
<div key={tip.title}>
<div className="text-sm font-medium text-emerald-800 dark:text-emerald-200">{tip.title}</div>
<p className="mt-1 text-sm leading-relaxed text-emerald-700/90 dark:text-emerald-300/90">{tip.text}</p>
</div>
))}
</div>
</div>
)}
{footer && <div>{footer}</div>}
</div>
</motion.aside>
</>
)}
</AnimatePresence>
);
}

Xet Storage Details

Size:
4.28 kB
·
Xet hash:
7f1a6e3376b72060e15ee329ede8dbcfd47ab366ad71c4da330fcac577ff9c6f

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.