[2026-04-28] Add apple-browsers .cursor rules (43 files) + executor v2 context
This commit is contained in:
@@ -0,0 +1,359 @@
|
||||
---
|
||||
source: ~/DuckDuckGo/apple-browsers.git/main/.cursor/rules/design-system-designresourceskit.mdc
|
||||
confidence: 0.9
|
||||
namespace: work
|
||||
last_synced: 2026-04-28
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# DuckDuckGo iOS Design System & DesignResourcesKit (DRK)
|
||||
|
||||
## Overview
|
||||
|
||||
The DuckDuckGo iOS design system is implemented through **DesignResourcesKit (DRK)**, a shared Swift package that contains our design tokens, type styles, colors, and design system elements.
|
||||
|
||||
**Repository**: [https://github.com/duckduckgo/DesignResourcesKit](https://github.com/duckduckgo/DesignResourcesKit)
|
||||
|
||||
**Figma Designs**: [🖱️ iOS & iPadOS Components](https://www.figma.com/file/GzGKD6gR24AHoUqVykX1ah/%F0%9F%93%B1-iOS-%26-iPadOS-Components?type=design&node-id=3938%3A23329&mode=design&t=0fuiNF84nnV5zExC-1)
|
||||
|
||||
### What DRK Contains
|
||||
|
||||
✅ **Currently Included**:
|
||||
- **Type styles and typography** (based on system styles)
|
||||
- **Semantic color system** (with light/dark mode support)
|
||||
- **Design tokens and foundations**
|
||||
|
||||
🔄 **Future Expansion**:
|
||||
- **Reusable components** (when patterns emerge)
|
||||
- **Advanced interaction patterns**
|
||||
|
||||
❌ **Not Included**:
|
||||
- **Icons** (remain in iOS app directly for now)
|
||||
|
||||
## ⚠️ Critical Rule: Don't Break the Design System
|
||||
|
||||
> **If you take only one thing away from this documentation**:
|
||||
> **Don't add new colors or type styles outside of the design system without reading the guidelines below.**
|
||||
|
||||
Breaking the design system:
|
||||
- **Undermines consistency** across the app
|
||||
- **Creates maintenance debt** with scattered styles
|
||||
- **Breaks accessibility** features like dynamic type
|
||||
- **Fragments the user experience**
|
||||
|
||||
## Typography System
|
||||
|
||||
### Philosophy
|
||||
|
||||
Our typography system is **based on system styles** rather than hardcoded sizes. This ensures:
|
||||
- **Automatic dynamic type support** for accessibility
|
||||
- **Consistent scaling** across different user preferences
|
||||
- **Platform-appropriate styling** that feels native
|
||||
|
||||
### UIKit Usage
|
||||
|
||||
DRK defines **static functions on UIFont** for all typography.
|
||||
|
||||
**Example:** See [uikit-typography-usage.swift](design-system-designresourceskit/uikit-typography-usage.swift)
|
||||
|
||||
#### Available Typography Styles
|
||||
|
||||
**Example:** See [uikit-typography-styles.swift](design-system-designresourceskit/uikit-typography-styles.swift)
|
||||
|
||||
#### Best Practices for UIKit
|
||||
|
||||
**Example:** See [uikit-typography-best-practices.swift](design-system-designresourceskit/uikit-typography-best-practices.swift)
|
||||
|
||||
### SwiftUI Usage
|
||||
|
||||
DRK provides **view modifiers and extensions** for SwiftUI that should be used instead of direct font access.
|
||||
|
||||
**Example:** See [swiftui-typography-usage.swift](design-system-designresourceskit/swiftui-typography-usage.swift)
|
||||
|
||||
#### Available SwiftUI Typography Modifiers
|
||||
|
||||
**Example:** See [swiftui-typography-modifiers.swift](design-system-designresourceskit/swiftui-typography-modifiers.swift)
|
||||
|
||||
#### SwiftUI Code Review Guidelines
|
||||
|
||||
**When reviewing PRs**: Look for `.font()` usage as a red flag.
|
||||
|
||||
**Example:** See [swiftui-code-review-red-flags.swift](design-system-designresourceskit/swiftui-code-review-red-flags.swift)
|
||||
|
||||
### Emergency Escape Hatch (Avoid!)
|
||||
|
||||
**For legacy layout fixes only**: If you absolutely must disable dynamic type, there's a deliberately obtusely named function:
|
||||
|
||||
```swift
|
||||
// ❌ LAST RESORT: Only for fixing legacy layouts
|
||||
let fixedFont = UIFont.daxFontOutsideOfTheDesignSystemToFixLegacyLayoutBreakage()
|
||||
```
|
||||
|
||||
**Important Notes**:
|
||||
- This function **may not exist** in current DRK versions
|
||||
- If you need it, you must **revert the commit** that removed it: [Commit 971979d](https://github.com/duckduckgo/DesignResourcesKit/pull/1/commits/971979d3dcd95567b9812b800eb22ab1611ce3a5)
|
||||
- This is **deliberately annoying** to discourage usage
|
||||
- **Always prefer** fixing the layout to support dynamic type instead
|
||||
|
||||
## Color System
|
||||
|
||||
### Semantic Color Approach
|
||||
|
||||
Our color system uses **semantic naming** rather than literal colors (e.g., "primary text" instead of "black"). This enables:
|
||||
- **Automatic dark mode support**
|
||||
- **Future theme flexibility**
|
||||
- **Accessibility compliance**
|
||||
- **Consistent visual hierarchy**
|
||||
|
||||
### Color Categories
|
||||
|
||||
#### Text Colors
|
||||
**UIKit Example:** See [colors-text-uikit.swift](design-system-designresourceskit/colors-text-uikit.swift)
|
||||
|
||||
**SwiftUI Example:** See [colors-text-swiftui.swift](design-system-designresourceskit/colors-text-swiftui.swift)
|
||||
|
||||
#### Background Colors
|
||||
**Example:** See [colors-background.swift](design-system-designresourceskit/colors-background.swift)
|
||||
|
||||
#### Control Colors
|
||||
```swift
|
||||
// UIKit
|
||||
button.backgroundColor = UIColor(designSystemColor: .controlsFillPrimary)
|
||||
button.backgroundColor = UIColor(designSystemColor: .controlsFillSecondary)
|
||||
|
||||
// SwiftUI
|
||||
Button("Action") { }
|
||||
.foregroundColor(Color(designSystemColor: .controlsFillPrimary))
|
||||
.background(Color(designSystemColor: .controlsFillSecondary))
|
||||
```
|
||||
|
||||
#### Button-Specific Colors
|
||||
```swift
|
||||
// UIKit
|
||||
primaryButton.backgroundColor = UIColor(designSystemColor: .buttonPrimaryBackground)
|
||||
primaryButton.setTitleColor(UIColor(designSystemColor: .buttonPrimaryText), for: .normal)
|
||||
|
||||
secondaryButton.backgroundColor = UIColor(designSystemColor: .buttonSecondaryBackground)
|
||||
secondaryButton.setTitleColor(UIColor(designSystemColor: .buttonSecondaryText), for: .normal)
|
||||
|
||||
// SwiftUI
|
||||
Button("Primary Action") { }
|
||||
.foregroundColor(Color(designSystemColor: .buttonPrimaryText))
|
||||
.background(Color(designSystemColor: .buttonPrimaryBackground))
|
||||
|
||||
Button("Secondary Action") { }
|
||||
.foregroundColor(Color(designSystemColor: .buttonSecondaryText))
|
||||
.background(Color(designSystemColor: .buttonSecondaryBackground))
|
||||
```
|
||||
|
||||
#### Accent Colors
|
||||
```swift
|
||||
// UIKit
|
||||
view.tintColor = UIColor(designSystemColor: .accent)
|
||||
|
||||
// SwiftUI
|
||||
Image(systemName: "heart.fill")
|
||||
.foregroundColor(Color(designSystemColor: .accent))
|
||||
```
|
||||
|
||||
### Anti-patterns: What NOT to Do
|
||||
|
||||
**Example:** See [colors-anti-patterns.swift](design-system-designresourceskit/colors-anti-patterns.swift)
|
||||
|
||||
## Enforcement and Code Review
|
||||
|
||||
### Automated Enforcement
|
||||
|
||||
#### Danger Integration
|
||||
**Asset catalog enforcement**: We use [Danger](https://danger.systems/) to prevent new colors being added directly to iOS app asset catalogs.
|
||||
|
||||
**Example:** See [danger-integration.rb](design-system-designresourceskit/danger-integration.rb)
|
||||
|
||||
### Manual Code Review Checklist
|
||||
|
||||
#### ✅ Look for in PRs:
|
||||
- **DRK typography usage**: `UIFont.daxTitle1()`, `.daxBody()` modifiers
|
||||
- **DRK color usage**: `UIColor(designSystemColor: .textPrimary)`
|
||||
- **No hardcoded colors**: No hex values, RGB tuples, or named colors
|
||||
- **No `.font()` modifiers** in SwiftUI (red flag for design system violations)
|
||||
- **Semantic naming**: Colors described by purpose, not appearance
|
||||
|
||||
#### Code Review Examples
|
||||
|
||||
**Example:** See [code-review-checklist.swift](design-system-designresourceskit/code-review-checklist.swift)
|
||||
|
||||
### Opportunistic Improvements
|
||||
|
||||
**Most of the iOS app currently does not use the design system**, so you're encouraged to:
|
||||
|
||||
1. **Opportunistically refactor** old code to use DRK when you encounter it
|
||||
2. **Update hardcoded colors** to semantic colors when working in an area
|
||||
3. **Replace system fonts** with DRK typography when touching text styling
|
||||
4. **File follow-up tickets** for systematic cleanup when you notice patterns
|
||||
|
||||
#### Example: Opportunistic Refactoring
|
||||
|
||||
**Example:** See [opportunistic-refactoring.swift](design-system-designresourceskit/opportunistic-refactoring.swift)
|
||||
|
||||
## Components
|
||||
|
||||
### Current State: Minimal Component Library
|
||||
|
||||
We primarily use **system components** rather than custom ones, following iOS design guidelines. This is different from our Android app which has more custom components.
|
||||
|
||||
**Philosophy**:
|
||||
- **System components first** - leverages platform conventions
|
||||
- **Custom components only when needed** - avoid overengineering
|
||||
- **Reusable when patterns emerge** - extract when used in multiple places
|
||||
|
||||
### Existing Custom Components
|
||||
|
||||
#### Blue Button (Reusable)
|
||||
Our primary custom component used across multiple screens.
|
||||
|
||||
**Example:** See [blue-button-component.swift](design-system-designresourceskit/blue-button-component.swift)
|
||||
|
||||
**Candidate for DRK**: This button is used in multiple places and should be extracted into DesignResourcesKit as a reusable component.
|
||||
|
||||
### Future Component Strategy
|
||||
|
||||
#### When to Create Components
|
||||
|
||||
**✅ Create a component when**:
|
||||
- Pattern is used in **3+ different contexts**
|
||||
- Styling is **complex or specialized**
|
||||
- Behavior needs to be **consistent across usage**
|
||||
- Component **encapsulates design system tokens**
|
||||
|
||||
**❌ Don't create a component when**:
|
||||
- Used in only **one place** (keep it local)
|
||||
- **System component exists** that meets needs
|
||||
- Component would be **overly generic** or complex
|
||||
|
||||
#### Emerging Patterns to Watch
|
||||
|
||||
Look for these patterns that might become components:
|
||||
|
||||
```swift
|
||||
// Bottom sheets - if format becomes consistent
|
||||
struct BottomSheetView: View {
|
||||
// Consistent styling, behavior, animation
|
||||
// Could become reusable component
|
||||
}
|
||||
|
||||
// Info cards/panels - if layout patterns emerge
|
||||
struct InfoCardView: View {
|
||||
// Standard card styling with DRK colors
|
||||
// Could be extracted if reused
|
||||
}
|
||||
|
||||
// Form elements - if custom styling is needed
|
||||
struct FormFieldView: View {
|
||||
// Consistent form field styling
|
||||
// Could become component library
|
||||
}
|
||||
```
|
||||
|
||||
#### Component Creation Process
|
||||
|
||||
1. **Identify the pattern** in your current work
|
||||
2. **Check if existing implementations** could be generalized
|
||||
3. **Design the API** to be flexible but opinionated
|
||||
4. **Implement using DRK tokens** for colors, typography, spacing
|
||||
5. **Add to DesignResourcesKit** package
|
||||
6. **Update existing usages** to use the new component
|
||||
7. **Document the component** with usage examples
|
||||
|
||||
**Example:** See [component-creation-example.swift](design-system-designresourceskit/component-creation-example.swift)
|
||||
|
||||
## Modularization Strategy
|
||||
|
||||
### Why DRK is a Separate Package
|
||||
|
||||
**High friction is a feature**: Making DRK a separate module provides beneficial constraints:
|
||||
|
||||
1. **Immutability encouragement**: Changes require more thought and process
|
||||
2. **API stability**: Forces consideration of breaking changes
|
||||
3. **Reusability**: Can be shared across iOS/macOS if needed
|
||||
4. **Clear boundaries**: Separates design tokens from app logic
|
||||
5. **Version control**: Can be tagged and versioned independently
|
||||
|
||||
### Design System Evolution
|
||||
|
||||
**Original Discussion**: [Tech Design: How to modularise iOS/macOS design system elements](✓ Tech Design: How to modularise iOS/macOS design system elements)
|
||||
|
||||
**Guiding Principles**:
|
||||
- **Start minimal**: Don't over-engineer early
|
||||
- **Evolve based on usage**: Add components when patterns emerge
|
||||
- **Maintain consistency**: All additions should follow established patterns
|
||||
- **Document decisions**: Keep rationale for future developers
|
||||
|
||||
## Working with DesignResourcesKit
|
||||
|
||||
### Adding New Design Tokens
|
||||
|
||||
**Process for adding colors/typography**:
|
||||
|
||||
1. **Design system first**: Ensure token is defined in Figma
|
||||
2. **Semantic naming**: Use purpose-based names (`textPrimary` not `black`)
|
||||
3. **Light/dark variants**: Define both light and dark mode values
|
||||
4. **PR to DRK**: Add to DesignResourcesKit repository
|
||||
5. **Update app**: Use new tokens in consuming apps
|
||||
6. **Documentation**: Update usage examples and guidelines
|
||||
|
||||
### Updating DRK Version
|
||||
|
||||
**In consuming app (iOS/macOS):**
|
||||
|
||||
**Example:** See [updating-drk-version.swift](design-system-designresourceskit/updating-drk-version.swift)
|
||||
|
||||
**Testing DRK changes**:
|
||||
- Test in both **light and dark modes**
|
||||
- Verify **dynamic type scaling** works correctly
|
||||
- Check **accessibility** with larger text sizes
|
||||
- Test on **different device sizes**
|
||||
|
||||
### Local Development
|
||||
|
||||
**For iterating on DRK:**
|
||||
|
||||
**Example:** See [local-development.sh](design-system-designresourceskit/local-development.sh)
|
||||
|
||||
## Resources and References
|
||||
|
||||
### Official Resources
|
||||
|
||||
- **GitHub Repository**: [duckduckgo/DesignResourcesKit](https://github.com/duckduckgo/DesignResourcesKit)
|
||||
- **Figma Designs**: [iOS & iPadOS Components](https://www.figma.com/file/GzGKD6gR24AHoUqVykX1ah/%F0%9F%93%B1-iOS-%26-iPadOS-Components?type=design&node-id=3938%3A23329&mode=design&t=0fuiNF84nnV5zExC-1)
|
||||
|
||||
### Related Documentation
|
||||
|
||||
- **Colors**: [Tech Design: How to organise colors and icons in iOS and macOS wrt the design system](✓ Tech Design: How to organise colors and icons in iOS and macOS wrt the design system)
|
||||
- **Colors Update**: [Tech Design: Redefine design system colors in DesignResourcesKit](✓ Tech Design: Redefine design system colors in DesignResourcesKit)
|
||||
- **Typography**: [Tech Design: How to organise typography/label styles in iOS and macOS wrt the design system](✓ Tech Design: How to organise typography/label styles in iOS and macOS wrt the design system)
|
||||
- **Enforcement**: [Use danger to stop new colors being added to the iOS app](✓ Use danger to stop new colors being added to the iOS app)
|
||||
|
||||
### Quick Reference
|
||||
|
||||
#### UIKit Checklist
|
||||
- [ ] Use `UIFont.daxTitle1()`, `UIFont.daxBody()`, etc.
|
||||
- [ ] Use `UIColor(designSystemColor: .textPrimary)` etc.
|
||||
- [ ] No hardcoded colors or fonts
|
||||
- [ ] No system colors for app content
|
||||
|
||||
#### SwiftUI Checklist
|
||||
- [ ] Use `.daxTitle1()`, `.daxBody()` modifiers
|
||||
- [ ] Use `Color(designSystemColor: .textPrimary)` etc.
|
||||
- [ ] Avoid `.font()` modifier (red flag in reviews)
|
||||
- [ ] No hardcoded colors
|
||||
|
||||
#### Code Review Checklist
|
||||
- [ ] No new colors in asset catalogs
|
||||
- [ ] DRK typography used consistently
|
||||
- [ ] Semantic color naming
|
||||
- [ ] No hardcoded styling
|
||||
- [ ] Opportunistic improvements to legacy code
|
||||
|
||||
---
|
||||
|
||||
**Remember**: The design system is only as strong as our commitment to using it. Every PR is an opportunity to improve consistency and user experience.
|
||||
Reference in New Issue
Block a user