docs: add brutalist app-wide design spec

Design for extending Brutalist style from home-screen-only to app-wide:
- StyleProvider protocol for shape/typography language
- Adaptive view routers for each major screen
- Brutalist variants for TripDetail, MyTrips, Schedule, Settings
- Colors still controlled by user's selected Theme

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-01-16 09:04:32 -06:00
parent 00a5e4ef0e
commit dc43bf0d53

View File

@@ -0,0 +1,183 @@
# Brutalist App-Wide Design
## Overview
Extend the Brutalist design style from home-screen-only to work app-wide. Brutalist is a **shape/typography language** that layers on top of the user's chosen **color theme** (Teal, Orbit, Clutch, etc.).
**Scope:** Classic + Brutalist styles only. Other 22 styles fall back to Classic for non-home screens.
## Design Language
### What Brutalist Controls (Shape Language)
| Property | Classic | Brutalist |
|----------|---------|-----------|
| Typography | System default | Monospaced |
| Text case | Mixed case | UPPERCASE |
| Letter tracking | 0 | 2-4 |
| Corner radius | 8-16px | 0px |
| Borders | None | 1-2px solid |
| Shadows | Soft | None or harsh |
| Gradients | Yes | No (flat colors) |
| Dividers | Subtle lines | Perforated ticket-stub |
| Labels | Plain text | Bracketed `[ SECTION ]` |
### What Theme Still Controls (Color Palette)
- `Theme.warmOrange` → accent color
- `Theme.routeGold` → secondary accent
- `Theme.textPrimary/Secondary/Muted` → text colors
- `Theme.cardBackground` → surfaces
- `Theme.darkBackground1/lightBackground1` → flat backgrounds (Brutalist override)
## Architecture
### Pattern: Adaptive View Routers
Each major screen has an "Adaptive" wrapper that routes to style-specific variants:
```swift
struct AdaptiveTripDetailView: View {
let trip: Trip
var body: some View {
switch DesignStyleManager.shared.currentStyle {
case .brutalist:
TripDetailView_Brutalist(trip: trip)
default:
TripDetailView_Classic(trip: trip)
}
}
}
```
### File Structure
```
SportsTime/Core/Design/
├── StyleProvider.swift (protocol + implementations)
SportsTime/Features/Trip/Views/
├── AdaptiveTripDetailView.swift (router)
└── Variants/
├── Classic/TripDetailView_Classic.swift
└── Brutalist/TripDetailView_Brutalist.swift
SportsTime/Features/MyTrips/Views/
├── AdaptiveMyTripsView.swift (router)
└── Variants/
├── Classic/MyTripsView_Classic.swift
└── Brutalist/MyTripsView_Brutalist.swift
SportsTime/Features/Schedule/Views/
├── AdaptiveScheduleView.swift (router)
└── Variants/
├── Classic/ScheduleView_Classic.swift
└── Brutalist/ScheduleView_Brutalist.swift
SportsTime/Features/Settings/Views/
├── AdaptiveSettingsView.swift (router)
└── Variants/
├── Classic/SettingsView_Classic.swift
└── Brutalist/SettingsView_Brutalist.swift
```
## StyleProvider Protocol
Lightweight protocol for shared component styling within variants:
```swift
protocol StyleProvider {
// Shape
var cornerRadius: CGFloat { get }
var borderWidth: CGFloat { get }
// Typography
var fontDesign: Font.Design { get }
var usesUppercase: Bool { get }
var headerTracking: CGFloat { get }
// Effects
var usesGradientBackgrounds: Bool { get }
var usesSoftShadows: Bool { get }
// Helpers
func flatBackground(_ colorScheme: ColorScheme) -> Color
}
struct ClassicStyle: StyleProvider {
let cornerRadius: CGFloat = 12
let borderWidth: CGFloat = 0
let fontDesign: Font.Design = .default
let usesUppercase = false
let headerTracking: CGFloat = 0
let usesGradientBackgrounds = true
let usesSoftShadows = true
}
struct BrutalistStyle: StyleProvider {
let cornerRadius: CGFloat = 0
let borderWidth: CGFloat = 1
let fontDesign: Font.Design = .monospaced
let usesUppercase = true
let headerTracking: CGFloat = 2
let usesGradientBackgrounds = false
let usesSoftShadows = false
}
```
## Screen Designs
### TripDetailView_Brutalist
**Header:**
- Date range: Monospaced, uppercase, wide tracking
- Route: `DETROIT → MILWAUKEE → SALT LAKE` (arrows, no dots)
- Sport badges: Bordered rectangles, monospace text
**Stats row:**
- Bordered boxes: `[ 7 DAYS ]` `[ 3 CITIES ]` `[ 4 GAMES ]`
- Monospaced numbers, uppercase labels
**Score card:**
- Sharp rectangle, 2px border
- Score grade uses `Theme.warmOrange`
- No glow effects
**Itinerary:**
- Day headers: `DAY 1` large monospace
- Perforated dividers between days
- Game rows: Bordered boxes, monospace teams
- Travel: `[ TRAVEL ] DETROIT → MILWAUKEE • 327 MI • 5H 27M`
- Timeline: Solid line, square dots
### MyTripsView_Brutalist
- Section headers: `[ PLANNED ]` `[ COMPLETED ]`
- Trip rows: Bordered, monospace city names
- Status badges: Sharp rectangles
### ScheduleView_Brutalist
- Date picker: Sharp buttons, monospace dates
- Game list: Bordered rows, monospace matchups
- Filters: Bracketed labels `[ NBA ]` `[ NHL ]`
### SettingsView_Brutalist
- Section headers: `[ APPEARANCE ]` `[ ACCOUNT ]`
- Row items: Bordered, monospace labels
- Toggles: Sharp rectangles
## Implementation Order
1. `StyleProvider.swift` - Protocol + Classic/Brutalist implementations
2. `TripDetailView_Brutalist.swift` + `AdaptiveTripDetailView.swift`
3. `MyTripsView_Brutalist.swift` + `AdaptiveMyTripsView.swift`
4. `ScheduleView_Brutalist.swift` + `AdaptiveScheduleView.swift`
5. `SettingsView_Brutalist.swift` + `AdaptiveSettingsView.swift`
## Files to Modify
- `UIDesignStyle.swift` - Add `styleProvider` computed property
- All callers of TripDetailView, MyTripsView, etc. - Switch to Adaptive versions