make toasts accessible: ARIA live region, dismiss button, pause on hover
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { X } from "lucide-react";
|
||||
import { springs } from "@/lib/motion";
|
||||
import { useToastStore } from "@/stores/toast-store";
|
||||
|
||||
@@ -10,9 +11,17 @@ const TYPE_STYLES = {
|
||||
|
||||
export function ToastContainer() {
|
||||
const toasts = useToastStore((s) => s.toasts);
|
||||
const removeToast = useToastStore((s) => s.removeToast);
|
||||
const pauseToast = useToastStore((s) => s.pauseToast);
|
||||
const resumeToast = useToastStore((s) => s.resumeToast);
|
||||
|
||||
return (
|
||||
<div className="pointer-events-none fixed bottom-4 right-4 z-[100] flex flex-col gap-2">
|
||||
<div
|
||||
className="pointer-events-none fixed bottom-4 right-4 z-[100] flex flex-col gap-2"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
aria-atomic="true"
|
||||
>
|
||||
<AnimatePresence>
|
||||
{toasts.map((toast) => (
|
||||
<motion.div
|
||||
@@ -21,9 +30,20 @@ export function ToastContainer() {
|
||||
animate={{ opacity: 1, y: 0, scale: 1 }}
|
||||
exit={{ opacity: 0, y: 20, scale: 0.9 }}
|
||||
transition={springs.wobbly}
|
||||
className={`pointer-events-auto rounded-lg border px-4 py-2 text-sm shadow-md ${TYPE_STYLES[toast.type]}`}
|
||||
className={`pointer-events-auto flex items-center gap-2 rounded-lg border px-4 py-2 text-sm shadow-md ${TYPE_STYLES[toast.type]}`}
|
||||
onMouseEnter={() => pauseToast(toast.id)}
|
||||
onMouseLeave={() => resumeToast(toast.id)}
|
||||
onFocus={() => pauseToast(toast.id)}
|
||||
onBlur={() => resumeToast(toast.id)}
|
||||
>
|
||||
{toast.message}
|
||||
<span className="flex-1">{toast.message}</span>
|
||||
<button
|
||||
onClick={() => removeToast(toast.id)}
|
||||
className="shrink-0 rounded p-0.5 transition-opacity hover:opacity-70"
|
||||
aria-label="Dismiss notification"
|
||||
>
|
||||
<X className="size-3.5" />
|
||||
</button>
|
||||
</motion.div>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
|
||||
Reference in New Issue
Block a user