Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>

This commit is contained in:
Matt Bruce 2026-01-12 13:29:00 -06:00
parent 4a420242a8
commit ce905431ed
5 changed files with 88 additions and 14 deletions

View File

@ -39,6 +39,8 @@ Use this checklist when setting up a new app with Bedrock:
- [ ] 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)
@ -98,6 +100,7 @@ Then add it to your target:
Use the `Design` enum for consistent spacing, sizing, and styling:
```swift
import SwiftUI
import Bedrock
struct MyView: View {

View File

@ -59,20 +59,33 @@ public struct AppIconView: View {
// Size calculations
private var iconSize: CGFloat { size * 0.35 }
private var subtitleSize: CGFloat { size * 0.25 }
/// Dynamic subtitle size based on text length.
private var subtitleSize: CGFloat {
guard let length = config.subtitle?.count else { return 0 }
let baseSize = size * 0.14 // Reduced from 0.25 to prevent overwhelm
let scaleFactor: CGFloat = switch length {
case ...4: 1.0 // "PRO", "PLUS"
case 5...6: 0.85 // "SAMPLE", "CAMERA"
case 7...9: 0.70 // "MESSENGER"
default: 0.55
}
return baseSize * scaleFactor
}
/// Dynamic title size based on text length.
/// Shorter titles get larger fonts, longer titles shrink to fit within the border.
private var titleSize: CGFloat {
let baseSize = size * 0.12
let baseSize = size * 0.10 // Adjusted to 0.10 to better balance with subtitle
let length = config.title.count
// Scale factor: full size for 6 chars, progressively smaller for longer
let scaleFactor: CGFloat = switch length {
case ...6: 1.0 // "SELFIE", "CAMERA"
case 7: 0.95 // "WEATHER"
case 8: 0.85 // "SETTINGS"
case 9: 0.75 // "MESSENGER"
case ...6: 1.0 // "BEDROCK", "SELFIE"
case 7...8: 0.90 // "SETTINGS"
case 9...10: 0.75 // "MESSENGER"
default: 0.65 // Very long titles
}

View File

@ -465,15 +465,12 @@ extension LaunchScreenConfig {
cornerSymbol: "sparkle", // Sparkles in corners
decorativeSymbol: "circle.fill", // Circle in decorative line
patternStyle: .radial, // Radial glow effect
layoutStyle: .iconAboveTitle,
iconSpacing: 12,
animationDuration: 0.6,
primaryColor: Color.Branding.primary,
secondaryColor: Color.Branding.secondary,
accentColor: Color.Branding.accent,
titleColor: .white,
iconSize: 52,
titleSize: 38,
iconSpacing: 12,
animationDuration: 0.6
titleColor: .white
)
}
```

View File

@ -389,6 +389,67 @@ For dark themes:
- Text is white with varying opacity
- Ensure sufficient contrast (WCAG AA: 4.5:1 for text)
## Asset Catalog Best Practices
While you can define colors directly in Swift, the **gold standard** for Bedrock themes is using an **Asset Catalog (`.xcassets`)**. This allows for visual editing, better system integration, and automatic Light/Dark mode switching.
### 1. Mandatory JSON Structure (Contents.json)
Xcode is extremely strict about the JSON schema in `.colorset/Contents.json`. To ensure your colors are correctly recognized (avoiding "unassigned children"), use this exact pattern:
> [!IMPORTANT]
> Use the `"color"` key for data (not `"value"`) and `"appearance": "luminosity"` for theme variants.
```json
{
"colors" : [
{
"idiom" : "universal",
"color" : {
"color-space" : "display-p3",
"components" : { "alpha": "1.000", "red": "0.06", "green": "0.06", "blue": "0.09" }
}
},
{
"appearances" : [ { "appearance": "luminosity", "value": "light" } ],
"idiom" : "universal",
"color" : {
"color-space" : "display-p3",
"components" : { "alpha": "1.000", "red": "0.96", "green": "0.96", "blue": "0.98" }
}
},
{
"appearances" : [ { "appearance": "luminosity", "value": "dark" } ],
"idiom" : "universal",
"color" : {
"color-space" : "display-p3",
"components" : { "alpha": "1.000", "red": "0.06", "green": "0.06", "blue": "0.09" }
}
}
],
"info" : { "author" : "xcode", "version" : 1 }
}
```
### 2. The 3-Variant Pattern
Always provide **Any (Universal)**, **Light**, and **Dark** variants.
- **Any**: Typically matches your dark branding for high-end apps.
- **Light/Dark**: Explicit luminosity overrides for standard OS behavior.
### 3. Folder Namespacing
Organize colors into folders (`Surface/`, `Text/`, `Accent/`).
- Enable **"Provides Namespace"** in the folder's `Contents.json`.
- This allows you to reference colors cleanly as `Color("Surface/Primary")` while keeping the catalog organized.
```json
{
"info" : { "author" : "xcode", "version" : 1 },
"properties" : { "provides-namespace" : true }
}
```
## Migrating Existing Views
If you have views using hardcoded colors, migrate them:

View File

@ -150,7 +150,7 @@ typealias AppBorder = MyAppBorderColors
typealias AppInteractive = MyAppInteractiveColors
```
> **Important**: Do NOT add typealiases inside `extension Color { }` as they will conflict with Bedrock's defaults and cause "ambiguous use" compiler errors. Use top-level `App`-prefixed typealiases instead.
> **Important**: Do NOT add typealiases inside `extension Color { }` as they will conflict with Bedrock's defaults and cause "ambiguous use" compiler errors. Use top-level `App`-prefixed typealiases instead. Ensure ALL typealiases mentioned in the theme are created, as components like `SettingsToggle` or `SettingsCard` rely on them for consistent branding.
---
@ -284,7 +284,7 @@ SettingsSectionHeader(
### SettingsToggle
A toggle row with title, subtitle, and optional title accessory (e.g., premium crown).
A toggle row with title, subtitle, and optional title accessory (e.g., premium crown). **Note: Subtitle is required.**
```swift
// Basic toggle