Bedrock/README.md

466 lines
15 KiB
Markdown

# Bedrock
A foundational design system and UI component library for building consistent, beautiful SwiftUI applications.
## Overview
Bedrock is designed to be the foundation upon which apps are built, providing:
- **Design System**: Consistent spacing, typography, colors, and animations
- **Color Protocols**: Define consistent color naming with custom palettes per app
- **Settings Components**: Ready-to-use toggle, picker, and selector views
- **Sound & Haptics**: Generic sound manager with haptic feedback support
- **Onboarding**: First-time user experience and contextual hints
- **Cloud Sync**: Generic iCloud data synchronization
- **Visual Effects**: Confetti celebrations, pulsing animations
- **Utilities**: Device detection, debugging tools, and more
---
## 📚 Implementation Guides for AI Agents
> **Before implementing any Bedrock features in a new app, read the relevant guide(s) below.** Each guide contains step-by-step instructions, templates, and troubleshooting information.
### Guide Reference
| Guide | Path | Purpose |
|-------|------|---------|
| **Typography Guide** | [`Sources/Bedrock/Theme/TYPOGRAPHY_GUIDE.md`](Sources/Bedrock/Theme/TYPOGRAPHY_GUIDE.md) | Text styling with `Text.styled()`, typography, and text emphasis |
| **Theme Guide** | [`Sources/Bedrock/Theme/THEME_GUIDE.md`](Sources/Bedrock/Theme/THEME_GUIDE.md) | Create custom color themes using Bedrock's protocol-based theming system |
| **Branding Guide** | [`Sources/Bedrock/Branding/BRANDING_GUIDE.md`](Sources/Bedrock/Branding/BRANDING_GUIDE.md) | Set up app icons, launch screens, and branded launch animations |
| **Settings Guide** | [`Sources/Bedrock/Views/Settings/SETTINGS_GUIDE.md`](Sources/Bedrock/Views/Settings/SETTINGS_GUIDE.md) | Build branded settings screens with reusable UI components |
| **SwiftData CloudKit Guide** | [`Sources/Bedrock/Storage/SWIFTDATA_CLOUDKIT_SETUP_GUIDE.md`](Sources/Bedrock/Storage/SWIFTDATA_CLOUDKIT_SETUP_GUIDE.md) | Configure SwiftData+iCloud sync with reusable Bedrock sync lifecycle utilities |
### Implementation Checklist
Use this checklist when setting up a new app with Bedrock:
#### 📝 Text Styling (Use First)
- [ ] **Read**: `TYPOGRAPHY_GUIDE.md`
- [ ] **Use `Text.styled()`** for all text in your app
- [ ] Choose appropriate `Typography` for each text element (`.heading`, `.body`, `.caption`, etc.)
- [ ] Apply `TextEmphasis` for semantic colors (`.primary`, `.secondary`, `.tertiary`)
- [ ] Use `SectionHeader` for grouped list section titles
- [ ] Use `Label.styled()` for icon + text combinations
#### 🎨 Theming (Required for all apps)
- [ ] **Read**: `THEME_GUIDE.md`
- [ ] Create `[AppName]Theme.swift` in `Shared/Theme/`
- [ ] Define custom `SurfaceColorProvider` with your brand colors
- [ ] Define custom `AccentColorProvider` for interactive elements
- [ ] Create typealiases for easy access (e.g., `AppSurface`, `AppAccent`)
- [ ] **Import Bedrock**: Add `import Bedrock` to all files using theme/design constants (Required)
- [ ] **Asset Catalog Format**: Ensure `Contents.json` uses the `"color"` key and `"luminosity"` appearance (See `THEME_GUIDE.md` for template)
- [ ] **Legibility Alignment**: Apply `.preferredColorScheme(.dark)` to the root view if using a dark theme to ensure system text resolves to white (Required for legibility)
- [ ] Apply theme colors to all views (never use hardcoded colors)
#### 🚀 Branding & Launch Screen (Required for all apps)
- [ ] **Read**: `BRANDING_GUIDE.md`
- [ ] Create `BrandingConfig.swift` in `Shared/`
- [ ] Define `Color.Branding.primary`, `.secondary`, `.accent`
- [ ] Create `AppIconConfig` extension for your app
- [ ] Create `LaunchScreenConfig` extension for your app
- [ ] Create `LaunchScreen.storyboard` with matching brand color (Mandatory for no-flash launch)
- [ ] Add `INFOPLIST_KEY_UILaunchStoryboardName` to build settings
- [ ] **Remove** `INFOPLIST_KEY_UILaunchScreen_*` settings from project (Unreliable)
- [ ] Wrap app entry point with `AppLaunchView` inside a ZStack
- [ ] Generate and export app icon using `IconGeneratorView`
#### ⚙️ Settings Screen (When adding settings)
- [ ] **Read**: `SETTINGS_GUIDE.md`
- [ ] Use `SettingsToggle`, `SettingsSlider`, `SegmentedPicker` components
- [ ] Apply theme colors via `AppSurface`, `AppAccent`, etc.
- [ ] Use `SettingsCard` for grouped sections
- [ ] Use `SettingsDivider` between rows in cards
- [ ] Use `SettingsCardRow` for custom rows inside cards
- [ ] Use `SettingsNavigationRow` for navigation links
- [ ] Avoid manual horizontal child padding inside `SettingsCard` (card owns row insets)
- [ ] Add `#if DEBUG` section for development tools
#### ☁️ SwiftData + CloudKit Sync (When enabling cross-device data sync)
- [ ] **Read**: `SWIFTDATA_CLOUDKIT_SETUP_GUIDE.md`
- [ ] Enable iCloud/CloudKit + Push Notifications + Remote notifications background mode
- [ ] Configure `aps-environment` via xcconfig (`development`/`production`)
- [ ] Wire `SwiftDataCloudKitSyncManager` into app store lifecycle
- [ ] Use `SwiftDataRefreshThrottler` for minimum-interval refresh gates
- [ ] Add a root-level refresh version observation for reliable UI invalidation
- [ ] Validate with two physical devices and CloudKit Console checks
### Quick Start Order
When building a new app from scratch:
1. **First**: Use `Text.styled()` for all text → Semantic typography + colors (see Usage below)
2. **Second**: Read `THEME_GUIDE.md` → Create your app's color theme
3. **Third**: Read `BRANDING_GUIDE.md` → Set up icons and launch screen
4. **Fourth**: Read `SETTINGS_GUIDE.md` → Build your settings view
> **💡 Key Principle**: Always prefer `Text("Hello").styled(.heading)` over raw `.font()` and `.foregroundStyle()` calls. This ensures consistent styling and makes your code more readable.
---
## Installation
Add Bedrock as a dependency in your `Package.swift`:
```swift
dependencies: [
.package(url: "ssh://git@192.168.1.128:220/mbrucedogs/Bedrock.git", branch: "master")
]
```
Then add it to your target:
```swift
.target(
name: "YourApp",
dependencies: ["Bedrock"]
)
```
## Usage
### ⭐ Text Styling (Start Here)
**The `Text.styled()` extension is the preferred way to style all text in Bedrock apps.** It combines typography and color emphasis into a single, semantic API.
> **📖 Full Documentation**: See [`TYPOGRAPHY_GUIDE.md`](Sources/Bedrock/Theme/TYPOGRAPHY_GUIDE.md) for complete typography options, text emphasis levels, and examples.
```swift
import SwiftUI
import Bedrock
// ✅ Preferred: Use styled() for all text
Text("Welcome Back")
.styled(.heroBold)
Text("Your profile is up to date")
.styled(.body, emphasis: .secondary)
Text("Last updated 5 min ago")
.styled(.caption, emphasis: .tertiary)
// Labels also support styled()
Label("Settings", systemImage: "gear")
.styled(.subheading)
// Section headers for grouped lists
SectionHeader("General")
SectionHeader("Notifications", icon: "bell.fill")
```
#### Why Use `styled()` First
- **Single source of truth**: Combines font + color in one call
- **Semantic naming**: Use `.heading`, `.body`, `.caption` instead of raw fonts
- **Theme-aware**: Colors automatically adapt to your registered theme
- **Readable code**: `Text("Hello").styled(.heading)` is clearer than chaining modifiers
---
### Design Constants
Use the `Design` enum for consistent spacing, sizing, and styling:
```swift
import SwiftUI
import Bedrock
struct MyView: View {
var body: some View {
VStack(spacing: Design.Spacing.medium) {
Text("Hello")
.styled(.title)
.padding(Design.Spacing.large)
Button("Tap Me") { }
.clipShape(.rect(cornerRadius: Design.CornerRadius.medium))
}
}
}
```
### Color System
Bedrock provides a **protocol-based color system** that enforces consistent naming while allowing apps to define their own palettes.
> **💡 For Text Colors**: Use `Text.styled()` with `TextEmphasis` instead of manually applying `foregroundStyle()`. See the [Text Styling](#-text-styling-start-here) section above.
#### Using Default Colors
Bedrock includes neutral default colors that work out of the box:
```swift
// ✅ Preferred for text: Use styled()
Text("Primary Text")
.styled(.body)
Text("Secondary Text")
.styled(.body, emphasis: .secondary)
// For non-text elements, use Color extensions
VStack { }
.background(Color.Surface.primary)
```
#### Creating Custom Color Themes
Apps can define custom color palettes by conforming to the color protocols:
```swift
// Define custom accent colors
public enum MyAppAccentColors: AccentColorProvider {
public static let primary = Color(red: 0.9, green: 0.75, blue: 0.3)
public static let light = Color(red: 1.0, green: 0.85, blue: 0.4)
public static let dark = Color(red: 0.7, green: 0.55, blue: 0.2)
public static let secondary = Color(red: 0.2, green: 0.7, blue: 0.7)
}
// Create a complete theme
public enum MyAppTheme: AppColorTheme {
public typealias Surface = DefaultSurfaceColors // Reuse Bedrock defaults
public typealias Text = DefaultTextColors
public typealias Accent = MyAppAccentColors // Custom accents
public typealias Button = DefaultButtonColors
public typealias Status = DefaultStatusColors
public typealias Border = DefaultBorderColors
public typealias Interactive = DefaultInteractiveColors
}
// Use in views
Button("Action") { }
.background(MyAppTheme.Accent.primary)
```
#### Available Color Protocols
| Protocol | Properties |
|----------|------------|
| `SurfaceColorProvider` | primary, secondary, tertiary, overlay, card, groupedFill, sectionFill |
| `TextColorProvider` | primary, secondary, tertiary, disabled, placeholder, inverse |
| `AccentColorProvider` | primary, light, dark, secondary |
| `ButtonColorProvider` | primaryLight, primaryDark, secondary, destructive, cancelText |
| `StatusColorProvider` | success, warning, error, info |
| `BorderColorProvider` | subtle, standard, emphasized, selected |
| `InteractiveColorProvider` | selected, hover, pressed, focus |
### Sound & Haptics
Generic sound manager that works with any app-defined sounds:
```swift
// Define your app's sounds
enum MyAppSound: String, AppSound {
case success, error, notification
var resourceName: String { rawValue }
var resourceExtension: String { "mp3" }
var bundle: Bundle { .main }
var fallbackSystemSoundID: UInt32? { nil }
}
// Play sounds and haptics
let soundManager = SoundManager.shared
soundManager.play(MyAppSound.success)
soundManager.playHaptic(.success)
soundManager.playHaptic(.light)
```
### Onboarding State
Track first-time user experience and contextual hints:
```swift
@Observable
class AppState {
let onboarding = OnboardingState(appIdentifier: "myApp")
var showWelcome: Bool {
!onboarding.hasCompletedWelcome
}
}
// Register hints for skip functionality
onboarding.registerHintKeys("firstBet", "settings", "tutorial")
// Check if hints should show
if onboarding.shouldShowHint("firstBet") {
// Show hint
onboarding.markHintShown("firstBet")
}
// Complete onboarding
onboarding.completeWelcome()
```
### Cloud Sync
Generic iCloud synchronization for app data:
```swift
// Define your persisted data
struct MyAppData: PersistableData {
static var dataIdentifier = "myApp"
static var empty = MyAppData()
var syncPriority: Int { score }
var lastModified: Date = .now
var score: Int = 0
}
// Create sync manager
let syncManager = CloudSyncManager<MyAppData>()
// Access and modify data
syncManager.data.score += 10
syncManager.save()
```
### Visual Effects
#### Confetti
```swift
ZStack {
MainContentView()
if showCelebration {
ConfettiView(colors: [.red, .blue, .gold], count: 50)
}
}
```
#### Pulsing Attention
```swift
Button("Tap Here") { }
.pulsing(isActive: shouldHighlight, color: .white)
```
### Settings Components
Ready-to-use settings UI components:
```swift
// Toggle with title and subtitle
SettingsToggle(
title: "Notifications",
subtitle: "Receive push notifications",
isOn: $notificationsEnabled
)
// Slider with format helpers
SettingsSlider(
title: "Brightness",
subtitle: "Adjusts the brightness",
value: $brightness,
format: SliderFormat.percentage,
leadingIcon: Image(systemName: "sun.min"),
trailingIcon: Image(systemName: "sun.max.fill")
)
// Segmented picker
SegmentedPicker(
title: "Theme",
options: [("Light", "light"), ("Dark", "dark")],
selection: $theme
)
// Selectable row with badge
SelectableRow(
title: "Premium Plan",
subtitle: "Unlock all features",
isSelected: plan == .premium,
badge: { BadgePill(text: "$9.99", isSelected: plan == .premium) },
action: { plan = .premium }
)
```
### Debug Tools
```swift
MyComplexView()
.debugBorder(isDebugMode, color: .red, label: "Header")
```
### Device Detection
Adapt your UI based on device characteristics:
```swift
if DeviceInfo.isPad {
SidebarView()
} else {
TabBarView()
}
if DeviceInfo.isLandscape {
HorizontalLayout()
}
```
## Styling Quick Reference
| What You're Styling | Preferred Approach |
|---------------------|-------------------|
| Any text | `Text("...").styled(.typography, emphasis: .level)` |
| Labels | `Label("...", systemImage: "...").styled(...)` |
| Section titles | `SectionHeader("...")` |
| Spacing | `Design.Spacing.medium`, `.large`, etc. |
| Corner radius | `Design.CornerRadius.medium`, `.large`, etc. |
| Backgrounds | `Color.Surface.primary`, `.card`, etc. |
| Accent/brand colors | `Color.Accent.primary`, `.secondary`, etc. |
| Status indicators | `Color.Status.success`, `.error`, etc. |
> **📖 See Also**: [`TYPOGRAPHY_GUIDE.md`](Sources/Bedrock/Theme/TYPOGRAPHY_GUIDE.md) for detailed do's and don'ts with text styling.
---
## Design System Reference
### Spacing
| Name | Value | Usage |
|------|-------|-------|
| `xxxSmall` | 1pt | Hairline spacing |
| `xxSmall` | 2pt | Minimal spacing |
| `xSmall` | 4pt | Tight spacing |
| `small` | 8pt | Compact spacing |
| `medium` | 12pt | Default spacing |
| `large` | 16pt | Comfortable spacing |
| `xLarge` | 20pt | Generous spacing |
| `xxLarge` | 24pt | Section spacing |
| `xxxLarge` | 32pt | Large section spacing |
### Opacity
| Name | Value | Usage |
|------|-------|-------|
| `verySubtle` | 0.05 | Barely visible |
| `subtle` | 0.1 | Subtle backgrounds |
| `hint` | 0.2 | Hints and disabled states |
| `light` | 0.3 | Light overlays |
| `medium` | 0.5 | Medium emphasis |
| `strong` | 0.7 | Strong emphasis |
| `heavy` | 0.8 | Heavy overlays |
| `almostFull` | 0.9 | Nearly opaque |
### Animation
| Name | Value | Usage |
|------|-------|-------|
| `quick` | 0.3s | Quick transitions |
| `standard` | 0.5s | Standard animations |
| `springDuration` | 0.4s | Spring animations |
| `staggerDelay` | 0.1s | Staggered animations |
## Requirements
- iOS 18.0+
- macOS 15.0+
- Swift 6.0+
## License
Proprietary - All rights reserved.