banatie-service/docs/labs/design-system.md

9.3 KiB

Lab Section Design System

The Lab section is a production-ready UI interface for interacting with the Banatie API service. It provides a clean, work-focused experience for image generation, gallery browsing, alias management, and flow control.

File Structure

apps/landing/src/
├── app/(lab)/
│   ├── CLAUDE.md              # This design documentation
│   ├── layout.tsx             # Root lab layout with scroll context
│   └── lab/
│       ├── layout.tsx         # Sub-layout with PageProvider
│       ├── page.tsx           # Redirect to /lab/generate
│       ├── generate/page.tsx  # Generation workbench
│       ├── images/page.tsx    # Image gallery browser
│       ├── live/page.tsx      # Live generation testing
│       └── upload/page.tsx    # File upload interface
│
├── components/layout/lab/
│   ├── LabLayout.tsx          # Main layout (sidebar + content + footer)
│   ├── LabSidebar.tsx         # Left filter panel
│   └── LabFooter.tsx          # Contextual footer with links
│
├── components/lab/
│   ├── GenerateFormPlaceholder.tsx  # Generation form component
│   └── FilterPlaceholder.tsx        # Reusable filter checkbox/radio
│
└── contexts/
    └── lab-scroll-context.tsx  # Scroll state for header collapse

Design Principles

  1. Work-focused, not marketing - Small typography, efficient spacing
  2. Clean and functional - Like Google AI Studio
  3. Dual color system - Zinc for layout, Slate for forms
  4. Consistent icons - Lucide React only, no emojis
  5. Responsive - Works on 768px to 1920px+ screens

Color System

Layout/Chrome → Zinc (Neutral Gray)

Used for sidebar, footer, and layout borders:

bg-zinc-950       /* Sidebar background */
bg-zinc-950/50    /* Footer background, layout wrappers */
border-zinc-800   /* Layout borders, dividers */
text-zinc-400     /* Sidebar text */
text-zinc-500     /* Footer text, muted */

Forms/Cards → Slate (Original Style)

Used for cards, inputs, and interactive UI elements:

bg-slate-900/80   /* Card backgrounds */
bg-slate-900/50   /* Empty states, lighter cards */
bg-slate-800      /* Input backgrounds, secondary surfaces */
border-slate-700  /* Card borders, input borders */
text-gray-400     /* Labels, secondary text */
text-gray-500     /* Placeholders, hints */

Accent Colors (Purple/Cyan)

/* Primary gradient */
bg-gradient-to-r from-purple-600 to-cyan-600
hover:from-purple-500 hover:to-cyan-500
shadow-lg shadow-purple-900/30
focus:ring-2 focus:ring-purple-500

/* Single-color accents */
text-purple-400   /* Links, interactive text */

/* Info banners */
bg-purple-900/10 border-purple-700/50

Status Colors

/* Success */ bg-emerald-500/10 border-emerald-500/30 text-emerald-400
/* Warning */ bg-amber-500/10 border-amber-500/30 text-amber-400
/* Error   */ bg-red-500/10 border-red-500/30 text-red-400
/* Info    */ bg-purple-900/10 border-purple-700/50 text-purple-400

Typography Scale

Headings (Practical Sizes)

// Page Title (only on main pages)
text-lg font-semibold text-white

// Section Title
text-base font-semibold text-white

// Card Title
text-sm font-medium text-white

Body Text

// Primary body
text-sm text-gray-300

// Secondary/descriptions
text-sm text-gray-400

// Small text (hints, metadata)
text-xs text-gray-500

// Labels (form fields)
text-xs font-medium text-gray-400

Interactive

// Button text
text-sm font-semibold

// Links
text-sm text-purple-400 hover:text-purple-300

// Badge/count
text-xs text-gray-600

Spacing System

Padding

// Cards
p-4 md:p-5

// Compact cards
p-3

// Form inputs
px-3 py-2

// Buttons (primary)
px-4 py-2.5

// Buttons (secondary)
px-3 py-2

Section Spacing

// Page padding
p-4 md:p-6

// Between sections
space-y-4

// Between cards in grid
gap-3 md:gap-4

// Between form fields
gap-2

// Label to input
mb-1.5

Border Radius

rounded-lg     /* Standard (inputs, small cards) */
rounded-xl     /* Medium (cards) */

Component Patterns

Page Header

<header className="pb-3 border-b border-zinc-800">
  <div className="flex items-center gap-2">
    <Sparkles className="w-5 h-5 text-purple-400" />
    <div>
      <h1 className="text-lg font-semibold text-white">Generate</h1>
      <p className="text-xs text-gray-400">Create AI images from text prompts</p>
    </div>
  </div>
</header>

Form Card (Slate)

<section className="p-4 bg-slate-900/80 backdrop-blur-sm border border-slate-700 rounded-xl">
  {/* content */}
</section>

Form Input (Slate)

<div className="space-y-1.5">
  <label className="block text-xs font-medium text-gray-400">Field Label</label>
  <input
    className="w-full px-3 py-2 text-sm bg-slate-800 border border-slate-700 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent"
    placeholder="Enter value..."
  />
</div>

Textarea (Slate)

<textarea
  className="w-full px-3 py-2.5 text-sm bg-slate-800 border border-slate-700 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent resize-none"
  rows={4}
/>

Primary Button

<button className="px-4 py-2 text-sm rounded-lg bg-gradient-to-r from-purple-600 to-cyan-600 text-white font-semibold hover:from-purple-500 hover:to-cyan-500 transition-all shadow-lg shadow-purple-900/30 focus:ring-2 focus:ring-purple-500 flex items-center gap-1.5">
  <Sparkles className="w-4 h-4" />
  Generate
</button>

Secondary Button (Slate)

<button className="w-full px-3 py-2 text-sm bg-slate-800 border border-slate-700 rounded-lg text-gray-400 hover:text-white hover:bg-slate-700 transition-colors flex items-center justify-center gap-1.5 focus:ring-2 focus:ring-purple-500">
  <Settings className="w-4 h-4" />
  Configure
</button>

Empty State (Slate)

<div className="p-6 bg-slate-900/50 backdrop-blur-sm border border-slate-700 rounded-lg text-center">
  <div className="w-12 h-12 mx-auto mb-3 flex items-center justify-center bg-slate-800 rounded-lg">
    <ImageOff className="w-6 h-6 text-gray-500" />
  </div>
  <h3 className="text-sm font-medium text-white mb-1">No results yet</h3>
  <p className="text-xs text-gray-400">Generated images will appear here</p>
</div>

Info Banner

<div className="p-3 bg-purple-900/10 border border-purple-700/50 rounded-lg">
  <div className="flex items-start gap-2">
    <Info className="w-4 h-4 text-purple-400 mt-0.5 shrink-0" />
    <p className="text-xs text-gray-300">
      <span className="font-medium text-white">Lab Mode:</span> Experimental features enabled.
    </p>
  </div>
</div>

Icon System (Lucide React)

Standard Sizes

// Inline with text
<Icon className="w-4 h-4" />

// Small (badges)
<Icon className="w-3 h-3" />

// Medium (empty states)
<Icon className="w-6 h-6" />

// With margin (before text)
<Icon className="w-4 h-4 mr-1.5" />
// Navigation
import { Home, Image, Upload, Zap, Settings } from 'lucide-react';

// Actions
import { Plus, X, Download, Share2, Copy, Trash2, Edit3, MoreVertical } from 'lucide-react';

// Filters
import { Activity, Calendar, Palette, ChevronRight, ChevronDown } from 'lucide-react';

// Status
import { CheckCircle2, AlertCircle, XCircle, Info, Loader2 } from 'lucide-react';

// Media
import { ImageOff, FileImage, Sparkles } from 'lucide-react';

// Form
import { Search, Filter, SlidersHorizontal } from 'lucide-react';

Responsive Breakpoints

// Base: < 768px (mobile) - single column, no sidebar
// md: >= 768px (tablet) - 2 columns, no sidebar
// lg: >= 1024px (desktop) - sidebar visible, 2-3 columns
// xl: >= 1280px (large desktop) - optimal spacing, 3 columns

Sidebar Behavior

// Hidden on mobile/tablet, visible lg+
hidden lg:block w-64

Content Grid

// Images: 1 col mobile, 2 col tablet, 3 col desktop
grid-cols-1 md:grid-cols-2 xl:grid-cols-3

// Form fields
grid-cols-1 md:grid-cols-3

Do's and Don'ts

DO

  • Use zinc for layout (sidebar, footer, layout borders)
  • Use slate for forms (cards, inputs, empty states)
  • Use text-sm/text-xs for most text
  • Use Lucide icons exclusively
  • Keep spacing tight (p-3 to p-5)
  • Add focus:ring-2 focus:ring-purple-500 to all interactive elements
  • Use transitions (transition-colors, transition-all)

DON'T

  • Use emojis anywhere in the UI
  • Use marketing-size headings (text-3xl+)
  • Use generous spacing (p-8+, py-12+)
  • Mix zinc and slate inconsistently
  • Forget aria-label on icon-only buttons

Layout Architecture

The Lab uses a scroll-aware header system:

  1. LabScrollProvider wraps the entire section
  2. LabLayout detects scroll > 50px in content area
  3. When scrolled, header collapses (h-16 → h-0)
  4. SubsectionNav becomes the top element
  5. Content height adjusts: h-[calc(100vh-7rem)]h-[calc(100vh-3rem)]
// Layout hierarchy
(lab)/layout.tsx           LabScrollProvider + LabHeader
  └── lab/layout.tsx       PageProvider (SubsectionNav)
      └── LabLayout.tsx    ThreeColumnLayout (sidebar + content + footer)
          └── page.tsx     Actual page content