Fix toast visibility and Create Look dialog error handling (#49)

* Fix toast visibility z-index issue and Create Look dialog error handling

- Moved `<Toaster />` outside of `SidebarProvider` in `Layout.tsx` and increased z-index to ensure toasts appear above dialog overlays.
- Updated `CreateLookDialog.tsx` to use `toast.error()` for API errors instead of displaying them inline at the bottom of the dialog.

* Fix Extractor error handling, toast visibility, and Create Look dialog errors

- Updated `ExtractorDialog.tsx` to reset the stage to `'selection'` on refinement error, preventing infinite loading.
- Updated `CreateLookDialog.tsx` to use `toast.error()` for API errors instead of inline text.
- Moved `<Toaster />` in `Layout.tsx` outside of `SidebarProvider` to ensure toasts appear above dialog overlays.
- Ensured `package.json` and `sonner.tsx` remain clean (reverted temporary changes).

* fix sonner

* fix lint

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: yiling ji <njjyl723@gmail.com>
This commit is contained in:
google-labs-jules[bot]andyiling ji authored and GitHub committed 2026-02-19 13:45:58 +08:00
1 parent 308d1d4f58
commit 3209e088e5
4 files changed
+50 -47

No files matched your search

+27 -23
View File
@@ -3,31 +3,35 @@ import { AppSidebar } from './components/AppSidebar'
import { Icons } from './components/Icons'
import { Separator } from './components/ui/separator'
import { SidebarInset, SidebarProvider, SidebarTrigger } from './components/ui/sidebar'
import { Toaster } from './components/ui/sonner'
export default function Layout() {
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2 border-b px-4 justify-between sticky top-0 z-10 bg-background">
<div className="flex items-center gap-2">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 h-4" />
<span className="font-black tracking-wider text-lg">Forgery</span>
</div>
<a
href="https://github.com/Yiling-J/forgery"
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-foreground transition-colors"
>
<Icons.Github className="h-7 w-7" />
</a>
</header>
<main className="flex flex-1 flex-col gap-4 px-4">
<Outlet />
</main>
</SidebarInset>
</SidebarProvider>
<>
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2 border-b px-4 justify-between sticky top-0 z-10 bg-background">
<div className="flex items-center gap-2">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 h-4" />
<span className="font-black tracking-wider text-lg">Forgery</span>
</div>
<a
href="https://github.com/Yiling-J/forgery"
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-foreground transition-colors"
>
<Icons.Github className="h-7 w-7" />
</a>
</header>
<main className="flex flex-1 flex-col gap-4 px-4">
<Outlet />
</main>
</SidebarInset>
</SidebarProvider>
<Toaster />
</>
)
}
+7 -10
View File
@@ -11,12 +11,12 @@ import { SaveOutfitDialog } from './SaveOutfitDialog'
import { Badge } from './ui/badge'
import { Button } from './ui/button'
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from './ui/dialog'
import { Label } from './ui/label'
import { ScrollArea, ScrollBar } from './ui/scroll-area'
@@ -52,7 +52,6 @@ export const CreateLookDialog: React.FC<CreateLookDialogProps> = ({
const [selectedExpressionId, setSelectedExpressionId] = useState<string | null>(null)
const [userPrompt, setUserPrompt] = useState('')
const [submitting, setSubmitting] = useState(false)
const [error, setError] = useState<string | null>(null)
const [loadOutfitOpen, setLoadOutfitOpen] = useState(false)
const [saveOutfitOpen, setSaveOutfitOpen] = useState(false)
@@ -143,7 +142,6 @@ export const CreateLookDialog: React.FC<CreateLookDialogProps> = ({
const handleCreate = async () => {
if (selectedEquipments.length === 0) return
setSubmitting(true)
setError(null)
try {
const res = await client.generations.$post({
@@ -167,7 +165,7 @@ export const CreateLookDialog: React.FC<CreateLookDialogProps> = ({
setUserPrompt('')
} catch (e) {
console.error(e)
setError(e instanceof Error ? e.message : 'Something went wrong')
toast.error(e instanceof Error ? e.message : 'Something went wrong')
} finally {
setSubmitting(false)
}
@@ -532,7 +530,6 @@ export const CreateLookDialog: React.FC<CreateLookDialogProps> = ({
</div>
<div className="flex items-center gap-4">
{error && <span className="text-red-500 text-sm font-medium">{error}</span>}
<Button
size="lg"
className="bg-stone-900 hover:bg-stone-800 text-white shadow-lg min-w-[150px]"
+1
View File
@@ -195,6 +195,7 @@ export const ExtractorDialog: React.FC<ExtractorDialogProps> = ({
console.error(e)
const err = e instanceof Error ? e : new Error(String(e))
toast.error(err.message || 'Refinement failed')
setStage('selection')
}
}
+15 -14
View File
@@ -1,19 +1,19 @@
import {
CircleCheckIcon,
InfoIcon,
Loader2Icon,
OctagonXIcon,
TriangleAlertIcon,
} from "lucide-react"
import { useTheme } from "next-themes"
import { Toaster as Sonner, type ToasterProps } from "sonner"
CircleCheckIcon,
InfoIcon,
Loader2Icon,
OctagonXIcon,
TriangleAlertIcon,
} from 'lucide-react'
import { useTheme } from 'next-themes'
import { Toaster as Sonner, type ToasterProps } from 'sonner'
const Toaster = ({ ...props }: ToasterProps) => {
const { theme = "system" } = useTheme()
const { theme = 'system' } = useTheme()
return (
<Sonner
theme={theme as ToasterProps["theme"]}
theme={theme as ToasterProps['theme']}
className="toaster group"
icons={{
success: <CircleCheckIcon className="size-4" />,
@@ -24,10 +24,11 @@ const Toaster = ({ ...props }: ToasterProps) => {
}}
style={
{
"--normal-bg": "var(--popover)",
"--normal-text": "var(--popover-foreground)",
"--normal-border": "var(--border)",
"--border-radius": "var(--radius)",
'--normal-bg': 'white',
'--normal-text': 'var(--popover-foreground)',
'--normal-border': 'var(--border)',
'--border-radius': 'var(--radius)',
zIndex: 99,
} as React.CSSProperties
}
{...props}