379 lines
10 KiB
Markdown
379 lines
10 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 |
|
|
|-------|------|---------|
|
|
| **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 |
|
|
|
|
### Implementation Checklist
|
|
|
|
Use this checklist when setting up a new app with Bedrock:
|
|
|
|
#### 🎨 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`)
|
|
- [ ] **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 `SettingsNavigationRow` for navigation links
|
|
- [ ] Add `#if DEBUG` section for development tools
|
|
|
|
### Quick Start Order
|
|
|
|
When building a new app from scratch:
|
|
|
|
1. **First**: Read `THEME_GUIDE.md` → Create your app's color theme
|
|
2. **Second**: Read `BRANDING_GUIDE.md` → Set up icons and launch screen
|
|
3. **Third**: Read `SETTINGS_GUIDE.md` → Build your settings view
|
|
|
|
---
|
|
|
|
## 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
|
|
|
|
### Design Constants
|
|
|
|
Use the `Design` enum for consistent spacing, sizing, and styling:
|
|
|
|
```swift
|
|
import Bedrock
|
|
|
|
struct MyView: View {
|
|
var body: some View {
|
|
VStack(spacing: Design.Spacing.medium) {
|
|
Text("Hello")
|
|
.font(.system(size: Design.BaseFontSize.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.
|
|
|
|
#### Using Default Colors
|
|
|
|
Bedrock includes neutral default colors that work out of the box:
|
|
|
|
```swift
|
|
Text("Primary Text")
|
|
.foregroundStyle(Color.TextColors.primary)
|
|
|
|
Text("Secondary Text")
|
|
.foregroundStyle(Color.TextColors.secondary)
|
|
|
|
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()
|
|
}
|
|
```
|
|
|
|
## 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.
|