SPB Git

Repository Public

toast.tsx 1.7 KB 39 lines tsx

1'use client';2import Link from 'next/link';3import { X } from 'lucide-react';4import { useToasts, type ToastTone } from '@/stores/toasts';5import { cn } from '@/lib/cn';67const BAR: Record<ToastTone, string> = { info: 'bg-accent', success: 'bg-success-vivid', warning: 'bg-warning-vivid', error: 'bg-error-vivid' };89export function Toaster() {10  const { toasts, dismiss } = useToasts();11  return (12    <div aria-live="polite" className="pointer-events-none fixed inset-x-3 bottom-[calc(env(safe-area-inset-bottom)+92px)] z-[90] mx-auto flex max-w-md flex-col gap-2 md:inset-x-auto md:bottom-4 md:right-4 md:mx-0 md:w-[360px]">13      {toasts.map((t) => {14        const body = (15          <>16            <p className="text-[13px] font-medium text-text">{t.title}</p>17            {t.body && <p className="mt-0.5 text-xs text-text-2">{t.body}</p>}18          </>19        );20        return (21          <div key={t.id} role="status" className="anim-pop pointer-events-auto relative flex overflow-hidden rounded-md border border-card-line bg-elevated shadow-float">22            <span className={cn('w-1 shrink-0', BAR[t.tone])} />23            {t.href ? (24              <Link href={t.href} onClick={() => dismiss(t.id)} className="min-w-0 flex-1 px-3 py-2.5">25                {body}26              </Link>27            ) : (28              <div className="min-w-0 flex-1 px-3 py-2.5">{body}</div>29            )}30            <button aria-label="Dismiss notification" onClick={() => dismiss(t.id)} className="m-1 inline-flex size-7 shrink-0 items-center justify-center rounded-sm text-muted hover:bg-hover hover:text-text pointer-coarse:size-11">31              <X className="size-3.5" />32            </button>33          </div>34        );35      })}36    </div>37  );38}39
Files main
Menu

Theme