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

VariantBackgroundTextWhen 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

SizeHeightPaddingTailwindUsage
sm32px (h-8)0 12pxsize="sm"Toolbars, compact rows, selection bars
default36px (h-9)0 16pxsize="default"Standard buttons in forms and dialogs
lg40px (h-10)0 24pxsize="lg"Prominent standalone CTAs
icon36px × 36px0size="icon"Icon-only buttons (close, expand, etc.)
icon-sm32px × 32px0size="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.

Rule: Only one magical gradient button should appear per page. If you need a second primary action, use a standard btn-primary. The Generate button is reserved for the most important creative action.

States

Svelte Implementation

// Import from shadcn-svelte
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

Flux1.dev
Newest

Switch

Enable NSFW filter
Dark mode

Form Anatomy

ElementHeightFont SizeBorderFocus Ring
Input (default)h-9 (36px)text-smborder-input3px ring/50
Input (compact)h-8 (32px)text-xsborder-input3px ring/50
Select triggerh-9 (36px)text-smborder-input3px ring/50
Textareamin 80pxtext-smborder-input3px ring/50
Switch track1.15remnonering on focus
Labelautotext-sm · 500

Form Layout Patterns

Standard form: 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)

Model Settings
Configure the AI model and generation parameters
Choose your preferred model, resolution, and quality settings before generating.
Glass card recipe: 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)

PartComponentStyling
ContainerCard.RootGlass treatment, rounded-xl, gap-6, py-6
HeaderCard.Headerflex col gap-1.5, px-6
TitleCard.Titlefont-semibold, tracking-tight
DescriptionCard.Descriptiontext-sm, text-muted-foreground
ContentCard.Contentpx-6
FooterCard.Footerflex 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).

PropertyValue
Backgroundbg-card/40 backdrop-blur-md
Border radiusrounded-lg
Hover transformhover:scale-105 + multi-layer shadow
Transitiontransition-all duration-300
Default aspectaspect-square
Overlay (status)bg-black/50 rounded-lg
Model badgebg-black/60 text-white text-xs px-2 py-0.5
Favourite starbg-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.

Delete Image?
This action cannot be undone. The image will be permanently removed from your gallery.

Dialog Anatomy

PartImplementationStyling
BackdropPortal overlaybg-black/80 · fixed inset-0 · z-50
ContentDialog.Contentbg-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 buttonAbsolute top-rightX icon · opacity-70 · hover:opacity-100
AnimationSvelte transitionsfade-in + zoom-in-95 · 200ms
Dialog rules: 1) Always include a way to dismiss (close button or Cancel). 2) Destructive dialogs require a confirmation mechanism (type text, check box). 3) Dialogs should never appear on top of other dialogs — use sequential flow instead. 4) Focus is trapped inside the dialog while open.

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.

Default Secondary Error Outline ● Ready ⚠ Warning

Usage Guidelines

TypeVariantExample
Model indicatorOutline (text-xs)Flux1.dev, SDXL
Status badgeSuccess / WarningReady, Queue: 3
TagSecondary (text-xs)Landscape, Portrait, 4K
Count indicatorDefault (min-w-5 h-5)3 (selection count)
Image overlaybg-background/80 backdrop-blur-smModel 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.

Image generated
Your image is ready in the gallery.
Generation failed
Could not connect to the Pollinations API. Check your connection.
Queue full
Maximum concurrent generations reached. Please wait.
Model downloading
Flux1.dev is being downloaded to your ComfyUI instance.

Toast Anatomy

PropertyValue
Backgroundbg-card (solid, not glass)
Border1px solid var(--border)
Border radiusvar(--radius)
Width400px (max calc(100vw - 32px))
Shadow0 4px 12px rgba(0,0,0,0.15)
Success accent3px left border · oklch(0.723 0.219 150)
Error accent3px left border · var(--destructive)
Warning accent3px left border · oklch(0.828 0.189 84)
Info accent3px left border · var(--primary)
Titletext-sm · font-semibold
Descriptiontext-xs · opacity 0.85
Implementation: Toasts use the Sonner library via shadcn's Sonner component. Custom styling is applied through the 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.

PartBackgroundTextRadius
Tab listbg-mutedrounded-lg
Active tabbg-background + shadow-smtext-foregroundrounded-md
Inactive tabtransparenttext-muted-foreground

Progress

Progress bars indicate determinate loading states. They use the primary color against a tinted track.

Downloading model... 67%
PartHeightValues
Trackh-2 (8px)bg-primary/20 rounded-full
Fillh-2bg-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.

Pollinations Ready
ComfyUI Error
Connecting...
StateBackgroundDotBorder
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

Section A
Section B
Horizontal separator (full-width)

Tooltip

Delete (← Arrow Left)
Tooltip rules: Show tooltips on icon-only buttons (mandatory), keyboard shortcuts, and truncated text. Keep tooltip text under 50 characters. Use 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

Loading...
Processing image...
Spinner implementation: Uses Lucide's Loader2 icon with animate-spin. The spinner wraps the icon in a custom Spinner component at $lib/components/ui/spinner.