# UX Spec

> Generates UI/UX specifications with wireframes and design system. Creates UX_SPEC.md and DESIGN_SYSTEM.md from PRD and Architecture specs. Use when designing app interface and creating design system.

- Skill: `rshankras/ux-spec` (Agent Skill)
- Install (CLI): `npx skillmds add rshankras/ux-spec`
- Raw SKILL.md: https://api.skillmd.com/api/skills/rshankras/ux-spec/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Product & Planning
- Author: rshankras (https://skillmd.com/u/rshankras)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/rshankras/ux-spec

---


# UX Specification Skill

Generate comprehensive UI/UX specifications with wireframes and design system for iOS/macOS apps.

## Metadata
- **Name**: ux-spec
- **Version**: 1.0.0
- **Role**: UI/UX Designer
- **Author**: ProductAgent Team

## When This Skill Activates

This skill activates when the user says:
- "generate UI spec"
- "create UX specification"
- "design wireframes"
- "create design system"
- "generate UX spec from PRD"

## Description

You are a UI/UX Designer AI agent specializing in iOS/macOS app design. Your job is to transform product requirements and architecture into comprehensive, actionable UI/UX specifications that developers can implement directly.

## Prerequisites

Before activating this skill, ensure:
1. PRD exists (from prd-generator skill)
2. ARCHITECTURE.md exists (from architecture-spec skill)
3. Product development plan with positioning and brand personality

## Input Sources

Read and extract information from:
1. **docs/PRD.md**
   - All features and requirements
   - User flows and user stories
   - Target audience
   - Acceptance criteria

2. **docs/ARCHITECTURE.md**
   - App structure and navigation
   - Data models (to understand what to display)
   - Platform (iOS/macOS)

3. **Product development plan** (product-plan-*.md)
   - Positioning and brand personality
   - Value proposition
   - Target market

4. **User clarifications** (ask if needed):
   - Preferred design style (minimalist, colorful, professional, playful)
   - Any brand colors or existing branding
   - Key screens to prioritize

## Output

Generate two comprehensive documents:

### 1. docs/UX_SPEC.md

```markdown
# UI/UX Specification: [App Name]

**Version**: 1.0.0
**Last Updated**: [Date]
**Status**: Draft / In Review / Approved
**Designer**: UX Designer AI
**Platform**: iOS / macOS

---

## 1. Design Principles

### 1.1 Core Principles
1. **[Principle 1]**: [e.g., "Simplicity over features - Every screen should have one primary action"]
2. **[Principle 2]**: [e.g., "Glanceable information - Users should understand content in < 5 seconds"]
3. **[Principle 3]**: [e.g., "Gesture-first interaction - Leverage native iOS gestures"]
4. **[Principle 4]**: [e.g., "Progressive disclosure - Show advanced features only when needed"]

### 1.2 Brand Personality
**From Positioning**: [e.g., "Professional, trustworthy, modern with a human touch"]

**Design Expression**:
- Visual style: [Clean, minimal, lots of whitespace]
- Tone: [Friendly but professional]
- Imagery: [Photography-based vs. illustration-based]

---

## 2. Information Architecture

### 2.1 App Structure

**Navigation Pattern**: [TabView / NavigationStack / Sidebar (iPad)]

**Screen Hierarchy**:
```
App Root
├── Tab 1: [Home]
│   ├── [Home Screen]
│   ├── [Item Detail Screen]
│   └── [Edit Item Screen]
├── Tab 2: [Discover]
│   ├── [Discover Screen]
│   └── [Category Detail Screen]
├── Tab 3: [Profile]
│   ├── [Profile Screen]
│   └── [Settings Screen]
└── Shared
    ├── [Login Screen]
    ├── [Onboarding Flow]
    └── [Error/Empty States]
```

### 2.2 Screen Inventory

| Screen Name | Purpose | Navigation | Priority |
|-------------|---------|------------|----------|
| Onboarding | First-time user education | Modal → Home | P0 |
| Home | Primary content view | Root tab | P0 |
| Item Detail | View single item details | Push from Home | P0 |
| Add/Edit Item | Create or modify item | Modal/Push | P0 |
| Profile | User profile and settings | Root tab | P1 |
| Settings | App preferences | Push from Profile | P1 |

### 2.3 Navigation Flow Diagram

```
[Splash] → [Onboarding] → [Home (Tab 1)]
                              ↓
                         [Item Detail]
                              ↓
                         [Edit Item]

[Profile (Tab 3)] → [Settings]
                  → [Account]
```

---

## 3. Screen Specifications

### 3.1 Onboarding Flow

**Purpose**: Help new users understand value and complete initial setup

**Screens**: 3 screens + Welcome

#### Screen 1: Welcome

**Layout** (ASCII wireframe):
```
┌─────────────────────────────────────┐
│                                     │
│                                     │
│          [App Icon/Logo]            │
│                                     │
│                                     │
│         Welcome to [AppName]        │
│                                     │
│      [One-line value proposition]   │
│                                     │
│                                     │
│                                     │
│         [Get Started Button]        │
│                                     │
│      Already have an account?       │
│             [Sign In]               │
│                                     │
└─────────────────────────────────────┘
```

**Components**:
- **App Icon/Logo**: Centered, large (120pt)
- **Welcome Title**: .largeTitle, bold, centered
- **Value Proposition**: .title3, secondary color, centered, max 2 lines
- **Get Started Button**: Primary button style, full width with margin
- **Sign In Link**: Text button, smaller, muted color

**Interactions**:
- Tap "Get Started" → Navigate to Onboarding Screen 1
- Tap "Sign In" → Navigate to Login Screen
- Swipe not enabled (no skip on welcome)

**States**:
- Default: All elements visible
- Loading: Show activity indicator if checking auth state

**Animations**:
- Fade in on appear (0.5s)
- Button press: Scale 0.95 with haptic feedback

---

#### Screen 2: Onboarding Step 1

**Purpose**: Explain primary feature/benefit

**Layout**:
```
┌─────────────────────────────────────┐
│  ○ ● ○                     [Skip]   │  (Progress + Skip)
├─────────────────────────────────────┤
│                                     │
│                                     │
│         [Feature Illustration]      │
│              or Screenshot          │
│                                     │
│                                     │
├─────────────────────────────────────┤
│                                     │
│       [Headline - Feature Name]     │
│                                     │
│     [Description - 2-3 lines        │
│      explaining the benefit]        │
│                                     │
├─────────────────────────────────────┤
│                                     │
│            [Next Button]            │
│                                     │
└─────────────────────────────────────┘
```

**Components**:
- **Progress Indicator**: 3 dots, current = filled circle
- **Skip Button**: Text button, top-right
- **Illustration**: Hero image or screenshot, 300pt height
- **Headline**: .title2, bold, benefit-focused
- **Description**: .body, 2-3 lines, explain value not feature
- **Next Button**: Primary button, full width

**Interactions**:
- Tap "Next" → Navigate to Onboarding Step 2
- Tap "Skip" → Navigate to Home (mark onboarding complete)
- Swipe left → Next screen
- Swipe right → Previous screen

**Content Guidelines**:
- Focus on BENEFITS not features
- Use "you" language ("You can organize all your tasks")
- Keep concise (< 20 words per description)

---

#### Screen 3: Onboarding Step 2 & 3
[Repeat structure for remaining onboarding screens]

---

### 3.2 Home Screen

**Purpose**: Display primary content and enable main user actions

**Layout** (iPhone Portrait):
```
┌─────────────────────────────────────┐
│  ←  Home              [+]  [⚙️]     │  (Navigation Bar)
├─────────────────────────────────────┤
│                                     │
│  Search...                    [🔍]  │  (Search Bar)
│                                     │
├─────────────────────────────────────┤
│                                     │
│  ┌───────────────────────────────┐ │
│  │  [Thumbnail]  Card Title      │ │  (Card Component)
│  │               Subtitle • Meta │ │
│  │               [Status Badge]  │ │
│  └───────────────────────────────┘ │
│                                     │
│  ┌───────────────────────────────┐ │
│  │  [Thumbnail]  Card Title      │ │
│  │               Subtitle • Meta │ │
│  │               [Status Badge]  │ │
│  └───────────────────────────────┘ │
│                                     │
│  ┌───────────────────────────────┐ │
│  │  [Thumbnail]  Card Title      │ │
│  │               Subtitle • Meta │ │
│  │               [Status Badge]  │ │
│  └───────────────────────────────┘ │
│                                     │
├─────────────────────────────────────┤
│  [Tab1]  [Tab2]  [Tab3]  [Tab4]    │  (Tab Bar)
└─────────────────────────────────────┘
```

**Components**:

**Navigation Bar**:
- Title: "Home" (.largeTitle when scrolled to top, .inline when scrolling)
- Leading: Back button (if navigated from elsewhere)
- Trailing:
  - [+] Add button → Navigate to Add Item
  - [⚙️] Settings button → Navigate to Settings

**Search Bar** (Optional, based on requirements):
- Placeholder: "Search [items]..."
- Style: .searchable modifier
- Clear button when text entered
- Dismiss on scroll down

**Card List**:
- Container: SwiftUI List with .plain style
- Card spacing: 12pt between cards
- Card style: See "Card Component" section below

**Tab Bar** (if using tabs):
- 3-5 tabs maximum
- Active tab: Primary color
- Inactive tabs: Secondary/gray color
- Badge: Red dot for notifications (if applicable)

**Interactions**:
- **Tap card** → Navigate to Item Detail Screen
- **Swipe left on card** → Show Delete action (red background, trash icon)
- **Swipe right on card** → Show Archive action (if applicable)
- **Pull down** → Refresh content (show activity indicator)
- **Tap [+]** → Present Add Item sheet
- **Tap [⚙️]** → Navigate to Settings
- **Search** → Filter list in real-time as user types
- **Scroll to top** → Navigation bar title animates to large title

**States**:

**Empty State**:
```
┌─────────────────────────────────────┐
│                                     │
│                                     │
│           [Empty Icon]              │
│              (tray)                 │
│                                     │
│          No Items Yet               │
│                                     │
│     Get started by tapping the      │
│           + button above            │
│                                     │
│                                     │
└─────────────────────────────────────┘
```
- Use ContentUnavailableView (iOS 17+)
- Icon: SF Symbol related to content type
- Title: Friendly, not error-focused
- Description: Clear call to action

**Loading State**:
```
┌─────────────────────────────────────┐
│                                     │
│                                     │
│       [Loading Spinner]             │
│          Loading...                 │
│                                     │
│                                     │
└─────────────────────────────────────┘
```
- Full-screen overlay with .ultraThinMaterial background
- Activity indicator (.large size)
- Optional "Loading..." text below

**Error State**:
```
┌─────────────────────────────────────┐
│                                     │
│                                     │
│      [Error Icon] (exclamationmark) │
│                                     │
│       Couldn't load items           │
│                                     │
│   [Error description message]       │
│                                     │
│         [Try Again Button]          │
│                                     │
└─────────────────────────────────────┘
```
- ContentUnavailableView with error styling
- Clear error message (user-friendly, not technical)
- Retry button to attempt reload

**Skeleton/Shimmer State** (Alternative to loading spinner):
```
┌─────────────────────────────────────┐
│  ┌───────────────────────────────┐ │
│  │  [▓▓▓]  ▓▓▓▓▓▓▓▓▓▓           │ │  (Shimmer effect)
│  │         ▓▓▓▓▓▓▓ • ▓▓▓         │ │
│  └───────────────────────────────┘ │
│  ┌───────────────────────────────┐ │
│  │  [▓▓▓]  ▓▓▓▓▓▓▓▓▓▓           │ │
│  │         ▓▓▓▓▓▓▓ • ▓▓▓         │ │
│  └───────────────────────────────┘ │
└─────────────────────────────────────┘
```
- Show 3-5 placeholder cards
- Animated shimmer effect (subtle, not distracting)
- Replace with real content when loaded

**Data Requirements**:
- Array of items: [Item]
- Each item needs: id, title, subtitle, thumbnailURL, status, metadata
- Sorting: By date (newest first) or user preference
- Filtering: Based on search query

**Accessibility**:
- VoiceOver label for each card: "[Title], [Subtitle], [Status]"
- Add button: "Add new item"
- Settings button: "Settings"
- Swipe actions announced: "Swipe right or left for actions"
- Search bar: "Search [items]"

---

### 3.3 Item Detail Screen

**Purpose**: Display full details of a single item

**Layout**:
```
┌─────────────────────────────────────┐
│  ← [Item Title]          [Edit]     │  (Navigation Bar)
├─────────────────────────────────────┤
│                                     │
│        [Hero Image/Thumbnail]       │
│              (Full width)           │
│                                     │
├─────────────────────────────────────┤
│                                     │
│  [Item Title]                       │
│  [Subtitle or Category]             │
│                                     │
│  [Status Badge]  [Metadata]         │
│                                     │
├─────────────────────────────────────┤
│                                     │
│  Description                        │
│  ─────────────                      │
│  [Full description text, can be     │
│   multiple paragraphs. Lorem ipsum  │
│   dolor sit amet...]                │
│                                     │
├─────────────────────────────────────┤
│                                     │
│  Details                            │
│  ────────                           │
│  Created: [Date]                    │
│  Modified: [Date]                   │
│  Author: [Name]                     │
│                                     │
├─────────────────────────────────────┤
│                                     │
│  Related Items                      │
│  ──────────────                     │
│  ┌─────────┐ ┌─────────┐           │
│  │ [Item1] │ │ [Item2] │           │
│  └─────────┘ └─────────┘           │
│                                     │
├─────────────────────────────────────┤
│                                     │
│         [Primary Action]            │
│         [Secondary Action]          │
│                                     │
└─────────────────────────────────────┘
```

**Components**:
- **Navigation Bar**: Item title (truncate if > 25 chars), Edit button
- **Hero Image**: Full-width, 16:9 aspect ratio, 250pt height
- **Title Section**: .title2 bold, subtitle .subheadline
- **Status Badge**: Rounded rectangle, color-coded by status
- **Description**: .body text, full paragraph formatting
- **Details Section**: Key-value pairs, .callout size, secondary color
- **Related Items**: Horizontal scroll, 100pt width cards
- **Action Buttons**: Primary (full width), Secondary (outlined)

**Interactions**:
- Tap "Edit" → Navigate to Edit Screen
- Tap Hero Image → Open full-screen image viewer (pinch to zoom)
- Tap Related Item → Navigate to that item's detail screen
- Swipe back → Return to Home
- Scroll → Navigation bar collapses to inline title

**States**:
- **Loading**: Show skeleton for all sections while data loads
- **Error**: Show error message inline (not full-screen)
- **No Image**: Show placeholder icon/gradient
- **No Description**: Hide section entirely (don't show empty)
- **No Related Items**: Hide section

---

### 3.4 Add/Edit Item Screen

**Purpose**: Create new item or modify existing

**Layout** (Sheet/Modal):
```
┌─────────────────────────────────────┐
│  [Cancel]  Add Item        [Save]   │  (Modal Header)
├─────────────────────────────────────┤
│                                     │
│  ┌───────────────────────────────┐ │
│  │   + Add Photo                 │ │  (Image Picker)
│  └───────────────────────────────┘ │
│                                     │
│  Title                              │
│  ┌───────────────────────────────┐ │
│  │ [Enter title...]              │ │
│  └───────────────────────────────┘ │
│                                     │
│  Category                           │
│  ┌───────────────────────────────┐ │
│  │ [Select category]       [▼]   │ │
│  └───────────────────────────────┘ │
│                                     │
│  Description                        │
│  ┌───────────────────────────────┐ │
│  │ [Enter description...]        │ │
│  │                               │ │
│  │                               │ │
│  └───────────────────────────────┘ │
│                                     │
│  Status                             │
│  ○ Active    ○ Pending    ○ Done   │
│                                     │
│                                     │
│         [Delete Item]               │  (Edit only)
│                                     │
└─────────────────────────────────────┘
```

**Components**:
- **Modal Header**: Cancel (leading), Title (center), Save (trailing, blue)
- **Image Picker**: Dashed border, + icon, tap to open photo picker
- **Text Fields**: Native iOS style, floating labels
- **Dropdown**: Chevron indicator, opens picker/sheet
- **Text Area**: Multiline, min 3 lines
- **Radio Group**: Horizontal segmented control or vertical radio buttons
- **Delete Button**: Destructive style, bottom of form (edit mode only)

**Interactions**:
- Tap "Cancel" → Dismiss sheet, confirm if unsaved changes
- Tap "Save" → Validate, save, dismiss, return to previous screen
- Tap Image Picker → Present photo picker (Camera + Photo Library)
- Tap Dropdown → Present selection sheet/picker
- Typing → Show character count if there's a limit
- Tap Delete → Show destructive alert confirmation

**Validation**:
- Required fields: Show red outline + error message on save attempt
- Character limits: Show count (e.g., "120/150 characters")
- Invalid format: Show inline error below field

**States**:
- **Add Mode**: Empty fields, no Delete button
- **Edit Mode**: Pre-filled fields, Delete button visible
- **Saving**: Disable Save button, show spinner
- **Error**: Show alert with error message, keep form open

---

### 3.5 Settings Screen

**Purpose**: App preferences and account management

**Layout**:
```
┌─────────────────────────────────────┐
│  ← Settings                         │
├─────────────────────────────────────┤
│                                     │
│  Account                            │
│  ┌───────────────────────────────┐ │
│  │  [👤]  [User Name]        [>] │ │
│  │        user@email.com          │ │
│  └───────────────────────────────┘ │
│                                     │
│  Preferences                        │
│  ┌───────────────────────────────┐ │
│  │  Notifications          [○●]  │ │  (Toggle)
│  │  Dark Mode              [○●]  │ │
│  │  Language               [>]   │ │
│  └───────────────────────────────┘ │
│                                     │
│  Data & Privacy                     │
│  ┌───────────────────────────────┐ │
│  │  Privacy Policy         [>]   │ │
│  │  Terms of Service       [>]   │ │
│  │  Delete Account         [>]   │ │
│  └───────────────────────────────┘ │
│                                     │
│  About                              │
│  ┌───────────────────────────────┐ │
│  │  App Version      1.0.0       │ │
│  │  Rate Us                [>]   │ │
│  │  Contact Support        [>]   │ │
│  └───────────────────────────────┘ │
│                                     │
│                                     │
│          [Sign Out]                 │
│                                     │
└─────────────────────────────────────┘
```

**Components**:
- **Section Headers**: .caption uppercase, secondary color, 24pt top padding
- **Grouped List**: iOS native .insetGrouped style
- **Row**: 44pt min height, tap area full width
- **Toggle**: iOS native switch, tappable label + switch
- **Disclosure**: Chevron on trailing edge
- **Sign Out Button**: Destructive style, centered, bottom

**Interactions**:
- Tap row with [>] → Navigate to detail screen
- Tap toggle → Immediate change (save to UserDefaults/CloudKit)
- Tap "Sign Out" → Show confirmation alert

---

## 4. Component Library

### 4.1 Buttons

#### Primary Button
**Style**:
- Background: Brand Primary color
- Text: White, .headline font
- Corner radius: 12pt
- Height: 50pt
- Padding: 16pt horizontal
- Shadow: radius 4, y: 2, opacity 0.1

**States**:
- Normal: Full color
- Pressed: Opacity 0.8 + scale 0.98
- Disabled: Opacity 0.5, no interaction
- Loading: Show spinner, disable interaction

**Code Example**:
```swift
.font(.headline)
.foregroundColor(.white)
.frame(maxWidth: .infinity)
.frame(height: 50)
.background(Color.brandPrimary)
.cornerRadius(12)
.shadow(radius: 4, y: 2)
```

#### Secondary Button
**Style**:
- Background: Clear
- Border: 2pt, Brand Primary color
- Text: Brand Primary color, .headline
- Corner radius: 12pt
- Height: 50pt

**States**: Same as Primary Button

#### Text Button
**Style**:
- Background: None
- Text: Brand Primary color, .body or .callout
- No border
- Height: Auto (text height + padding)

**States**:
- Normal: Primary color
- Pressed: Opacity 0.6
- Disabled: Secondary color, no interaction

---

### 4.2 Cards

#### Standard Card
**Style**:
- Background: White (light mode) / .secondarySystemBackground (dark mode)
- Corner radius: 12pt
- Padding: 16pt
- Shadow: radius 8, y: 2, opacity 0.1
- Border: None (use shadow for elevation)

**Layout**:
```
┌───────────────────────────────┐
│  [Thumbnail]  Title           │
│  (60x60pt)    Subtitle        │
│               Metadata        │
└───────────────────────────────┘
```

**Spacing**:
- Thumbnail to text: 12pt
- Title to subtitle: 4pt
- Text to edge: 16pt

#### Highlighted Card
**Differences from Standard**:
- Border: 2pt, Brand Primary color
- Background: Tinted (Primary color at 5% opacity)
- Shadow: Slightly larger (radius 10)

---

### 4.3 Forms

#### Text Input
**Style**:
- Height: 50pt
- Padding: 16pt horizontal
- Background: .secondarySystemBackground
- Corner radius: 10pt
- Border: 1pt, clear (2pt primary color when focused)
- Font: .body

**States**:
- Default: Gray background, no border
- Focused: White background, blue border
- Error: Red border, red tint
- Disabled: Reduced opacity, no interaction

**With Label**:
- Label above input, .caption size, secondary color
- 8pt spacing between label and input

**With Error**:
- Error message below input, .caption size, red color
- Error icon (exclamationmark.circle) leading

---

### 4.4 Typography Styles

**Usage Guide**:
- **Large Title**: Screen titles (Home, Settings)
- **Title**: Section headers
- **Title 2**: Card titles, detail screen main heading
- **Title 3**: Subsection headers
- **Headline**: Button labels, emphasized text
- **Body**: Default text, descriptions
- **Callout**: Metadata, secondary information
- **Subheadline**: Subtitles, labels
- **Footnote**: Timestamps, hints
- **Caption**: Section headers (uppercase), disclaimers

---

## 5. Interaction Patterns

### 5.1 Gestures

| Gesture | Use Case | Feedback |
|---------|----------|----------|
| Tap | Primary action, select, open | Visual (highlight), Haptic (light) |
| Long Press | Context menu, preview | Visual (scale up), Haptic (medium) |
| Swipe Left | Delete, remove | Visual (red background), Haptic (none) |
| Swipe Right | Archive, mark done | Visual (green background), Haptic (success) |
| Pull Down | Refresh content | Visual (activity indicator), Haptic (light when triggered) |
| Pinch | Zoom image, map | Visual (scale), Haptic (none) |
| Edge Swipe | Back navigation | Visual (screen slide), Haptic (none) |

### 5.2 Animations

#### Screen Transitions
- **Push/Pop**: Native NavigationStack animation (slide from right)
- **Modal**: Sheet from bottom, 0.3s ease-in-out
- **Full Screen**: Fade in, 0.2s

#### Element Animations
- **List Item Appear**: Fade + slide up, 0.3s, staggered by 0.05s
- **Button Press**: Scale to 0.95, 0.1s
- **Toggle**: Native iOS switch animation
- **Skeleton → Content**: Fade out skeleton, fade in content, 0.2s

#### Loading States
- **Spinner**: Continuous rotation, native iOS style
- **Progress Bar**: Fill animation, 0.5s per segment
- **Shimmer**: Gradient sweep, 1.5s repeat

### 5.3 Haptic Feedback

**When to Use**:
- ✅ Button taps (light)
- ✅ Toggle switches (light)
- ✅ Pull-to-refresh triggered (medium)
- ✅ Successful action (success pattern)
- ✅ Error occurred (error pattern)
- ❌ Scrolling (no haptic)
- ❌ Text input (no haptic)
- ❌ Standard navigation (no haptic)

**Implementation**:
```swift
import CoreHaptics

// Light impact
let impact = UIImpactFeedbackGenerator(style: .light)
impact.impactOccurred()

// Success notification
let notification = UINotificationFeedbackGenerator()
notification.notificationOccurred(.success)
```

---

## 6. Accessibility

### 6.1 VoiceOver

**Requirements**:
- All interactive elements must have labels
- Labels should describe action, not appearance
- Images need descriptions (decorative = empty label)
- Status changes should be announced

**Examples**:
- Button: "Add new item" (not "Plus button")
- Card: "Meeting notes, Created 2 hours ago, Tap to view details"
- Image: "Profile photo of John Doe" or "" if decorative
- Toggle: "Notifications, On, Toggle switch" (system provides toggle part)

**Testing**:
- Enable VoiceOver in Simulator (Cmd+F5)
- Navigate with swipe gestures
- Verify all elements are reachable and labeled

### 6.2 Dynamic Type

**Support all text sizes**: Extra Small to Accessibility XXL

**Implementation**:
```swift
Text("Title")
    .font(.title)  // Automatically scales
    .lineLimit(nil)  // Allow wrapping
    .minimumScaleFactor(0.8)  // If must fit one line
```

**Layout Adjustments**:
- Stack elements vertically at larger sizes
- Increase spacing proportionally
- Ensure minimum tap targets (44x44pt)

**Testing**:
- Settings → Accessibility → Display & Text Size → Larger Text
- Test at XS, default, and XXL sizes

### 6.3 Color Contrast

**WCAG AA Standards**:
- Text: 4.5:1 minimum contrast ratio
- Large text (18pt+): 3:1 minimum
- UI elements: 3:1 minimum

**Testing Tools**:
- Xcode Accessibility Inspector
- Online: WebAIM Contrast Checker
- Test in both light and dark modes

**Common Issues**:
- Light gray text on white background (increase contrast)
- Color-only indicators (add icon or label)
- Low opacity overlays (ensure text remains readable)

### 6.4 Reduced Motion

**Respect System Setting**:
```swift
@Environment(\.accessibilityReduceMotion) var reduceMotion

if reduceMotion {
    // Use fade instead of slide
    // Reduce animation duration
    // Remove complex animations
}
```

**Alternatives**:
- Replace slide animations with instant transitions
- Replace complex spring animations with linear fades
- Reduce animation duration by 50%
- Keep critical animations (loading, errors)

---

## 7. Dark Mode

### 7.1 Color Adaptation

**Semantic Colors** (Automatic):
- Use system colors when possible (they adapt automatically)
- `.primary`, `.secondary` for text
- `.background`, `.secondaryBackground` for surfaces

**Custom Colors**:
- Define in Assets.xcassets with Appearances: "Any, Dark"
- Provide separate values for each mode
- Test all screens in both modes

### 7.2 Image Adaptation

**Techniques**:
- Template images (tint to match color scheme)
- Separate dark mode assets (image_name~dark.png)
- Reduce opacity of photos in dark mode (optional)

### 7.3 Dark Mode Best Practices

**Do**:
- Use true black (#000000) sparingly (only for OLED optimization)
- Use elevated surfaces (lighter) for cards/modals
- Maintain visual hierarchy (contrast between levels)
- Test with "Increase Contrast" enabled

**Don't**:
- Don't invert light mode colors (design separately)
- Don't use pure white text (#FFFFFF) - use slightly off-white
- Don't forget shadows (they disappear on dark backgrounds)

---

## 8. Responsive Design

### 8.1 iPhone Sizes

**Layouts to Support**:
- **iPhone SE (3rd gen)**: 375pt width (smallest)
- **iPhone 15**: 393pt width
- **iPhone 15 Pro Max**: 430pt width (largest)

**Adaptation Strategy**:
- Use flexible layouts (HStack, VStack, Grid)
- Set minimum widths, allow expansion
- Test safe area insets (notch, Dynamic Island)

### 8.2 iPad (Optional)

**Layout Changes**:
- Sidebar navigation instead of tabs
- Multi-column layouts (master-detail)
- Larger cards (2-3 columns in grid)
- Utilize horizontal space

**Keyboard Support**:
- Cmd+N: New item
- Cmd+F: Focus search
- Cmd+S: Save
- Cmd+W: Close modal

### 8.3 Orientation

**Portrait**: Default, all screens optimized
**Landscape**:
- iPhone: Optional (usually lock to portrait)
- iPad: Required, adjust layout

---

## 9. Edge Cases & Error Handling

### 9.1 Network States

| State | User Experience | System Behavior |
|-------|-----------------|-----------------|
| No connection | "No internet connection. Showing saved data." banner at top | Use cached data, disable sync, queue changes |
| Slow connection | Loading indicator, timeout after 30s | Show skeleton screens, async load images |
| Connection restored | "Back online" banner (auto-dismiss 3s) | Trigger sync, upload queued changes |

### 9.2 Data States

| State | User Experience | System Behavior |
|-------|-----------------|-----------------|
| Empty list | ContentUnavailableView with CTA | Hide list, show empty state |
| Single item | Show list with one item (not special case) | Same as multiple items |
| Thousands of items | Paginated, lazy loading, search encouraged | Load 50 at a time, virtual scrolling |

### 9.3 Input Validation

| Invalid Input | User Experience | Prevention |
|---------------|-----------------|------------|
| Empty required field | Red outline, "This field is required" below | Disable Save button |
| Invalid email | "Please enter a valid email" | Real-time validation |
| Duplicate entry | Alert: "Item already exists. Continue?" | Check on save, allow override |

### 9.4 Permission States

| Permission | Denied | Granted |
|------------|--------|---------|
| Camera | Show alert: "Camera access needed. Open Settings?" | Open camera picker |
| Photos | Show placeholder, "Tap to allow photo access" | Open photo picker |
| Notifications | App works without, show banner once | Send notifications |
| Location | Feature disabled, show upgrade message | Show map with location |

---

## 10. Platform-Specific Considerations

### 10.1 iOS Human Interface Guidelines

**Follow These Patterns**:
- Navigation: Use NavigationStack, not custom
- Tabs: Max 5 tabs, use "More" tab if needed
- Modals: Sheet for forms, fullScreenCover for immersive
- Lists: Use native List with proper row heights (44pt min)
- Search: Use .searchable modifier
- Pull-to-refresh: Use .refreshable modifier
- Context menus: Long press for actions

**Avoid**:
- Custom navigation that doesn't follow back button patterns
- Non-standard gestures (users expect iOS conventions)
- Hamburger menus (use tabs or sidebar on iPad)
- Bottom sheets (use native sheets from bottom)

### 10.2 iOS 17+ Features to Leverage

**Adopt New APIs**:
- ContentUnavailableView for empty states
- @Observable for view models (instead of ObservableObject)
- SwiftData for persistence (instead of Core Data)
- #Preview macros (instead of PreviewProvider)
- Sensory feedback API (instead of UIImpactFeedbackGenerator)

**Test on iOS 17+**: Set minimum deployment target to iOS 17.0

---

## 11. Design Handoff Checklist

Before considering UX spec complete:

- [ ] All screens from PRD are designed with wireframes
- [ ] Empty, loading, and error states defined for all screens
- [ ] All interactive elements specified (tap, swipe, long press)
- [ ] Navigation flow is clear and consistent
- [ ] Component library covers all UI elements used
- [ ] Accessibility requirements documented (VoiceOver, Dynamic Type)
- [ ] Dark mode adaptations specified
- [ ] Responsive behavior defined (iPhone sizes)
- [ ] Edge cases and error scenarios handled
- [ ] Animation and haptic feedback specified
- [ ] Colors, typography, spacing all reference design system
- [ ] No placeholder or "TBD" items remain

---

## Appendix A: Screen Specifications Template

Use this template for additional screens not detailed above:

```markdown
### X.X [Screen Name]

**Purpose**: [One sentence describing what user accomplishes]

**Layout** (ASCII wireframe):
```
┌─────────────────────────────────────┐
│  [Navigation Bar]                   │
├─────────────────────────────────────┤
│                                     │
│  [Main Content Area]                │
│                                     │
├─────────────────────────────────────┤
│  [Bottom Bar / Actions]             │
└─────────────────────────────────────┘
```

**Components**:
- [Component 1]: [Description]
- [Component 2]: [Description]

**Interactions**:
- Tap [Element] → [Result]
- Swipe [Direction] → [Action]

**States**:
- Empty: [How it looks]
- Loading: [How it looks]
- Error: [How it looks]

**Data Requirements**:
- [Data needed from backend/storage]

**Accessibility**:
- [VoiceOver labels]
- [Special considerations]
```

---

**Document History**:
| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 1.0.0 | [Date] | UX Designer AI | Initial UX specification |
```

### 2. docs/DESIGN_SYSTEM.md

```markdown
# Design System: [App Name]

**Version**: 1.0.0
**Last Updated**: [Date]
**Platform**: iOS 17+
**Language**: SwiftUI

---

## 1. Brand Identity

### 1.1 Brand Personality
**From Positioning**: [e.g., "Professional, trustworthy, modern with a human touch"]

**Visual Expression**:
- **Modern**: Clean lines, generous whitespace, sans-serif typography
- **Professional**: Muted color palette, consistent spacing, subtle animations
- **Approachable**: Friendly copy, helpful empty states, forgiving errors

### 1.2 Voice & Tone

**Voice** (Consistent):
- Clear and concise
- Helpful, not bossy
- Human, not robotic
- Confident, not arrogant

**Tone** (Context-dependent):
- **Success**: Encouraging ("Great job!")
- **Error**: Apologetic and helpful ("Oops! Let's try that again.")
- **Onboarding**: Excited and welcoming ("Welcome! Let's get started.")
- **Empty state**: Optimistic ("Ready to create your first item?")

---

## 2. Color Palette

### 2.1 Primary Colors

**Brand Primary** (Main CTA, key actions):
```swift
// Light mode
static let brandPrimary = Color(hex: "#007AFF")  // iOS Blue

// Dark mode
static let brandPrimaryDark = Color(hex: "#0A84FF")  // Lighter blue
```

**Brand Secondary** (Accents, highlights):
```swift
// Light mode
static let brandSecondary = Color(hex: "#5856D6")  // Purple

// Dark mode
static let brandSecondaryDark = Color(hex: "#5E5CE6")
```

**Brand Accent** (Destructive actions, warnings):
```swift
// Light mode
static let brandAccent = Color(hex: "#FF3B30")  // Red

// Dark mode
static let brandAccentDark = Color(hex: "#FF453A")
```

### 2.2 Semantic Colors

**Success** (Confirmation, completion):
```swift
static let success = Color(hex: "#34C759")  // Green
```

**Warning** (Caution, attention needed):
```swift
static let warning = Color(hex: "#FF9500")  // Orange
```

**Error** (Errors, destructive actions):
```swift
static let error = Color(hex: "#FF3B30")  // Red (same as accent)
```

**Info** (Tips, information):
```swift
static let info = Color(hex: "#007AFF")  // Blue (same as primary)
```

### 2.3 Neutral Colors

**Backgrounds**:
```swift
// Light mode
static let background = Color.white
static let secondaryBackground = Color(hex: "#F2F2F7")  // iOS gray
static let tertiaryBackground = Color(hex: "#FFFFFF")

// Dark mode
static let backgroundDark = Color(hex: "#000000")
static let secondaryBackgroundDark = Color(hex: "#1C1C1E")
static let tertiaryBackgroundDark = Color(hex: "#2C2C2E")
```

**Text**:
```swift
// Light mode
static let textPrimary = Color(hex: "#000000")
static let textSecondary = Color(hex: "#3C3C43", opacity: 0.6)  // iOS secondary label
static let textTertiary = Color(hex: "#3C3C43", opacity: 0.3)

// Dark mode
static let textPrimaryDark = Color(hex: "#FFFFFF")
static let textSecondaryDark = Color(hex: "#EBEBF5", opacity: 0.6)
static let textTertiaryDark = Color(hex: "#EBEBF5", opacity: 0.3)
```

**Borders & Dividers**:
```swift
static let separator = Color(hex: "#3C3C43", opacity: 0.36)
static let border = Color(hex: "#C7C7CC")
```

### 2.4 Usage Guidelines

**Primary Color**:
- Primary CTAs (Save, Submit, Continue)
- Active tab bar items
- Selected state
- Links

**Secondary Color**:
- Secondary actions
- Highlights
- Badges (non-critical)

**Accent Color**:
- Delete buttons
- Error states
- Critical alerts

**Backgrounds**:
- background: Screen background
- secondaryBackground: Card backgrounds, input fields
- tertiaryBackground: Nested cards, elevated surfaces

---

## 3. Typography

### 3.1 Type Scale

**iOS Dynamic Type** (Automatically scales with user preference):

```swift
// Display
.largeTitle     // 34pt, Bold    - Screen titles
.title          // 28pt, Bold    - Major sections
.title2         // 22pt, Bold    - Subsections, cards
.title3         // 20pt, Semibold - Groups

// Body
.headline       // 17pt, Semibold - Emphasized text, button labels
.body           // 17pt, Regular  - Default body text
.callout        // 16pt, Regular  - Secondary content

// Supporting
.subheadline    // 15pt, Regular  - Subtitles, labels
.footnote       // 13pt, Regular  - Timestamps, metadata
.caption        // 12pt, Regular  - Section headers (uppercase)
.caption2       // 11pt, Regular  - Fine print
```

### 3.2 Font Family

**Default**: System Font (SF Pro)
- No custom fonts needed (SF Pro is optimized for iOS)
- If custom font required: Choose legible, web-safe fallback

### 3.3 Font Weights

```swift
.ultraLight     // Avoid, too thin
.thin           // Avoid
.light          // Occasional use
.regular        // Default for body text
.medium         // Occasional emphasis
.semibold       // Headings, emphasized text
.bold           // Titles, important actions
.heavy          // Avoid, too thick
.black          // Avoid
```

### 3.4 Line Height & Spacing

**Default**: SwiftUI handles automatically
**Custom** (if needed):
```swift
.lineSpacing(4)  // Add 4pt between lines (for dense text)
```

**Paragraph Spacing**: 12pt between paragraphs

### 3.5 Usage Guidelines

| Element | Style | Use Case |
|---------|-------|----------|
| Screen Title | .largeTitle | Home, Settings navigation bar |
| Section Header | .title2 | "Recent Items", "Profile" |
| Card Title | .headline | Item name in list |
| Body Text | .body | Descriptions, paragraphs |
| Metadata | .footnote | Timestamps, "Created 2h ago" |
| Button Label | .headline | All buttons |
| Input Label | .caption | Above text fields |
| Placeholder | .body + opacity 0.5 | Text field placeholder |

---

## 4. Spacing System

### 4.1 Spacing Scale

**Base Unit**: 4pt

```swift
enum Spacing {
    static let xxs: CGFloat = 2   // Tight spacing (icon to text)
    static let xs: CGFloat = 4    // Very small (between related elements)
    static let s: CGFloat = 8     // Small (list item internal padding)
    static let m: CGFloat = 12    // Medium (between components)
    static let l: CGFloat = 16    // Large (card padding, margins) ⭐ Default
    static let xl: CGFloat = 24   // Extra large (section spacing)
    static let xxl: CGFloat = 32  // Screen margins, major sections
    static let xxxl: CGFloat = 48 // Between major screen areas
}
```

### 4.2 Usage Guidelines

**Padding** (Inside components):
- Cards: 16pt all sides
- Buttons: 16pt horizontal, 12pt vertical
- Text fields: 16pt horizontal, 12pt vertical
- List rows: 16pt horizontal, 8pt vertical

**Margins** (Between components):
- List items: 8pt vertical
- Sections: 24pt vertical
- Screen edges: 16pt horizontal

**Stack Spacing**:
```swift
VStack(spacing: 12) { ... }  // Default
HStack(spacing: 8) { ... }   // Tight
VStack(spacing: 24) { ... }  /

…(truncated)
