Files
Kordant/tasks/shieldai-unified-restructure/29-ios-design-system.md
2026-05-25 12:23:23 -04:00

136 lines
6.3 KiB
Markdown

# 29. iOS App — Design System Components Matching Web Theme
meta:
id: shieldai-unified-restructure-29
feature: shieldai-unified-restructure
priority: P1
depends_on: [shieldai-unified-restructure-28]
tags: [ios, swiftui, design-system, components, mobile]
objective:
- Build a comprehensive set of reusable SwiftUI components that mirror the web app's UI primitives (Button, Card, Input, Badge, Modal, Toast) using the iOS theme system from task 28. These components should feel native to iOS while maintaining visual consistency with the web app.
deliverables:
- `iOS/ShieldAI/Components/ShieldButton.swift` — Button component:
- Styles: primary (filled), secondary (outlined), ghost (text only), danger
- Sizes: small, medium, large
- States: enabled, disabled, loading (shows `ProgressView`)
- Supports icons (leading/trailing)
- `iOS/ShieldAI/Components/ShieldCard.swift` — Card container:
- Gradient background matching web `.gradient-card`
- Border with corner radius
- Optional header and footer content
- Tap gesture support
- `iOS/ShieldAI/Components/ShieldTextField.swift` — Text input:
- Label, placeholder, validation state
- Secure text entry toggle for passwords
- Error message display
- Focus state styling
- `iOS/ShieldAI/Components/ShieldBadge.swift` — Status badge:
- Variants: default, success, warning, error, info
- Small rounded pill shape
- Icon + text or text only
- `iOS/ShieldAI/Components/ShieldModal.swift` — Modal/sheet presentation:
- `.sheet` wrapper with consistent styling
- Title, content, and action buttons
- Dismiss gesture support
- `iOS/ShieldAI/Components/ShieldToast.swift` — Toast notification:
- Slide-in from top or bottom
- Auto-dismiss after 3-4 seconds
- Variants: success, error, warning, info
- Tap to dismiss
- Uses `overlay` modifier on root view
- `iOS/ShieldAI/Components/ShieldAvatar.swift` — User avatar:
- Displays image or initials fallback
- Sizes: small, medium, large
- Online/away status indicator dot
- `iOS/ShieldAI/Components/ShieldProgressBar.swift` — Progress indicator:
- Linear progress bar with percentage label
- Color variants
- `iOS/ShieldAI/Components/ShieldEmptyState.swift` — Empty state view:
- Icon, title, description, action button
- `iOS/ShieldAI/Components/ShieldSkeleton.swift` — Skeleton loading:
- Shimmer animation using `LinearGradient` mask
- Text line and rectangle shapes
steps:
1. Create `iOS/ShieldAI/Components/` directory.
2. **ShieldButton**:
- Use `Button` with custom label
- Primary: `brandPrimary` background, white text
- Secondary: transparent with `brandPrimary` border and text
- Ghost: transparent, `brandPrimary` text
- Danger: red gradient background
- Loading: replace label with `ProgressView` + reduce opacity
- Use `.frame(maxWidth: .infinity)` for full-width buttons
3. **ShieldCard**:
- `ZStack` with gradient background shape
- `.overlay` for border
- `VStack` for content with padding
- Corner radius: 16pt (matching web `rounded-2xl`)
4. **ShieldTextField**:
- `VStack` with label + `TextField`/`SecureField` + error text
- Custom background using `bgSecondary` with border
- Focus ring using `.overlay` with `brandPrimary` stroke on focus
- Eye icon button for password visibility toggle
5. **ShieldBadge**:
- `Text` inside `Capsule()` background
- Colors from semantic tokens
- Small padding and font size
6. **ShieldModal**:
- View extension `.shieldModal(isPresented:content:)`
- Wraps `.sheet` with consistent header and button bar
- Uses `ShieldCard` styling for sheet background
7. **ShieldToast**:
- Create `ToastManager` as `@Observable` class (iOS 17+) or `ObservableObject`
- `showToast(message, variant, duration)` method
- Root view applies `.overlay` with `ToastContainer`
- `ToastContainer` animates toast in/out with `withAnimation`
8. **ShieldAvatar**:
- `AsyncImage` or `Image` with circular clip
- Fallback: `Text` with initials on `brandPrimary` circle
- Status dot overlay
9. **ShieldProgressBar**:
- `GeometryReader` with filled `Rectangle`
- Percentage label overlay
10. **ShieldEmptyState**:
- `VStack` with icon (`Image(systemName:)`), title, description, optional `ShieldButton`
11. **ShieldSkeleton**:
- `Rectangle` or `RoundedRectangle` with shimmer animation
- Use `LinearGradient` masked with `mask` modifier
- Animate gradient position with `withAnimation(.linear(duration: 1.5).repeatForever())`
12. Create a preview/test view showing all components in light and dark mode.
steps:
- Unit: Each component renders correctly in previews
- Unit: ShieldButton action fires on tap
- Unit: ShieldTextField validation shows error state
- Unit: ShieldToast auto-dismisses after specified duration
- Visual: All components match web app appearance in both color schemes
- Visual: Components adapt to Dynamic Type (accessibility font sizes)
acceptance_criteria:
- [ ] All 10 component types exist in `iOS/ShieldAI/Components/`
- [ ] Each component supports light and dark modes
- [ ] Button supports all 4 styles, 3 sizes, and loading state
- [ ] TextField supports validation, secure entry, and focus styling
- [ ] Toast system can queue and auto-dismiss multiple toasts
- [ ] Card uses gradient background matching web theme
- [ ] Skeleton has smooth shimmer animation
- [ ] All components use theme tokens (no hardcoded colors)
- [ ] Components adapt to accessibility font sizes
validation:
- Open preview canvas for each component and verify appearance
- Run app on simulator and navigate to component test screen
- Toggle dark mode and verify all components shift colors
- Enable large text in Accessibility settings and verify layouts don't break
- Run unit tests via Xcode Cmd+U
notes:
- SwiftUI previews are invaluable for component development. Create a `ComponentsPreview.swift` that shows all variants side by side.
- Use `@ViewBuilder` closures for content slots in `ShieldCard`, `ShieldModal`, etc. to allow flexible content.
- For the toast system, consider using the new `@Observable` macro (iOS 17+) instead of `ObservableObject` for better performance.
- The shimmer animation can be implemented using a `LinearGradient` that moves across the view. Reference: https://swiftuirecipes.com/blog/swiftui-shimmer-effect
- Keep components generic — they should not import service-specific types or business logic.