Install any skill in seconds. Free to start, no credit card required.
Get Started Free →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.
.claude/skills/rshankras-ux-spec/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 351% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 619% | 0% |
| case-10 | ✓→✗ | ▼ Worse | 563% | 0% |
| case-19 | ✓→✗ | ▼ Worse | 735% | 0% |
| case-06 | ✓→✓ | = Same ✓ | 552% | 0% |
Generate comprehensive UI/UX specifications with wireframes and design system for iOS/macOS apps.
This skill activates when the user says:
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.
Before activating this skill, ensure:
Read and extract information from:
Generate two comprehensive documents:
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**:.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**: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**: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**:@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:
Purpose: One sentence describing what user accomplishes]
Layout (ASCII wireframe):
┌─────────────────────────────────────┐
│ [Navigation Bar] │
├─────────────────────────────────────┤
│ │
│ [Main Content Area] │
│ │
├─────────────────────────────────────┤
│ [Bottom Bar / Actions] │
└─────────────────────────────────────┘Components:
Interactions:
States:
Data Requirements:
Accessibility:
---
**Document History**:
| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 1.0.0 | [Date] | UX Designer AI | Initial UX specification |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):
// Light mode static let brandPrimary = Color(hex: "#007AFF") // iOS Blue
// Dark mode static let brandPrimaryDark = Color(hex: "#0A84FF") // Lighter blue
**Brand Secondary** (Accents, highlights):// Light mode static let brandSecondary = Color(hex: "#5856D6") // Purple
// Dark mode static let brandSecondaryDark = Color(hex: "#5E5CE6")
**Brand Accent** (Destructive actions, warnings):// Light mode static let brandAccent = Color(hex: "#FF3B30") // Red
// Dark mode static let brandAccentDark = Color(hex: "#FF453A")
### 2.2 Semantic Colors
**Success** (Confirmation, completion):static let success = Color(hex: "#34C759") // Green
**Warning** (Caution, attention needed):static let warning = Color(hex: "#FF9500") // Orange
**Error** (Errors, destructive actions):static let error = Color(hex: "#FF3B30") // Red (same as accent)
**Info** (Tips, information):static let info = Color(hex: "#007AFF") // Blue (same as primary)
### 2.3 Neutral Colors
**Backgrounds**:// 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**:// 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**: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):
// 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
.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):.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
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**:VStack(spacing: 12) { ... } // Default HStack(spacing: 8) { ... } // Tight VStack(spacing: 24) { ... } // Loose
---
## 5. Layout Grid
### 5.1 Grid System
**Columns**: 12-column grid (flexible)
**Gutter**: 16pt between columns
**Margins**: 16pt (iPhone), 20pt (iPad)
**Usage**:
- Single column: Full width (12/12)
- Two columns: 6/12 each (rare on iPhone)
- Three columns: 4/12 each (iPad only)
### 5.2 Breakpoints
| Device | Width (pt) | Columns | Margins |
|--------|-----------|---------|---------|
| iPhone SE | 375 | 1 | 16pt |
| iPhone 15 | 393 | 1 | 16pt |
| iPhone Pro Max | 430 | 1 | 16pt |
| iPad Portrait | 768 | 2 | 20pt |
| iPad Landscape | 1024 | 3 | 20pt |
---
## 6. Iconography
### 6.1 Icon Set
**Primary**: SF Symbols (native, 4000+ icons)
**Custom**: Only if SF Symbols doesn't have the icon
### 6.2 Icon Sizes
.small // 16x16pt - Inline with text .medium // 20x20pt - Default .large // 24x24pt - Emphasized .xlarge // 28x28pt - Hero icons
### 6.3 Icon Weights
**Match text weight**:
- Body text (.regular) → .regular weight icon
- Headline (.semibold) → .semibold weight icon
- Title (.bold) → .bold weight icon
Image(systemName: "star.fill") .font(.title2) // Size .fontWeight(.semibold) // Weight
### 6.4 Icon Colors
**Default**: Match text color
**Tinted**: Brand primary for active/selected
**Multicolor**: SF Symbols multicolor variant (sparingly)
### 6.5 Common Icons
| Use Case | SF Symbol | Alternative |
|----------|-----------|-------------|
| Add | plus | plus.circle.fill |
| Delete | trash | trash.fill |
| Edit | pencil | pencil.circle |
| Search | magnifyingglass | - |
| Settings | gearshape | gearshape.fill |
| Profile | person | person.circle |
| Home | house | house.fill |
| Favorites | star | star.fill |
| Share | square.and.arrow.up | - |
| Close | xmark | xmark.circle.fill |
| Back | chevron.left | arrow.left |
| Success | checkmark.circle.fill | - |
| Error | xmark.circle.fill | exclamationmark.triangle.fill |
| Warning | exclamationmark.triangle | - |
| Info | info.circle | questionmark.circle |
---
## 7. Shadows & Elevation
### 7.1 Shadow Levels
**Level 1** (Cards, subtle elevation):.shadow(color: .black.opacity(0.1), radius: 8, y: 2)
**Level 2** (Modals, popovers):.shadow(color: .black.opacity(0.15), radius: 16, y: 4)
**Level 3** (Dropdowns, tooltips):.shadow(color: .black.opacity(0.2), radius: 24, y: 8)
### 7.2 Usage Guidelines
**When to Use Shadows**:
- Cards on plain background (differentiation)
- Floating action buttons
- Modals and sheets
- Popovers and dropdowns
**When NOT to Use**:
- Dark mode (use borders or different background colors)
- List items (use dividers instead)
- Flat design (intentionally no elevation)
### 7.3 Dark Mode Adaptation
**Replace shadows with borders**:if colorScheme == .dark { .border(Color.white.opacity(0.1), width: 1) } else { .shadow(radius: 8, y: 2) }
---
## 8. Corner Radius
### 8.1 Radius Scale
enum CornerRadius { static let xs: CGFloat = 4 // Very subtle (badges) static let s: CGFloat = 8 // Small (buttons, inputs) static let m: CGFloat = 12 // Medium (cards) ⭐ Default static let l: CGFloat = 16 // Large (modals, sheets) static let xl: CGFloat = 24 // Extra large (hero cards) static let full: CGFloat = 9999 // Fully rounded (pills, avatars) }
### 8.2 Usage Guidelines
| Element | Radius | Rationale |
|---------|--------|-----------|
| Buttons | 12pt | iOS standard, comfortable |
| Text inputs | 10pt | Slightly less than buttons (visual distinction) |
| Cards | 12pt | Consistent with buttons |
| Modals/Sheets | 16pt | Larger surface, more prominence |
| Badges | 8pt or full | Depends on style (rounded or pill) |
| Avatars | full | Circular |
| Thumbnails | 8pt | Subtle rounding |
---
## 9. Animation & Motion
### 9.1 Animation Timings
enum AnimationDuration { static let fast: Double = 0.2 // Button press, toggle static let standard: Double = 0.3 // Screen transition, fade ⭐ Default static let slow: Double = 0.5 // Complex animations static let verySlow: Double = 1.0 // Onboarding, celebration }
### 9.2 Easing Curves
**Default**: `.easeInOut` (most natural)
.animation(.easeInOut(duration: 0.3), value: someValue)
**Spring**: For playful, bouncy effects.animation(.spring(response: 0.3, dampingFraction: 0.7), value: someValue)
**Linear**: For progress bars, loaders.animation(.linear(duration: 2.0), value: progress)
### 9.3 Common Animations
**Fade In/Out**:.opacity(isVisible ? 1 : 0) .animation(.easeInOut(duration: 0.3), value: isVisible)
**Slide In**:.offset(y: isVisible ? 0 : 50) .opacity(isVisible ? 1 : 0) .animation(.easeOut(duration: 0.4), value: isVisible)
**Scale (Button Press)**:.scaleEffect(isPressed ? 0.95 : 1.0) .animation(.easeInOut(duration: 0.1), value: isPressed)
**Rotation**:.rotationEffect(.degrees(isLoading ? 360 : 0)) .animation(.linear(duration: 1.0).repeatForever(autoreverses: false), value: isLoading)
### 9.4 Reduced Motion
**Respect accessibility setting**:@Environment(\.accessibilityReduceMotion) var reduceMotion
if reduceMotion { // Use fade instead of slide .opacity(isVisible ? 1 : 0) } else { // Use full animation .offset(y: isVisible ? 0 : 50) .opacity(isVisible ? 1 : 0) }
---
## 10. Component Styles (SwiftUI Code)
### 10.1 Button Styles
struct PrimaryButtonStyle: ButtonStyle { func makeBody(configuration: Configuration) -> some View { configuration.label .font(.headline) .foregroundColor(.white) .frame(maxWidth: .infinity) .frame(height: 50) .background(Color.brandPrimary) .cornerRadius(12) .scaleEffect(configuration.isPressed ? 0.98 : 1.0) .animation(.easeInOut(duration: 0.1), value: configuration.isPressed) } }
// Usage: Button("Continue") { } .buttonStyle(PrimaryButtonStyle())
### 10.2 Card Modifier
extension View { func cardStyle() -> some View { self .padding(16) .background(Color(.secondarySystemBackground)) .cornerRadius(12) .shadow(color: .black.opacity(0.1), radius: 8, y: 2) } }
// Usage: VStack { ... } .cardStyle()
### 10.3 Text Field Style
struct CustomTextFieldStyle: TextFieldStyle { func _body(configuration: TextField<Self._Label>) -> some View { configuration .padding(16) .background(Color(.secondarySystemBackground)) .cornerRadius(10) .overlay( RoundedRectangle(cornerRadius: 10) .stroke(Color.brandPrimary.opacity(0.3), lineWidth: 1) ) } }
// Usage: TextField("Enter name", text: $name) .textFieldStyle(CustomTextFieldStyle())
---
## 11. Assets Organization
### 11.1 Color Assets
**Location**: `Assets.xcassets/Colors/`
**Naming Convention**:
- `BrandPrimary` (with Light + Dark appearances)
- `BrandSecondary`
- `TextPrimary`
- `BackgroundSecondary`
### 11.2 Image Assets
**Location**: `Assets.xcassets/Images/`
**Naming Convention**:
- `icon-name` (lowercase, hyphen-separated)
- `illustration-onboarding-1`
- `placeholder-avatar`
**Formats**:
- Icons: PDF (vector) or PNG @2x, @3x
- Photos: PNG or JPEG @2x, @3x
- Illustrations: PDF (preferred) or PNG
### 11.3 SF Symbols
**No need to add to assets** - use directly by name:Image(systemName: "star.fill")
---
## 12. Design Tokens (Reference)
For developers: centralized constants file
// DesignTokens.swift
import SwiftUI
enum DesignSystem { // Colors enum Colors { static let brandPrimary = Color("BrandPrimary") static let brandSecondary = Color("BrandSecondary") static let textPrimary = Color.primary static let textSecondary = Color.secondary static let success = Color.green static let error = Color.red static let warning = Color.orange }
// Typography enum Typography { static let largeTitle = Font.largeTitle static let title = Font.title static let headline = Font.headline static let body = Font.body static let caption = Font.caption }
// Spacing enum Spacing { static let xs: CGFloat = 4 static let s: CGFloat = 8 static let m: CGFloat = 12 static let l: CGFloat = 16 static let xl: CGFloat = 24 static let xxl: CGFloat = 32 }
// Corner Radius enum Radius { static let small: CGFloat = 8 static let medium: CGFloat = 12 static let large: CGFloat = 16 static let full: CGFloat = 9999 }
// Shadows enum Shadow { static let card = (color: Color.black.opacity(0.1), radius: CGFloat(8), y: CGFloat(2)) static let modal = (color: Color.black.opacity(0.15), radius: CGFloat(16), y: CGFloat(4)) }
// Animation enum Animation { static let fast = 0.2 static let standard = 0.3 static let slow = 0.5 } }
// Usage: Text("Hello") .font(DesignSystem.Typography.headline) .foregroundColor(DesignSystem.Colors.brandPrimary) .padding(DesignSystem.Spacing.l)
---
## 13. Implementation Checklist
Before considering design system complete:
- [ ] All colors defined in Assets.xcassets with Dark mode variants
- [ ] Typography scale documented and tested at multiple sizes
- [ ] Spacing scale applied consistently across all screens
- [ ] Corner radius values standardized
- [ ] Shadow styles defined for different elevation levels
- [ ] Icon library documented (SF Symbols references)
- [ ] Animation timings and easing curves specified
- [ ] Component styles implemented as reusable SwiftUI modifiers
- [ ] Design tokens file created for developer reference
- [ ] Dark mode tested for all colors and components
- [ ] Accessibility: Dynamic Type, VoiceOver, Contrast verified
- [ ] Responsive behavior tested on all iPhone sizes
---
**Document History**:
| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 1.0.0 | [Date] | UX Designer AI | Initial design system |When activated, follow these steps:
If any missing, ask user for file path
From inputs, extract:
For each P0 screen:
Based on brand personality:
Write comprehensive UX_SPEC.md to: docs/UX_SPEC.md Write complete DESIGN_SYSTEM.md to: docs/DESIGN_SYSTEM.md
After generating files, present summary:
✅ UI/UX Specifications generated!
📱 UX_SPEC.md Summary:
🎨 DESIGN_SYSTEM.md Summary:
Next Steps:
Would you like me to make any changes to the UI design?
If user requests changes:
When generating the UX specifications:
User: "Generate UX spec from PRD"
You:
This skill is typically:
The UX specifications serve as the visual blueprint that developers use to implement the UI.
Other measured skills in the registry, with their headline benchmark lift.