Buttons
Buttons are the primary call-to-action elements. They come in six variants and three sizes, all sharing consistent border-radius, focus rings, and disabled states.
Variants
| Variant | Background | Text | When to Use |
|---|---|---|---|
| Primary | bg-primary | text-primary-foreground | Main action per context: Generate, Save, Confirm |
| Secondary | bg-secondary | text-secondary-foreground | Supporting actions: Cancel, Reset, Sort |
| Outline | bg-background | text-foreground | Settings rows, catalog actions, toolbar controls |
| Ghost | transparent | text-foreground | Toolbar toggles, icon-only buttons, skip actions |
| Destructive | bg-destructive/60 | white | Delete, remove, clear — always confirm first |
| Link | transparent | text-primary | Inline navigation, less prominent text actions |
Sizes
| Size | Height | Padding | Tailwind | Usage |
|---|---|---|---|---|
| sm | 32px (h-8) | 0 12px | size="sm" | Toolbars, compact rows, selection bars |
| default | 36px (h-9) | 0 16px | size="default" | Standard buttons in forms and dialogs |
| lg | 40px (h-10) | 0 24px | size="lg" | Prominent standalone CTAs |
| icon | 36px × 36px | 0 | size="icon" | Icon-only buttons (close, expand, etc.) |
| icon-sm | 32px × 32px | 0 | size="icon-sm" | Compact icon buttons in dense areas |
Special: Generate Button
The "Generate" button is the single most important CTA in the app. It uses the signature magical animated gradient (Blue → Pink → Green) to visually connect to the wavy background and brand identity. On hover, the animation accelerates and the button lifts.
btn-primary. The Generate button is reserved for
the most important creative action.
States
Svelte Implementation
import { Button } from "$lib/components/ui/button";
// Usage
<Button variant="default">Primary</Button>
<Button variant="outline" size="sm">Compact</Button>
<Button variant="ghost" size="icon"><X /></Button>
Inputs & Forms
Form elements share a consistent visual language: same border color, same radius, same focus ring. Compact variants reduce height for toolbar and filter contexts.
Text Input
Textarea
Select
Switch
Form Anatomy
| Element | Height | Font Size | Border | Focus Ring |
|---|---|---|---|---|
| Input (default) | h-9 (36px) | text-sm | border-input | 3px ring/50 |
| Input (compact) | h-8 (32px) | text-xs | border-input | 3px ring/50 |
| Select trigger | h-9 (36px) | text-sm | border-input | 3px ring/50 |
| Textarea | min 80px | text-sm | border-input | 3px ring/50 |
| Switch track | 1.15rem | — | none | ring on focus |
| Label | auto | text-sm · 500 | — | — |
Form Layout Patterns
flex flex-col gap-4 for the form, flex flex-col gap-2
for each label+input group. Use space-y-5 between field groups inside a VLCard.Inline form:
flex gap-2 items-center for toolbar-style compact controls like
search bars with adjacent filter buttons.
Cards
Cards are the primary container for grouping related content. They use the signature glass morphism treatment — translucent backgrounds with backdrop blur that lets the wavy background breathe through.
Standard Card (Glass)
bg-card/10 backdrop-blur-sm border-border/50 rounded-xl py-6 shadow-sm.
The /10 opacity is key — it makes cards feel like floating glass panes rather than opaque
containers. The border-border/50 softens the edge to prevent hard outlines.
Card Anatomy (shadcn)
| Part | Component | Styling |
|---|---|---|
| Container | Card.Root | Glass treatment, rounded-xl, gap-6, py-6 |
| Header | Card.Header | flex col gap-1.5, px-6 |
| Title | Card.Title | font-semibold, tracking-tight |
| Description | Card.Description | text-sm, text-muted-foreground |
| Content | Card.Content | px-6 |
| Footer | Card.Footer | flex row, px-6, gap-2 |
VLCard (Collapsible Wrapper)
VLCard is the app-specific wrapper around shadcn's Card. It adds a title bar with
optional collapse/expand toggle. Used throughout the Generate and Settings pages to create
accordion-like sections.
Image Tile Card
Image tiles are specialized cards for the gallery grid. They add hover scale, layered shadows, aspect ratio constraints, and overlay elements (badges, favourite star, radial menu).
| Property | Value |
|---|---|
| Background | bg-card/40 backdrop-blur-md |
| Border radius | rounded-lg |
| Hover transform | hover:scale-105 + multi-layer shadow |
| Transition | transition-all duration-300 |
| Default aspect | aspect-square |
| Overlay (status) | bg-black/50 rounded-lg |
| Model badge | bg-black/60 text-white text-xs px-2 py-0.5 |
| Favourite star | bg-black/40 — active: fill-yellow-400 |
Dialogs
Dialogs interrupt the user flow for confirmation, input, or display of detailed information. They are always modal with a dark scrim backdrop.
Dialog Anatomy
| Part | Implementation | Styling |
|---|---|---|
| Backdrop | Portal overlay | bg-black/80 · fixed inset-0 · z-50 |
| Content | Dialog.Content | bg-background · rounded-lg · p-6 · shadow-lg · centered |
| Width (default) | — | max-w-lg (32rem / 512px) |
| Width (confirm) | — | sm:max-w-md (28rem / 448px) |
| Width (wizard) | — | max-w-2xl (42rem / 672px) |
| Close button | Absolute top-right | X icon · opacity-70 · hover:opacity-100 |
| Animation | Svelte transitions | fade-in + zoom-in-95 · 200ms |
Custom Overlay Dialog
For rich content overlays (catalog detail, image detail), a custom layout replaces the standard
shadcn dialog. These use fixed inset-0 bg-black/80 with a centered glass panel:
bg-card/40 backdrop-blur-md rounded-lg max-w-4xl.
Badges & Pills
Badges communicate status, category, or count. They are always rounded-full
to distinguish them from buttons and cards.
Usage Guidelines
| Type | Variant | Example |
|---|---|---|
| Model indicator | Outline (text-xs) | Flux1.dev, SDXL |
| Status badge | Success / Warning | Ready, Queue: 3 |
| Tag | Secondary (text-xs) | Landscape, Portrait, 4K |
| Count indicator | Default (min-w-5 h-5) | 3 (selection count) |
| Image overlay | bg-background/80 backdrop-blur-sm | Model name on catalog card |
Toasts
Toast notifications provide transient feedback. They appear in the bottom-right corner and auto-dismiss after a timeout. A colored left border indicates the type at a glance.
Toast Anatomy
| Property | Value |
|---|---|
| Background | bg-card (solid, not glass) |
| Border | 1px solid var(--border) |
| Border radius | var(--radius) |
| Width | 400px (max calc(100vw - 32px)) |
| Shadow | 0 4px 12px rgba(0,0,0,0.15) |
| Success accent | 3px left border · oklch(0.723 0.219 150) |
| Error accent | 3px left border · var(--destructive) |
| Warning accent | 3px left border · oklch(0.828 0.189 84) |
| Info accent | 3px left border · var(--primary) |
| Title | text-sm · font-semibold |
| Description | text-xs · opacity 0.85 |
toastOptions
prop on <Toaster>.
Tabs
Tabs switch between views within the same context. The active tab is highlighted with a solid background, creating a "pushed in" effect against the muted tab list.
| Part | Background | Text | Radius |
|---|---|---|---|
| Tab list | bg-muted | — | rounded-lg |
| Active tab | bg-background + shadow-sm | text-foreground | rounded-md |
| Inactive tab | transparent | text-muted-foreground | — |
Progress
Progress bars indicate determinate loading states. They use the primary color against a tinted track.
| Part | Height | Values |
|---|---|---|
| Track | h-2 (8px) | bg-primary/20 rounded-full |
| Fill | h-2 | bg-primary rounded-full, transition-all |
Status Indicators
Status pills communicate the connection state of backend services (Pollinations, ComfyUI) in the status bar and startup screen.
| State | Background | Dot | Border |
|---|---|---|---|
| Ready | bg-emerald-500/10 | bg-emerald-500 | border-emerald-500/30 |
| Error | bg-red-500/10 | bg-red-500 | border-red-500/30 |
| Pending | bg-muted/50 | bg-muted-foreground/60 | border-border |
Miscellaneous
Separator
Tooltip
Tooltip.Provider at the app
root for consistent delay behavior.
Scroll Area
Custom scrollbars use a thin 10px thumb with rounded corners. The track is transparent, and the
thumb uses muted-foreground at 40% opacity, increasing to 55% on hover and 70% when active.
Firefox uses scrollbar-width: thin with matching colors.
Popover
Popovers share the dialog's visual treatment but are positioned relative to their trigger rather
than centered on screen. Used for the model selector, filter panels, and color pickers.
Styling: bg-popover text-popover-foreground rounded-md border shadow-md.
Collapsible
Collapsible sections use a toggle button with a bg-muted size-6 rounded-full indicator
containing a chevron. Content slides in/out with Svelte's slide transition. Used in
VLCard and model selector group sections.
Spinner
Loader2 icon with animate-spin.
The spinner wraps the icon in a custom Spinner component at $lib/components/ui/spinner.