Skip to main content

iOS Component Library: AI-Powered Photo Journaling App

Date: 2025-11-10 Version: 1.0 Author: UX Designer Status: Approved for UI Design Platform: iOS 15+ (Native Swift/SwiftUI)

Overview

This design system defines all reusable UI components for the AI-powered photo journaling iOS app. Each component includes specifications for all states, variants, anatomy, spacing, typography, colors, and accessibility requirements. Component Organization:
  1. Navigation Components - Tab bar, navigation bar, search bar
  2. Input Components - Text fields, photo picker, camera, emotion selector
  3. Action Components - Buttons, FAB, action sheets
  4. Content Components - Photo cards, entry cards, loading/error/empty states
  5. Feedback Components - Toasts, alerts, progress indicators
  6. Data Display - Timeline grid, tags, labels, metadata
  7. Onboarding Components - Welcome screens, permission requests
  8. Premium Components - Paywall, subscription UI

1. Navigation Components

1.1 Tab Bar (Bottom Navigation)

Purpose: Primary navigation between main app sections Variants:
  • Standard (5 tabs max, iOS convention)
Anatomy:
┌──────────────────────────────────────────┐
│  [Home]  [Search]  [+]  [Profile]        │ ← Tab Bar (49pt height)
└──────────────────────────────────────────┘
Tabs:
  1. Timeline (Home)
    • Icon: house.fill
    • Label: “Timeline”
  2. Search
    • Icon: magnifyingglass
    • Label: “Search”
  3. Create Entry (Center, emphasized)
    • Icon: plus.circle.fill (larger, 32pt)
    • Label: None (icon-only)
    • Color: Primary Coral
  4. Profile
    • Icon: person.circle.fill
    • Label: “Profile”
Spacing:
  • Height: 49pt (iOS standard)
  • Safe Area Inset: Respects home indicator
  • Icon size: 24x24pt (standard), 32x32pt (center)
  • Padding: 8pt top, 4pt bottom
Typography:
  • Font: Caption 2 (11pt regular)
  • Color: Secondary Gray (unselected), Primary Coral (selected)
Colors:
  • Background: Off-White (Light), Elevated Surface (Dark)
  • Divider: 0.5pt Light Gray (top border)
  • Selected: Primary Coral
  • Unselected: Secondary Gray
States:
  • Default: Gray icon + label
  • Selected: Coral icon + label, bold font
  • Pressed: Scale 0.95 (0.1s animation)
Accessibility:
  • ARIA role: tab, tablist
  • VoiceOver: “Timeline, tab, 1 of 4, selected”
  • Keyboard: Tab navigation, Enter to select
  • Minimum touch target: 44x44pt per tab
Usage Guidelines:
  • Always visible (sticky bottom navigation)
  • Maximum 5 tabs (iOS convention)
  • Center tab for primary action (Create Entry)
  • Use icons + labels for clarity

1.2 Navigation Bar (Top Bar)

Purpose: Page titles, back navigation, contextual actions Variants:
  • Standard: Title only
  • Large Title: Scrollable large title (iOS 11+)
  • With Actions: Title + trailing buttons
Anatomy (Standard):
┌──────────────────────────────────────────┐
│  ← Back    Timeline          [Search]    │ ← 44pt height
└──────────────────────────────────────────┘
Anatomy (Large Title):
┌──────────────────────────────────────────┐
│  Timeline                      [Search]   │ ← 96pt height (expanded)
│                                           │
│  (Collapses to 44pt on scroll)           │
└──────────────────────────────────────────┘
Elements:
  1. Back Button (leading):
    • Icon: chevron.left
    • Text: Previous screen title (truncated)
    • Color: Primary Coral
  2. Title (center):
    • Font: Headline (17pt semibold) or Large Title (34pt bold)
    • Color: Charcoal (Light), Off-White (Dark)
  3. Actions (trailing):
    • Icons: 24x24pt (search, filter, more)
    • Max 2-3 icons
Spacing:
  • Height: 44pt (standard), 96pt (large title expanded)
  • Horizontal padding: 16pt
  • Safe Area Inset: Respects status bar
Colors:
  • Background: Transparent (scrolls with content)
  • Blur: iOS native blur effect (when scrolling)
States:
  • Expanded: Large title visible
  • Collapsed: Standard title visible (scroll-triggered)
Accessibility:
  • VoiceOver: “Back to [Previous Screen]”, “Timeline, heading”
  • Keyboard: Tab to navigate actions

Purpose: Keyword search for journal entries Anatomy:
┌──────────────────────────────────────────┐
│  🔍  Search your memories...      [×]    │ ← 44pt height
└──────────────────────────────────────────┘
Elements:
  • Search Icon: magnifyingglass (leading, 20x20pt)
  • Text Field: “Search your memories…”
  • Clear Button: xmark.circle.fill (trailing, appears when typing)
Spacing:
  • Height: 44pt
  • Padding: 12pt horizontal, 8pt vertical
  • Border Radius: 12pt
Typography:
  • Font: Body (17pt regular)
  • Placeholder: Secondary Gray
  • Input Text: Charcoal (Light), Off-White (Dark)
Colors:
  • Background: Off-White (Light), Elevated Surface (Dark)
  • Border: None (uses background color)
  • Focus: 2pt Primary Coral border
States:
  • Default: Placeholder visible
  • Active: Keyboard open, cursor blinking
  • Typing: Clear button visible
  • Results: Autocomplete suggestions (future)
Accessibility:
  • VoiceOver: “Search your memories, search field”
  • Keyboard: Auto-focus when tapped
  • Clear button: “Clear search text”
Usage Guidelines:
  • Debounce search: 300ms delay after typing stops
  • Show results in real-time
  • Highlight matching keywords in results

2. Input Components

2.1 Text Field (Journal Entry)

Purpose: Multi-line text entry for journal content Anatomy:
┌──────────────────────────────────────────┐
│  What do you want to remember about      │
│  this moment?                             │
│                                           │
│  [User types here...]                    │
│                                           │
│                                           │
│                              450 / 500 ◄─ Character count
└──────────────────────────────────────────┘
Spacing:
  • Min Height: 120pt (3 lines of text)
  • Max Height: Unlimited (scrollable)
  • Padding: 16pt horizontal, 12pt vertical
  • Border Radius: 12pt
Typography:
  • Font: Body (17pt regular)
  • Line Height: 22pt
  • Placeholder: Secondary Gray
  • Input Text: Charcoal (Light), Off-White (Dark)
Colors:
  • Background: Off-White (Light), Elevated Surface (Dark)
  • Border: 1pt Light Gray
  • Focus: 2pt Primary Coral border
  • Error: 2pt Error Red border
States:
  • Default: Placeholder visible
  • Focus: Keyboard open, cursor blinking
  • Typing: Character count visible at 450+ chars (free tier)
  • Error: Red border + error message below
  • Disabled: 40% opacity, no interaction
Character Limits:
  • Free Tier: 500 characters per entry
  • Premium: Unlimited
  • Show count at: 450 characters (90% of limit)
Accessibility:
  • VoiceOver: “Journal entry, text area”
  • Keyboard: Auto-capitalization, spell check enabled
  • Dynamic Type: Respects user font size settings
Usage Guidelines:
  • Auto-save draft every 10 seconds
  • Preserve text on app backgrounding
  • Show character count at 90% of limit
  • Allow line breaks (Enter key)

2.2 Camera Capture

Purpose: In-app photo capture for journal entries Anatomy (Camera View):
┌──────────────────────────────────────────┐
│                                     [×]   │ ← Close button
│                                           │
│                                           │
│          [Live Camera Feed]               │
│                                           │
│                                           │
│                                           │
│  [Flash] [Flip]     ⚪      [Gallery]    │ ← Controls
└──────────────────────────────────────────┘
Elements:
  1. Camera Preview: Full-screen live feed
  2. Close Button: xmark (top-left)
  3. Flash Control: bolt.fill (bottom-left)
  4. Flip Camera: arrow.triangle.2.circlepath (bottom-left)
  5. Capture Button: Large circle (center-bottom, 70x70pt)
  6. Gallery Button: photo.on.rectangle (bottom-right)
Spacing:
  • Full-screen: Safe Area respected
  • Capture Button: 70x70pt, 16pt from bottom
  • Control Icons: 44x44pt touch targets
Colors:
  • Background: Black (camera feed)
  • Capture Button: White with Primary Coral ring
  • Control Icons: White with 50% black background blur
States:
  • Default: Camera active, controls visible
  • Capturing: Capture button animates (scale + flash)
  • Review: Photo captured, “Use Photo” or “Retake” buttons
Animations:
  • Capture: White flash (0.1s), scale capture button (0.2s)
  • Flip Camera: Rotate animation (0.3s)
Accessibility:
  • VoiceOver: “Capture photo, button”
  • Alternative: “Choose from Library” for users who can’t use camera
  • Permission: Request camera access with clear explanation
Usage Guidelines:
  • Request permissions on first use
  • Show permission denied state with “Open Settings” button
  • Support front and rear cameras
  • Basic flash control (auto, on, off)

2.3 Photo Picker (Library)

Purpose: Select existing photos from device library Anatomy:
┌──────────────────────────────────────────┐
│  Photos                            Cancel │ ← Navigation bar
├──────────────────────────────────────────┤
│  ┌────┐ ┌────┐ ┌────┐ ┌────┐           │
│  │    │ │    │ │    │ │    │           │ ← Photo grid
│  └────┘ └────┘ └────┘ └────┘           │
│  ┌────┐ ┌────┐ ┌────┐ ┌────┐           │
│  │    │ │    │ │    │ │    │           │
│  └────┘ └────┘ └────┘ └────┘           │
└──────────────────────────────────────────┘
Implementation:
  • Use PHPickerViewController (iOS 14+)
  • Single photo selection (MVP)
  • Support: JPEG, PNG, HEIC (max 25MB)
Elements:
  • Navigation Bar: “Photos” title, “Cancel” button
  • Photo Grid: 4 columns, 2pt gutters
  • Selection: Checkmark overlay (Primary Coral)
Spacing:
  • Grid: 4 columns, 2pt gutters, 16pt margins
  • Thumbnail: Square aspect ratio
Colors:
  • Background: Off-White (Light), Elevated Surface (Dark)
  • Selection: Primary Coral checkmark
States:
  • Default: Grid of photos
  • Selected: Checkmark overlay + coral border
  • Loading: Spinner while importing
Accessibility:
  • VoiceOver: “Photo, [Date Taken], double-tap to select”
  • Permission: Request photo library access
Usage Guidelines:
  • Request permissions on first use
  • Show permission denied state with “Open Settings” button
  • Import full-resolution photo (compress later)

2.4 Emotion Selector

Purpose: Multi-select emotion tags for journal entries Anatomy:
┌──────────────────────────────────────────┐
│  How did you feel?                 Done  │ ← Title + Done button
├──────────────────────────────────────────┤
│  Positive Emotions                       │ ← Category header
│  ┌────────┐ ┌────────┐ ┌────────┐      │
│  │ 😊 Happy│ │❤️ Grate│ │🎉 Excit│      │ ← Emotion chips
│  └────────┘ └────────┘ └────────┘      │
│  ┌────────┐                             │
│  │😌 Peace│                             │
│  └────────┘                             │
│                                          │
│  Reflective Emotions                    │
│  ┌────────┐ ┌────────┐ ┌────────┐      │
│  │🤔 Think│ │😢 Nosta│ │😊 Proud│      │
│  └────────┘ └────────┘ └────────┘      │
│  ┌────────┐                             │
│  │😍 Lovin│                             │
│  └────────┘                             │
│                                          │
│  Challenging Emotions                   │
│  ┌────────┐ ┌────────┐ ┌────────┐      │
│  │😔 Sad  │ │😰 Anxio│ │😤 Frust│      │
│  └────────┘ └────────┘ └────────┘      │
│  ┌────────┐                             │
│  │😌 Hopef│                             │
│  └────────┘                             │
└──────────────────────────────────────────┘
12-Emotion Taxonomy: Positive Emotions (4):
  • 😊 Happy (Warm Coral #FF6B6B)
  • ❤️ Grateful (Soft Pink #FF8FA3)
  • 🎉 Excited (Bright Yellow #FDCB6E)
  • 😌 Peaceful (Light Teal #81ECEC)
Reflective Emotions (4):
  • 🤔 Thoughtful (Cool Blue #74B9FF)
  • 😢 Nostalgic (Muted Purple #A29BFE)
  • 😊 Proud (Golden Orange #FAB1A0)
  • 😍 Loving (Rose Pink #FD79A8)
Challenging Emotions (4):
  • 😔 Sad (Muted Blue #6C5CE7)
  • 😰 Anxious (Gray-Blue #636E72)
  • 😤 Frustrated (Muted Red #E17055)
  • 😌 Hopeful (Soft Teal #55EFC4)
Emotion Chip Specifications: Anatomy:
┌────────────────┐
│ 😊 Happy   ✓  │ ← Icon + Label + Checkmark (if selected)
└────────────────┘
Spacing:
  • Height: 44pt
  • Padding: 12pt horizontal, 8pt vertical
  • Icon: 24x24pt
  • Gap: 8pt between icon and label
  • Border Radius: 22pt (pill shape)
Typography:
  • Font: Callout (16pt regular)
  • Label: Emotion name
Colors (Unselected):
  • Background: Emotion color at 15% opacity
  • Text: Emotion color at 100%
  • Border: None
  • Icon: Emotion color
Colors (Selected):
  • Background: Emotion color at 100%
  • Text: White
  • Border: None
  • Icon: White
  • Checkmark: White, 20x20pt
States:
  • Unselected: Light background, colored text
  • Selected: Full color background, white text + checkmark
  • Hover: Background opacity 25% (iPad, future)
  • Pressed: Scale 0.98 (0.1s animation)
Accessibility:
  • VoiceOver: “Happy, positive emotion, selected, button”
  • Keyboard: Tab to navigate, Space to toggle
  • Minimum touch target: 44x44pt
Usage Guidelines:
  • No limit on selections (encourage 1-3)
  • Show hint if >5 selected: “Focus on your strongest feelings”
  • Group by category for easier scanning
  • Display in same order across app

3. Action Components

3.1 Primary Button

Purpose: Main call-to-action buttons Anatomy:
┌────────────────────┐
│   Save Entry       │ ← Text centered
└────────────────────┘
Spacing:
  • Height: 50pt
  • Padding: 16pt horizontal
  • Border Radius: 12pt
  • Min Width: 120pt
Typography:
  • Font: Headline (17pt semibold)
  • Color: White
Colors:
  • Background: Primary Coral (#FF6B6B)
  • Shadow: Level 1 (subtle)
States:
  • Default: Full coral background
  • Hover: 10% darker coral (iPad)
  • Pressed: 20% darker coral, scale 0.98
  • Disabled: 40% opacity, no interaction
  • Loading: Spinner replaces text
Accessibility:
  • VoiceOver: “[Action], button”
  • Minimum touch target: 44x44pt (height)
  • Dynamic Type: Text size adjusts
Usage Guidelines:
  • Maximum 1 primary button per screen
  • Use for main actions: Save, Continue, Start, Subscribe
  • Place at bottom of forms or modals
  • Full-width on mobile, fixed width on iPad

3.2 Secondary Button

Purpose: Alternative actions, less emphasis than primary Anatomy:
┌────────────────────┐
│   Cancel           │ ← Text centered
└────────────────────┘
Spacing:
  • Height: 50pt
  • Padding: 16pt horizontal
  • Border Radius: 12pt
  • Border: 1pt solid Light Gray
Typography:
  • Font: Headline (17pt semibold)
  • Color: Charcoal (Light), Off-White (Dark)
Colors:
  • Background: Off-White (Light), Elevated Surface (Dark)
  • Border: 1pt Light Gray
States:
  • Default: Light background, border
  • Hover: Background 5% darker
  • Pressed: Background 10% darker, scale 0.98
  • Disabled: 40% opacity
Usage Guidelines:
  • Use for secondary actions: Cancel, Skip, Later
  • Pair with primary button (left/right or top/bottom)
  • Never use two primary buttons

Purpose: Tertiary actions, navigation links Anatomy:
Forgot password?  ← Text only, no border/background
Spacing:
  • Height: 44pt (touch target)
  • Padding: 8pt horizontal
Typography:
  • Font: Headline (17pt semibold)
  • Color: Primary Coral
Colors:
  • Background: None
  • Underline: None (iOS convention)
States:
  • Default: Coral text
  • Hover: 10% darker coral
  • Pressed: 20% darker coral, 0.8 opacity
  • Disabled: 40% opacity
Usage Guidelines:
  • Use for low-priority actions: Forgot password, Learn more, Skip
  • Always use semantic link color (coral)
  • Minimum touch target: 44x44pt

3.4 Floating Action Button (FAB)

Purpose: Quick access to create new journal entry Anatomy:
    ┌─────┐
    │  +  │ ← Plus icon
    └─────┘
Spacing:
  • Size: 56x56pt circle
  • Icon: 32x32pt plus icon
  • Position: Bottom-right corner, 16pt from edges
  • Safe Area: Above tab bar (if visible)
Typography:
  • N/A (icon-only)
Colors:
  • Background: Primary Coral
  • Icon: White
  • Shadow: Level 3 (floating, prominent)
States:
  • Default: Full coral circle
  • Hover: 10% darker coral
  • Pressed: 20% darker coral, scale 0.9
  • Hidden: Scroll down (hide), scroll up (show)
Animations:
  • Scroll hide: Slide down + fade out (0.3s)
  • Scroll show: Slide up + fade in (0.3s)
  • Press: Scale 0.9 (0.1s)
Accessibility:
  • VoiceOver: “Create new entry, button”
  • Keyboard: Tab accessible
  • Touch target: Full 56x56pt
Usage Guidelines:
  • Always visible on Timeline screen
  • Hide on scroll down (reduce clutter)
  • Show on scroll up (quick access)
  • Tapping opens camera or photo picker

3.5 Icon Button

Purpose: Small action buttons with icons Anatomy:
 [🔍]  ← Icon only, square or circular
Spacing:
  • Size: 44x44pt (minimum touch target)
  • Icon: 24x24pt
  • Padding: 10pt (makes 44x44pt total)
Colors:
  • Icon: Charcoal (Light), Off-White (Dark)
  • Background: None (transparent)
States:
  • Default: Icon visible
  • Hover: 20% gray background circle
  • Pressed: 30% gray background, scale 0.95
  • Disabled: 40% opacity
Usage Guidelines:
  • Use in navigation bars (search, filter, more)
  • Always pair with accessibility label
  • Never use ambiguous icons

4. Content Components

4.1 Photo Card (Timeline Grid)

Purpose: Display journal entry in timeline grid Anatomy:
┌────────────────────┐
│                    │
│      [Photo]       │ ← Photo (aspect ratio preserved)
│                    │
├────────────────────┤
│ Nov 10          😊❤️│ ← Date + Emotions (max 3 visible)
│ What a beautiful...│ ← Text preview (1 line, truncated)
└────────────────────┘
Spacing:
  • Photo: Full-width, aspect ratio preserved
  • Padding: 12pt internal padding (bottom section)
  • Border Radius: 12pt
  • Gutter: 8pt between cards
Typography:
  • Date: Footnote (13pt regular), Secondary Gray
  • Text Preview: Callout (16pt regular), Charcoal
Colors:
  • Background: White (Light), Elevated Surface (Dark)
  • Shadow: Level 1 (subtle)
  • Border: None
Elements:
  1. Photo: Lazy-loaded thumbnail (400x400pt)
  2. Date Badge: “Nov 10” (top-left overlay on photo)
  3. Emotion Icons: Max 3 visible, ”+” if more (top-right)
  4. Text Preview: First 50 characters of journal text
States:
  • Default: Shadow Level 1
  • Hover: Shadow Level 2 (iPad)
  • Pressed: Scale 0.98, opacity 0.95
  • Loading: Skeleton screen (gray rectangle with shimmer)
Accessibility:
  • VoiceOver: “Entry from November 10, Happy, Grateful, What a beautiful day…”
  • Touch target: Entire card (not just photo)
  • Alt text: Photo description (if AI-generated)
Usage Guidelines:
  • Grid: 2 columns (portrait), 3 columns (landscape)
  • Masonry layout: Variable heights based on content
  • Lazy load: Photos load on scroll
  • Tap: Navigate to entry detail view

4.2 Entry Detail View

Purpose: Full view of a single journal entry Anatomy:
┌──────────────────────────────────────────┐
│  ←                                  [⋮]  │ ← Navigation + Menu
├──────────────────────────────────────────┤
│                                           │
│                                           │
│          [Full-Size Photo]                │ ← Photo (tappable for full-screen)
│                                           │
│                                           │
├──────────────────────────────────────────┤
│  November 10, 2025 • 2:30 PM             │ ← Date + Time
│  📍 San Francisco, CA                    │ ← Location (if available)
│                                           │
│  😊 Happy  ❤️ Grateful  🎉 Excited       │ ← Emotion tags
│                                           │
│  What a beautiful day! The weather was   │ ← Journal text
│  perfect and I spent time with family.   │
│  These moments are what I want to        │
│  remember forever.                       │
└──────────────────────────────────────────┘
Spacing:
  • Photo: Full-width, aspect ratio preserved
  • Content Padding: 16pt horizontal
  • Section Spacing: 16pt between sections
Typography:
  • Date/Time: Callout (16pt regular), Secondary Gray
  • Location: Callout (16pt regular), Secondary Gray
  • Journal Text: Body (17pt regular), Charcoal
Elements:
  1. Navigation Bar: Back button + Menu (edit/delete)
  2. Photo: Full-width, tappable for full-screen
  3. Metadata: Date, time, location
  4. Emotion Tags: All selected emotions as chips
  5. Journal Text: Full text, scrollable
States:
  • Default: All content visible
  • Photo Loading: Skeleton screen
  • Photo Error: Error state with retry button
  • Full-Screen Photo: Black background, pinch-to-zoom
Accessibility:
  • VoiceOver: Read all content in order
  • Photo: “Photo from November 10, double-tap to view full screen”
  • Dynamic Type: Text size adjusts
Usage Guidelines:
  • Always show full journal text (no truncation)
  • Emotion tags: Show all (no ”+” indicator)
  • Metadata: Gray, subtle (not main focus)
  • Edit/Delete: Menu button (⋮) in navigation bar

4.3 AI Prompt Card

Purpose: Display AI-generated journal prompts Anatomy:
┌────────────────────────────────────────┐
│  What made this moment special?        │ ← Prompt text
└────────────────────────────────────────┘
Spacing:
  • Height: Variable (2-3 lines of text)
  • Padding: 16pt horizontal, 12pt vertical
  • Border Radius: 12pt
  • Gap: 12pt between prompt cards
Typography:
  • Font: Body (17pt regular)
  • Color: Charcoal (Light), Off-White (Dark)
Colors:
  • Background: Off-White (Light), Elevated Surface (Dark)
  • Border: 1pt Light Gray
  • Selected: 2pt Primary Coral border
States:
  • Default: Light background, border
  • Selected: Coral border, coral text
  • Pressed: Scale 0.98
  • Loading: Skeleton with shimmer animation
Accessibility:
  • VoiceOver: “[Prompt text], button, tap to use this prompt”
  • Touch target: Entire card
Usage Guidelines:
  • Show 3 prompts at a time
  • “Refresh prompts” button for new suggestions
  • Tapping inserts prompt into text field
  • Loading state: “Thinking about your photo…“

4.4 Loading State (Skeleton Screen)

Purpose: Show content structure while loading Anatomy (Timeline Grid):
┌────────┐ ┌────────┐
│░░░░░░░░│ │░░░░░░░░│ ← Gray rectangles
│░░░░░░░░│ │░░░░░░░░│
│░░░░░░░░│ │░░░░░░░░│
└────────┘ └────────┘
┌────────┐ ┌────────┐
│░░░░░░░░│ │░░░░░░░░│
│░░░░░░░░│ │░░░░░░░░│
└────────┘ └────────┘
Spacing:
  • Match actual content dimensions
  • Same grid layout as loaded content
Colors:
  • Background: Light Gray (#E0E0E0)
  • Shimmer: White gradient (left to right)
Animation:
  • Shimmer: 1.5s loop, left to right gradient
  • Smooth, continuous (no flicker)
Usage Guidelines:
  • Show immediately on load (no blank screen)
  • Preserve layout structure
  • Replace with real content when loaded

4.5 Empty State

Purpose: Guide users when no content exists Anatomy (Timeline Empty):
┌──────────────────────────────────────────┐
│                                           │
│                                           │
│         [Illustration: Camera + Journal]  │ ← Friendly illustration
│                                           │
│         Your story starts here            │ ← Headline
│                                           │
│     Capture a moment and let AI help     │ ← Body text
│     you remember it forever.              │
│                                           │
│     ┌──────────────────────────────┐     │
│     │  + Create Your First Memory  │     │ ← CTA button
│     └──────────────────────────────┘     │
│                                           │
└──────────────────────────────────────────┘
Spacing:
  • Center-aligned vertically and horizontally
  • Illustration: 200x200pt
  • Spacing: 24pt between elements
Typography:
  • Headline: Title 2 (22pt bold), Charcoal
  • Body: Body (17pt regular), Secondary Gray
Colors:
  • Illustration: Coral + Teal accents
  • CTA: Primary button styling
Variants:
  1. Timeline Empty: “Your story starts here”
  2. Search Empty: “No entries found”
  3. AI Loading: “Thinking about your photo…”
  4. Error State: “Something went wrong”
Usage Guidelines:
  • Always show empty state (never blank screen)
  • Provide clear next action
  • Use friendly, encouraging tone
  • Include illustration or icon

4.6 Error State

Purpose: Communicate errors clearly and provide solutions Anatomy:
┌──────────────────────────────────────────┐
│           ⚠️                              │ ← Icon (48x48pt)
│                                           │
│      Something went wrong                 │ ← Headline
│                                           │
│  We couldn't upload your photo.           │ ← Error message
│  Please check your connection and         │
│  try again.                               │
│                                           │
│     ┌──────────────────────────────┐     │
│     │       Try Again              │     │ ← CTA button
│     └──────────────────────────────┘     │
│                                           │
└──────────────────────────────────────────┘
Spacing:
  • Center-aligned
  • Icon: 48x48pt
  • Spacing: 16pt between elements
Typography:
  • Headline: Title 3 (20pt semibold), Charcoal
  • Error Message: Body (17pt regular), Secondary Gray
Colors:
  • Icon: Warning Amber or Error Red (based on severity)
  • CTA: Primary button styling
Error Types:
  1. Network Error: “Check your connection and try again”
  2. AI Failure: “AI couldn’t generate prompts. Try manual entry.”
  3. Upload Failure: “Photo upload failed. Try again.”
  4. Permission Denied: “Camera access required. Open Settings.”
Usage Guidelines:
  • Clear, non-technical language
  • Actionable (what can user do?)
  • Friendly tone, not blaming
  • Always provide “Try Again” or alternative action

5. Feedback Components

5.1 Toast Notification

Purpose: Brief, non-blocking feedback messages Anatomy:
┌────────────────────────────────┐
│ ✓  Entry saved successfully    │ ← Icon + Message
└────────────────────────────────┘
Spacing:
  • Height: 44pt
  • Padding: 16pt horizontal, 12pt vertical
  • Border Radius: 12pt
  • Position: Top center, 16pt from top (Safe Area)
Typography:
  • Font: Callout (16pt regular)
  • Color: White
Colors:
  • Background: Success Green (#00B894) or Error Red (#D63031)
  • Shadow: Level 2
States:
  • Appear: Slide down + fade in (0.3s)
  • Visible: 3 seconds
  • Dismiss: Slide up + fade out (0.3s)
Variants:
  1. Success: Green background, checkmark icon
  2. Error: Red background, xmark icon
  3. Info: Primary Coral, info icon
Accessibility:
  • VoiceOver: Announce immediately
  • Reduce Motion: Fade in/out instead of slide
Usage Guidelines:
  • Auto-dismiss after 3 seconds
  • User can swipe up to dismiss early
  • Maximum 1 toast at a time
  • Use for confirmations, not errors (use error state for errors)

5.2 Alert Dialog

Purpose: Critical decisions or confirmations Anatomy:
┌──────────────────────────────────┐
│  Delete Entry?                   │ ← Title
│                                  │
│  This action cannot be undone.   │ ← Message
│  Are you sure?                   │
│                                  │
│  ┌────────────┐ ┌────────────┐  │
│  │   Cancel   │ │   Delete   │  │ ← Actions
│  └────────────┘ └────────────┘  │
└──────────────────────────────────┘
Spacing:
  • Width: 270pt (iOS standard)
  • Padding: 16pt
  • Border Radius: 14pt
Typography:
  • Title: Headline (17pt semibold), Charcoal
  • Message: Callout (16pt regular), Secondary Gray
  • Actions: Headline (17pt semibold)
Colors:
  • Background: White (Light), Elevated Surface (Dark)
  • Overlay: 40% black dim
  • Destructive Action: Error Red text
Variants:
  1. Confirmation: “Delete Entry?” (destructive)
  2. Information: “Permission Required”
  3. Warning: “Unsaved Changes”
Accessibility:
  • VoiceOver: Read title, message, actions
  • Keyboard: Tab between actions, Enter to confirm
  • Reduce Motion: Fade in instead of scale
Usage Guidelines:
  • Use sparingly (only for critical decisions)
  • Title: Short, clear question
  • Message: Explain consequence
  • Destructive action: Red text, right side (iOS convention)

5.3 Progress Indicator

Purpose: Show progress for long operations Variants:
  1. Linear Progress Bar (Photo Upload)
  2. Circular Spinner (AI Processing)
Linear Progress Bar:
┌──────────────────────────────────┐
│ Uploading...                 45% │ ← Label + Percentage
│ ████████████░░░░░░░░░░░░░░░░░░░ │ ← Progress bar
└──────────────────────────────────┘
Spacing:
  • Height: 4pt (bar), 44pt (total with label)
  • Width: Full-width or fixed
  • Border Radius: 2pt
Colors:
  • Background: Light Gray
  • Fill: Primary Coral
  • Label: Secondary Gray
Circular Spinner:
    ⟲  ← Rotating spinner
Spacing:
  • Size: 32x32pt (medium), 48x48pt (large)
Colors:
  • Spinner: Primary Coral or Secondary Gray
Animation:
  • Linear: Fill from 0% to 100%
  • Circular: Rotate 360° continuously (1s loop)
Usage Guidelines:
  • Linear: Use for deterministic progress (photo upload)
  • Circular: Use for indeterminate progress (AI processing)
  • Always show estimated time if possible

6. Data Display Components

6.1 Emotion Tag (Chip)

Purpose: Display selected emotion on entry Anatomy:
┌──────────────┐
│ 😊 Happy     │ ← Icon + Label
└──────────────┘
Spacing:
  • Height: 32pt
  • Padding: 8pt horizontal
  • Icon: 20x20pt
  • Gap: 6pt between icon and label
  • Border Radius: 16pt (pill shape)
Typography:
  • Font: Callout (16pt regular)
  • Color: Emotion color (unselected), White (selected)
Colors (Unselected - Display Mode):
  • Background: Emotion color at 20% opacity
  • Text: Emotion color at 100%
  • Icon: Emotion color
Colors (Selected - Selection Mode):
  • Background: Emotion color at 100%
  • Text: White
  • Icon: White
Usage Guidelines:
  • Display mode: Show all emotions on entry (20% opacity)
  • Selection mode: Show selected emotions (100% opacity)
  • Always show icon + label (not icon-only)
  • Wrap to multiple lines if needed

6.2 Metadata Label

Purpose: Display entry metadata (date, time, location) Anatomy:
November 10, 2025 • 2:30 PM • 📍 San Francisco, CA
Spacing:
  • Height: 20pt (single line)
  • Gap: 8pt between elements
  • Icon: 16x16pt
Typography:
  • Font: Callout (16pt regular)
  • Color: Secondary Gray
Elements:
  • Date: “November 10, 2025”
  • Time: “2:30 PM” (12-hour format)
  • Location: ”📍 San Francisco, CA” (if available)
  • Separator: ” • ” (bullet point)
Usage Guidelines:
  • Always show date and time
  • Show location only if user granted permission
  • Use relative dates for recent entries: “Today”, “Yesterday”, “3 days ago”

6.3 Timeline Grid

Purpose: Masonry grid layout for photo timeline Anatomy:
┌────────┐ ┌────────┐
│        │ │        │
│ Card 1 │ │ Card 2 │ ← Variable heights
│        │ │        │
│        │ └────────┘
└────────┘ ┌────────┐
┌────────┐ │        │
│        │ │ Card 4 │
│ Card 3 │ │        │
└────────┘ └────────┘
Spacing:
  • Columns: 2 (portrait), 3 (landscape)
  • Gutter: 8pt
  • Margins: 16pt horizontal
  • Row Gap: 8pt
Grid Behavior:
  • Masonry layout: Variable heights
  • Aspect ratio: Preserved from photo
  • Lazy loading: Load on scroll
  • Infinite scroll: Load more at bottom
Performance:
  • Thumbnail size: 400x400pt
  • Prefetch: 2 screens ahead
  • Cache: 200MB limit (Kingfisher)
Usage Guidelines:
  • Newest entries first (reverse chronological)
  • Show 20 entries initially
  • Load 20 more on scroll to bottom
  • Pull-to-refresh at top

7. Onboarding Components

7.1 Welcome Screen (Onboarding Step 1)

Purpose: Introduce app value proposition Anatomy:
┌──────────────────────────────────────────┐
│                                           │
│                                           │
│         [Hero Image: Photo + Journal]     │ ← Beautiful hero image
│                                           │
│                                           │
│      Your life, beautifully remembered    │ ← Headline
│                                           │
│  Capture moments, let AI help you journal,│ ← Subheadline
│  and rediscover your memories.            │
│                                           │
│     ┌──────────────────────────────┐     │
│     │      Get Started             │     │ ← Primary CTA
│     └──────────────────────────────┘     │
│                                           │
│     Already have an account? Log in       │ ← Secondary action
│                                           │
└──────────────────────────────────────────┘
Spacing:
  • Hero Image: 300x300pt
  • Vertical Spacing: 32pt between sections
  • Padding: 24pt horizontal
Typography:
  • Headline: Large Title (34pt bold), Charcoal
  • Subheadline: Body (17pt regular), Secondary Gray
Colors:
  • Hero Image: Coral + Teal gradient
  • CTA: Primary button
Usage Guidelines:
  • Show only on first app launch
  • Skip if user already logged in
  • Warm, welcoming tone
  • Focus on value, not features

7.2 How It Works (Onboarding Step 2)

Purpose: Explain core workflow in 3 steps Anatomy:
┌──────────────────────────────────────────┐
│                                           │
│  ┌─────┐                                  │
│  │  1  │  Snap a photo                    │ ← Step 1
│  └─────┘  Use your camera or library      │
│                                           │
│  ┌─────┐                                  │
│  │  2  │  AI suggests prompts             │ ← Step 2
│  └─────┘  Get thoughtful journal prompts  │
│                                           │
│  ┌─────┐                                  │
│  │  3  │  Save your memory                │ ← Step 3
│  └─────┘  Build your visual timeline      │
│                                           │
│     ┌──────────────────────────────┐     │
│     │          Next                │     │ ← CTA
│     └──────────────────────────────┘     │
│                                           │
│              ● ● ○  (Page indicators)     │ ← Progress
│                                           │
└──────────────────────────────────────────┘
Spacing:
  • Icon: 48x48pt circles
  • Gap: 32pt between steps
  • Padding: 24pt horizontal
Typography:
  • Step Title: Headline (17pt semibold), Charcoal
  • Step Description: Callout (16pt regular), Secondary Gray
Colors:
  • Step Numbers: Primary Coral background, white text
  • Icons: Coral
Usage Guidelines:
  • Show 3 steps maximum
  • Support swipe left/right navigation
  • Page indicators at bottom
  • “Skip” option in top-right

7.3 Permission Request (Onboarding Step 3)

Purpose: Request camera and notification permissions Anatomy:
┌──────────────────────────────────────────┐
│                                           │
│         We need a few permissions         │ ← Headline
│                                           │
│  📷 Camera                                │ ← Permission 1
│  To capture photos for your journal       │
│  ┌──────────────────────────────────┐    │
│  │      Allow Camera Access         │    │ ← CTA
│  └──────────────────────────────────┘    │
│                                           │
│  🔔 Notifications (Optional)              │ ← Permission 2
│  Daily reminders to journal                │
│  ┌──────────────────────────────────┐    │
│  │   Allow Notifications            │    │ ← CTA
│  └──────────────────────────────────┘    │
│                                           │
│     I'll do this later                    │ ← Skip option
│                                           │
└──────────────────────────────────────────┘
Spacing:
  • Icon: 48x48pt
  • Gap: 24pt between permissions
  • Padding: 24pt horizontal
Typography:
  • Headline: Title 2 (22pt bold), Charcoal
  • Permission Title: Headline (17pt semibold), Charcoal
  • Description: Callout (16pt regular), Secondary Gray
Colors:
  • Icons: Primary Coral
  • CTA: Primary button
Usage Guidelines:
  • Explain why each permission is needed
  • Request permissions sequentially (not all at once)
  • Provide skip option for optional permissions (notifications)
  • Handle “Don’t Allow” gracefully (show settings link later)

8. Premium Components

8.1 Paywall Screen

Purpose: Encourage free users to upgrade to Premium Anatomy:
┌──────────────────────────────────────────┐
│  ×                                        │ ← Close button
│                                           │
│      Unlock Your Full Story               │ ← Headline
│                                           │
│  ✓ Unlimited photos per month            │ ← Feature list
│  ✓ Advanced search filters               │
│  ✓ HD quality photo storage              │
│  ✓ Priority AI processing                │
│                                           │
│  ┌──────────────────────────────────┐    │
│  │  Annual  $60/year  (Save 25%)    │    │ ← Pricing option 1 (recommended)
│  └──────────────────────────────────┘    │
│  ┌──────────────────────────────────┐    │
│  │  Monthly  $8/month               │    │ ← Pricing option 2
│  └──────────────────────────────────┘    │
│                                           │
│     ┌──────────────────────────────┐     │
│     │   Start 14-Day Free Trial    │     │ ← CTA
│     └──────────────────────────────┘     │
│                                           │
│  Cancel anytime. No commitment.           │ ← Fine print
│                                           │
│         Maybe later                       │ ← Skip option
│                                           │
└──────────────────────────────────────────┘
Spacing:
  • Padding: 24pt horizontal
  • Gap: 16pt between features
  • Gap: 12pt between pricing options
Typography:
  • Headline: Title 1 (28pt bold), Charcoal
  • Features: Body (17pt regular), Charcoal
  • Pricing: Headline (17pt semibold), Charcoal
  • Fine Print: Footnote (13pt regular), Secondary Gray
Colors:
  • Checkmarks: Success Green
  • Pricing Options: Off-White background, 2pt coral border (selected)
  • CTA: Primary button
  • Badge: “Save 25%” in coral
Usage Guidelines:
  • Show when user hits free tier limit (50 photos/month)
  • Emphasize value, not limitations
  • Highlight savings on annual plan
  • Free trial: 14 days, requires payment method
  • Dismissible (not blocking)

8.2 Premium Badge

Purpose: Indicate Premium subscription status Anatomy:
┌────────────┐
│ 👑 Premium │ ← Crown icon + Label
└────────────┘
Spacing:
  • Height: 24pt
  • Padding: 6pt horizontal
  • Icon: 16x16pt
  • Gap: 4pt between icon and label
  • Border Radius: 12pt
Typography:
  • Font: Caption 1 (12pt semibold)
  • Color: Golden Orange (#FAB1A0)
Colors:
  • Background: Golden Orange at 15% opacity
  • Text: Golden Orange at 100%
  • Icon: Golden Orange
Usage Guidelines:
  • Show in profile section
  • Small, subtle (not ostentatious)
  • Gold color (premium feel)

Accessibility Summary

WCAG 2.1 AA Compliance Checklist

Color & Contrast:
  • ✅ Text contrast: 4.5:1 minimum (normal text), 3:1 (large text)
  • ✅ UI component contrast: 3:1 minimum
  • ✅ Never rely on color alone (use icons, labels, shapes)
  • ✅ Colorblind-friendly emotion colors
Typography & Legibility:
  • ✅ Dynamic Type support (all text styles)
  • ✅ Readable font sizes (17pt body minimum)
  • ✅ Adequate line height (1.3x font size)
  • ✅ No fixed font sizes (always use text styles)
Touch Targets & Interaction:
  • ✅ Minimum touch target: 44x44pt
  • ✅ Adequate spacing between interactive elements (8pt minimum)
  • ✅ Clear focus indicators (2pt blue ring)
  • ✅ No time limits on interactions
Navigation & Structure:
  • ✅ Logical VoiceOver reading order
  • ✅ Meaningful accessibility labels (not “Button” or “Image”)
  • ✅ Grouped related elements
  • ✅ Clear hierarchy (headings, sections)
Motion & Animation:
  • ✅ Respect Reduce Motion setting
  • ✅ No flashing content (seizure risk)
  • ✅ Alternative to motion-based interactions
Alternative Input:
  • ✅ Keyboard navigation support (iPad, future)
  • ✅ Voice Control compatibility
  • ✅ External keyboard support

Implementation Notes for @frontend-developer

SwiftUI Components

All components are designed for SwiftUI implementation:
// Example: Primary Button
Button(action: { /* action */ }) {
    Text("Save Entry")
        .font(.headline)
        .foregroundColor(.white)
        .frame(height: 50)
        .frame(maxWidth: .infinity)
        .background(Color("PrimaryCoral"))
        .cornerRadius(12)
        .shadow(color: Color.black.opacity(0.08), radius: 2, x: 0, y: 1)
}
.buttonStyle(.plain) // Disable default button style
.accessibilityLabel("Save entry")

// Example: Emotion Tag
HStack(spacing: 6) {
    Image(systemName: "face.smiling")
        .resizable()
        .frame(width: 20, height: 20)
    Text("Happy")
        .font(.callout)
}
.padding(.horizontal, 8)
.padding(.vertical, 4)
.background(Color("EmotionHappy").opacity(0.2))
.foregroundColor(Color("EmotionHappy"))
.cornerRadius(16)

Design Tokens Usage

All colors, spacing, and typography values are defined in design-tokens.json. Import and use tokens:
// Color tokens
Color("PrimaryCoral")
Color("TextPrimary")
Color("BackgroundSurface")

// Spacing tokens
.padding(.horizontal, Spacing.md) // 16pt
.padding(.vertical, Spacing.xs)   // 8pt

// Typography tokens
.font(.title2) // 22pt bold
.font(.body)   // 17pt regular

  • Style Guide: /docs/design/ux/style-guide.md - Typography, colors, spacing, accessibility
  • Design Tokens: /docs/design/ux/design-tokens.json - SwiftUI-ready tokens
  • PRD: /docs/product/prds/mvp-q1-2025-prd.md - Product requirements
  • Apple HIG: Human Interface Guidelines

Approval

  • UX Designer (self) - Design system complete
  • Product Designer - Reviewed and ready for UI design
  • Frontend Developer (iOS) - Reviewed and implementable
  • Chief Product Officer - Approved for brand alignment

END OF DESIGN SYSTEM Next Steps:
  1. @product-designer: Use components to create high-fidelity UI designs in Figma
  2. @frontend-developer: Implement components in SwiftUI using design tokens
  3. Create Figma component library for design handoff
Version History:
VersionDateChangesAuthor
1.02025-11-10Initial design system with full component libraryUX Designer