Replace Sonner with custom Sera UI-inspired toast system (#296)

* refactor(ui): replace Sonner with custom Sera UI-inspired toast system

Replace the Sonner toast library with a custom implementation inspired by
Sera UI's glassmorphism design. The new system uses an external store pattern
with useSyncExternalStore for React integration, keeping the same
toast.success()/error()/warning() API so all 172 call sites required only
an import path change.

Key changes:
- New toast-store.ts: singleton store with identical API to Sonner
- New toast.tsx: Sera UI-faithful Notification component with Framer Motion
  animations, frosted glass (backdrop-blur-xl), type gradient overlays,
  animated progress bar (green→blue→sky gradient), and hover:scale-105
- Removed sonner and next-themes dependencies
- Rewired all 19 consumer files to import from the new store

* fix(ui): resolve ESLint errors in toast system

- Use const for listeners Set (prefer-const)
- Initialize startRef with 0 instead of Date.now() to satisfy
  react-hooks/purity rule, set actual value inside useEffect
This commit is contained in:
Anso
2026-03-31 21:34:49 -04:00
committed by GitHub
parent 8d988d6b08
commit d393d06885
25 changed files with 241 additions and 74 deletions
@@ -3,7 +3,7 @@ import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Skeleton } from '@/components/ui/skeleton';
import { toast } from 'sonner';
import { toast } from '@/components/ui/toast-store';
import { apiFetch } from '@/lib/api';
import { RefreshCw } from 'lucide-react';
import type { PatchableSettings } from './types';
@@ -3,7 +3,7 @@ import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Badge } from '@/components/ui/badge';
import { toast } from 'sonner';
import { toast } from '@/components/ui/toast-store';
import { useLicense } from '@/context/LicenseContext';
import { TierBadge } from '@/components/TierBadge';
import {
@@ -7,7 +7,7 @@ import { Label } from '@/components/ui/label';
import { Switch } from '@/components/ui/switch';
import { Badge } from '@/components/ui/badge';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import { toast } from 'sonner';
import { toast } from '@/components/ui/toast-store';
import { apiFetch } from '@/lib/api';
import { useNodes } from '@/context/NodeContext';
import { RefreshCw, Info } from 'lucide-react';
@@ -9,7 +9,7 @@ import {
AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent,
AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger,
} from '@/components/ui/alert-dialog';
import { toast } from 'sonner';
import { toast } from '@/components/ui/toast-store';
import { apiFetch } from '@/lib/api';
import { useAuth, type UserRole } from '@/context/AuthContext';
import { useLicense } from '@/context/LicenseContext';
@@ -6,7 +6,7 @@ import { Badge } from '@/components/ui/badge';
import { Switch } from '@/components/ui/switch';
import { Skeleton } from '@/components/ui/skeleton';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { toast } from 'sonner';
import { toast } from '@/components/ui/toast-store';
import { apiFetch } from '@/lib/api';
import { ProGate } from '@/components/ProGate';
import { TierBadge } from '@/components/TierBadge';