supermemory/packages/ui/components/sonner.tsx
MaheshtheDev 1706752668 mobile responsiveness pass + connections reauth fix (#959)
Nova mobile pass
- viewport: viewportFit cover for iOS safe-area-inset
- safe-area utilities (pb-safe, pt-safe, bottom-safe-5, scroll-fade-x) in globals.css
- chat FAB pinned above iPhone home indicator; chat sidebar widths responsive across sm/md/lg with min() clamps
- chat input CoT panel max-h capped via min(60dvh, 420px)
- header tab strip swapped from visible scrollbar to scroll-fade-x mask + snap-x
- nova empty state uses svh on mobile, dvh from sm up

Add-memory modal rebuilt for mobile
- mobile shell switched from fullscreen Dialog to vaul Drawer at 85svh with swipe-down dismissal and scaled background
- in-modal header removed; tabs moved to the bottom of the sheet for thumb reach
- four tab compactLabels: Note, Links, Files, Connections
- desktop tabs now render only when !isMobile (no DOM duplication)
- note/link content state lifted to parent so switching tabs preserves typed input
- NoteContent snapshots initialContent via lazy useState so the editor isn't reset on every keystroke
- shared Drawer base uses rounded-t-xl
- removed legacy pt-4 on tab content for mobile

Connections — replace expiresAt with sync-run health
- new useConnectionHealth hook reads the latest sync run and matches auth-failure patterns; backend errorKind field still needed (TODO)
- regex tightened so 401/403 require co-occurring auth/token/grant context; refresh_token requires expired/revoked/invalid/missing qualifier
- badge label changed Disconnected -> Needs reauth
- Reconnect button replaces the sync action when needsReauth, kicks off the same OAuth flow
- per-row reconnect tracking via mutation.variables instead of a single shared id (no race when multiple rows clicked)
- fallback toast when authLink is missing so the spinner can't get stuck
- sync history panel timeline capped at max-h-260 with internal scroll
- useSyncRuns no longer refetches on mount; cache (30s) actually applies, cutting N requests per modal open
2026-05-17 21:49:23 +00:00

32 lines
966 B
TypeScript

"use client"
import { useTheme } from "next-themes"
import { Toaster as Sonner, type ToasterProps } from "sonner"
const Toaster = ({ ...props }: ToasterProps) => {
const { theme = "system" } = useTheme()
return (
<Sonner
className="toaster group"
theme={theme as ToasterProps["theme"]}
toastOptions={{
classNames: {
toast:
"!bg-[#0b1017] !border !border-[#1b1f24] !rounded-[10px] !p-3 !shadow-lg px-4",
title:
"!text-[#fafafa] !text-[12px] !leading-[1.35] !tracking-[-0.12px] !font-['DM_Sans',sans-serif]",
description:
"!text-[#fafafa] !text-[12px] !leading-[1.35] !tracking-[-0.12px] !font-['DM_Sans',sans-serif] opacity-80",
closeButton:
"!bg-transparent !border-none !text-[#fafafa] hover:!bg-white/10 !size-6 !static !ml-2 !shrink-0",
actionButton: "!bg-white/10 !text-[#fafafa]",
cancelButton: "!bg-transparent !text-[#fafafa]",
},
}}
{...props}
/>
)
}
export { Toaster }