diff --git a/README.md b/README.md index 314657c..f4f6257 100644 --- a/README.md +++ b/README.md @@ -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 { diff --git a/Sources/Bedrock/Branding/AppIconView.swift b/Sources/Bedrock/Branding/AppIconView.swift index 400ce09..5c2a090 100644 --- a/Sources/Bedrock/Branding/AppIconView.swift +++ b/Sources/Bedrock/Branding/AppIconView.swift @@ -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 } diff --git a/Sources/Bedrock/Branding/BRANDING_GUIDE.md b/Sources/Bedrock/Branding/BRANDING_GUIDE.md index f7a9a7b..789534f 100644 --- a/Sources/Bedrock/Branding/BRANDING_GUIDE.md +++ b/Sources/Bedrock/Branding/BRANDING_GUIDE.md @@ -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 ) } ``` diff --git a/Sources/Bedrock/Theme/THEME_GUIDE.md b/Sources/Bedrock/Theme/THEME_GUIDE.md index 436f9f9..0df0aa0 100644 --- a/Sources/Bedrock/Theme/THEME_GUIDE.md +++ b/Sources/Bedrock/Theme/THEME_GUIDE.md @@ -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: diff --git a/Sources/Bedrock/Views/Settings/SETTINGS_GUIDE.md b/Sources/Bedrock/Views/Settings/SETTINGS_GUIDE.md index acdbdc4..7a0f9ce 100644 --- a/Sources/Bedrock/Views/Settings/SETTINGS_GUIDE.md +++ b/Sources/Bedrock/Views/Settings/SETTINGS_GUIDE.md @@ -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