---
phase: 30
slug: onboarding-redesign
status: draft
shadcn_initialized: false
preset: none
created: 2026-04-12
---

# Phase 30 — UI Design Contract

> Visual and interaction contract for the onboarding redesign. Generated by gsd-ui-researcher, verified by gsd-ui-checker.

---

## Design System

| Property | Value |
|----------|-------|
| Tool | none |
| Preset | not applicable |
| Component library | none (pure Tailwind) |
| Icon library | Lucide via `LucideIcon` from `lib/iconData` |
| Font | System font stack (Tailwind default) |

---

## Spacing Scale

Declared values (must be multiples of 4):

| Token | Value | Usage |
|-------|-------|-------|
| xs | 4px | Icon gaps, inline badge padding |
| sm | 8px | Compact element spacing, tag gaps |
| md | 16px | Default element spacing, card padding |
| lg | 24px | Section padding, step content margins |
| xl | 32px | Step container padding |
| 2xl | 48px | Major section breaks between steps |
| 3xl | 64px | Page-level vertical padding (step centering) |

Exceptions: Hobby cards use 20px internal padding (5 in Tailwind) for visual balance with icons.

---

## Typography

| Role | Size | Weight | Line Height | Tailwind Class |
|------|------|--------|-------------|----------------|
| Body | 14px | 400 (normal) | 1.5 | `text-sm text-gray-500` |
| Label | 12px | 500 (medium) | 1.25 | `text-xs font-medium text-gray-400` |
| Heading | 18px | 600 (semibold) | 1.33 | `text-lg font-semibold text-gray-900` |
| Display | 30px | 700 (bold) | 1.2 | `text-3xl font-bold text-gray-900` |
| Step Subtitle | 16px | 400 (normal) | 1.5 | `text-base text-gray-500` |

---

## Color

| Role | Value | Usage |
|------|-------|-------|
| Dominant (60%) | `#FFFFFF` / `white` | Full-screen backgrounds, step containers |
| Secondary (30%) | `#F9FAFB` / `gray-50` | Card backgrounds, hobby card default state, item grid background |
| Accent (10%) | `#374151` / `gray-700` | Primary CTA buttons, active step indicator, selected hobby card border |
| Destructive | `#DC2626` / `red-600` | Not used in onboarding (no destructive actions) |

Accent reserved for: Primary "Get Started" / "Confirm" / "Continue" buttons, active progress indicator segment, selected hobby card outline ring.

### Selection States

| State | Visual Treatment |
|-------|-----------------|
| Hobby card default | `bg-gray-50 border border-gray-200 rounded-2xl` |
| Hobby card hover | `border-gray-300 shadow-sm` |
| Hobby card selected | `border-gray-700 ring-2 ring-gray-700/20 bg-white` |
| Item card default | `bg-white border border-gray-100 rounded-xl` |
| Item card hover | `border-gray-200 shadow-sm` |
| Item card selected | `border-gray-700 ring-2 ring-gray-700/20` with checkmark overlay |

---

## Copywriting Contract

| Element | Copy |
|---------|------|
| Welcome heading | "Welcome to GearBox" |
| Welcome body | "Tell us what you're into, and we'll help you set up your collection with gear that people actually use." |
| Primary CTA (welcome) | "Let's go" |
| Hobby picker heading | "What are you into?" |
| Hobby picker body | "Pick one or more — we'll show you popular gear for each." |
| Item browser heading | "Popular gear for {hobby}" |
| Item browser body | "Tap items you already own. We'll add them to your collection." |
| Item browser empty state heading | "No gear cataloged yet" |
| Item browser empty state body | "We're still building our catalog for this hobby. You can skip this step and add gear manually later." |
| Review heading | "Your starting collection" |
| Review body | "{N} items ready to add" |
| Review CTA | "Add to my collection" |
| Review empty | "No items selected — you can always add gear later from the catalog." |
| Skip link | "Skip this step" |
| Done heading | "You're all set!" |
| Done body | "Your collection is ready. Browse the catalog anytime to discover more gear." |
| Done CTA | "Start exploring" |

---

## Component Inventory

### OnboardingFlow (top-level)

Full-screen overlay replacing the current `OnboardingWizard`. Renders when `onboardingComplete !== "true"` and user is authenticated.

```
Layout: fixed inset-0 z-50 bg-white
Step container: flex flex-col items-center justify-center min-h-screen px-8
Max content width: max-w-2xl (672px) for text steps, max-w-5xl (1024px) for item grid
```

### Step Indicator

Full-width horizontal progress bar at the top of every step.

```
Container: fixed top-0 left-0 right-0 h-1 bg-gray-100
Progress fill: h-1 bg-gray-700 transition-all duration-500
Steps: Welcome=25%, Hobby=50%, Browse=75%, Review/Done=100%
```

### HobbyCard

Visual card for hobby selection. Displays icon + name + short descriptor.

```
Layout: w-40 h-40 flex flex-col items-center justify-center gap-3 p-5 rounded-2xl cursor-pointer transition-all
Icon: LucideIcon size={32}
Name: text-sm font-semibold text-gray-900
Descriptor: text-xs text-gray-400
Grid: flex flex-wrap justify-center gap-4
```

Hobby card data:

| Hobby | Icon | Descriptor |
|-------|------|------------|
| Bikepacking | `bike` | Ride & camp |
| Hiking | `mountain` | Trail gear |
| Climbing | `mountain-snow` | Vertical kit |
| Cycling | `circle-dot` | Road & gravel |
| Camping | `tent` | Base camp |
| Running | `footprints` | Run light |

### SelectableItemCard

Extends `GlobalItemCard` visual pattern with selection overlay.

```
Layout: Same as GlobalItemCard (bg-white rounded-xl border border-gray-100)
Selection overlay: absolute top-2 right-2, 24x24 circle
Unselected: border-2 border-gray-200 bg-white rounded-full
Selected: bg-gray-700 border-gray-700 rounded-full with white check icon (size 14)
Grid: grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4
```

### ReviewList

Summary of selected items grouped by category.

```
Category heading: text-xs font-medium text-gray-400 uppercase tracking-wide
Item row: flex items-center gap-3 py-2 border-b border-gray-50
Item image: w-10 h-10 rounded-lg object-cover bg-gray-50
Item name: text-sm text-gray-900
Remove button: text-gray-300 hover:text-red-500, X icon (size 16)
```

---

## Transitions

Step transitions use CSS transitions (no framer-motion dependency):

```
Enter: opacity-0 translate-y-4 → opacity-100 translate-y-0 (duration-300 ease-out)
Exit: opacity-100 translate-y-0 → opacity-0 -translate-y-4 (duration-200 ease-in)
```

Implementation: conditionally render steps with Tailwind transition classes and a brief `setTimeout` for exit animation before switching step state.

---

## Responsive Behavior

| Breakpoint | Behavior |
|------------|----------|
| Mobile (<640px) | Single column item grid, hobby cards 2-across, step content full-width with px-6 |
| Tablet (640-1024px) | 2-3 column item grid, hobby cards 3-across |
| Desktop (>1024px) | 4-column item grid, hobby cards in single centered row |

---

## Registry Safety

| Registry | Blocks Used | Safety Gate |
|----------|-------------|-------------|
| No external registries | none | not required |

All components are custom Tailwind — no shadcn or third-party UI blocks.

---

## Checker Sign-Off

- [ ] Dimension 1 Copywriting: PASS
- [ ] Dimension 2 Visuals: PASS
- [ ] Dimension 3 Color: PASS
- [ ] Dimension 4 Typography: PASS
- [ ] Dimension 5 Spacing: PASS
- [ ] Dimension 6 Registry Safety: PASS

**Approval:** pending
