PlanBoard — Platform Decision Record
A dated entry for every cross-platform decision baked into the codebase. Treat this as a living document — every PR that adds an #if os(...) block updates this file.
Format:
## PDR-NNN — Short title
**Date**: YYYY-MM-DD
**File(s)**: relative path
**Decision**: what we did
**Rationale**: why
**Alternatives considered**: brief
**Revisit if**: condition
PDR-001 — Native macOS, not Catalyst
Date: 2024-09-01
Files: project-level (Xcode target setup)
Decision: Two separate targets — PlanBoard-iOS and PlanBoard-macOS — sharing Swift packages, not a single iOS target with Catalyst.
Rationale: Mac-feeling app. Catalyst’s iOS chrome doesn’t pass a Mac user’s smell test (button tints, toolbar sizing, missing keyboard nav).
Alternatives considered: Catalyst (faster, worse UX); SwiftUI multiplatform single target with #available(macOS ...) (couples shipping cadences).
Revisit if: Apple converges Catalyst + SwiftUI lifecycle further and the Mac chrome story improves.
PDR-002 — NavigationStack on iPhone, NavigationSplitView on iPad and Mac
Date: 2024-09-03
Files: PlanBoardiOS/RootView.swift, PlanBoardMac/RootView.swift
Decision: iPhone uses a stack-based navigation root; iPad and Mac use 3-pane split view.
Rationale: Phone screen is too small for split view to be useful. iPad and Mac users expect sidebar/content/detail.
Alternatives considered: Split view everywhere (cramped on iPhone); stack everywhere (wastes screen on iPad/Mac).
Revisit if: iPhone introduces a new form factor where a sidebar makes sense (foldable).
PDR-003 — MenuBarExtra on Mac, no equivalent on iOS
Date: 2024-09-05
Files: PlanBoardMac/App.swift
Decision: Mac app declares a MenuBarExtra scene with a popover showing top 3 cards. iOS has no equivalent.
Rationale: Menu bar is a native Mac affordance; iOS has Widgets which fill the same role.
Alternatives considered: NSStatusItem via NSApplicationDelegate (legacy, more boilerplate).
Revisit if: Apple adds a system-tray-like surface to iOS.
PDR-004 — CommandMenu only on Mac
Date: 2024-09-05
Files: PlanBoardMac/App.swift
Decision: .commands { ... } modifier is applied only to the Mac scene.
Rationale: iOS doesn’t render command menus. Including them does nothing on iOS but adds clutter.
Alternatives considered: Apply to all platforms (no harm but no benefit; we prefer explicit).
Revisit if: SwiftUI on iPad gets first-class menu support.
PDR-005 — Multi-window only on Mac
Date: 2024-09-06
Files: PlanBoardMac/App.swift
Decision: WindowGroup(id: "board", for: UUID.self) only declared in Mac target.
Rationale: iPad does support multi-window via scenes, but the UX is less common and adds complexity. Defer to v2.
Alternatives considered: Add iPad multi-window now (longer scope).
Revisit if: a user explicitly requests iPad multi-window.
PDR-006 — Card drag with Transferable everywhere, custom for cross-window only on Mac
Date: 2024-09-08
Files: PlanBoardShared/Card+Transferable.swift, PlanBoardMac/MultiWindowDragHandler.swift
Decision: Card conforms to Transferable for all platforms; cross-window drag handler is Mac-only.
Rationale: Single-window drag works the same everywhere via Transferable. Cross-window drag only matters on Mac (only Mac has multi-window in v1).
Alternatives considered: Implement custom drag everywhere (over-engineered).
Revisit if: iPad multi-window is added (then this handler needs iPad support too).
PDR-007 — Hover effects only on Mac
Date: 2024-09-10
Files: PlanBoardShared/View+Hover.swift
Decision: A .planboardCardHover() modifier applies .onHover only when os(macOS).
Rationale: iPad has pointer events too, but the design feedback is similar to touch. Mac is the primary hover-driven platform.
Alternatives considered: Enable hover on iPad with pointer (could revisit).
Revisit if: iPad pointer usage becomes a primary interaction model worth designing around.
PDR-008 — Different “primary action” gesture per platform
Date: 2024-09-12
Files: PlanBoardShared/CardView.swift
Decision: Tap on iOS, click on Mac (same .onTapGesture); long-press on iOS shows context menu, right-click on Mac shows the same menu.
Rationale: .contextMenu handles both — single API, platform-correct trigger.
Alternatives considered: Custom gesture handling per platform (unnecessary).
Revisit if: tvOS or visionOS support is added.
PDR-009 — Inspector as sheet on iPhone, third pane on iPad/Mac
Date: 2024-09-14
Files: PlanBoardiOS/RootView.swift, PlanBoardMac/RootView.swift
Decision: Card detail is a .sheet on iPhone, the detail column on iPad/Mac.
Rationale: iPhone screen can’t fit a third pane; sheet is the iOS-idiomatic modal.
Alternatives considered: Sheet on all platforms (wastes screen on iPad/Mac); navigation push on iPhone (loses context).
Revisit if: a new iPhone form factor changes this.
PDR-010 — Widget shape varies by host
Date: 2024-09-16
Files: PlanBoardWidget-iOS/WidgetEntryView.swift, PlanBoardMac/MenuBarContent.swift
Decision: Same TopCardsContent view; iOS wraps in containerBackground(.fill.tertiary, for: .widget), Mac wraps in a popover-shaped container.
Rationale: Widget hosts have different visual conventions; the content is identical.
Alternatives considered: Two completely separate widget implementations (duplication).
Revisit if: Apple introduces unified widget chrome across platforms.
PDR-011 — Keyboard shortcuts only declared on Mac
Date: 2024-09-18
Files: PlanBoardMac/App.swift
Decision: .keyboardShortcut(...) modifiers exist only inside Mac CommandMenu declarations. iOS shortcuts (for hardware keyboards) are not declared in v1.
Rationale: Scope. iOS hardware keyboard shortcuts are a v2 polish.
Alternatives considered: Declare shortcuts in shared scenes (works but doesn’t address discoverability on iOS).
Revisit if: a user with an iPad+keyboard requests it.
PDR-012 — NavigationSplitViewStyle.balanced on Mac, .automatic elsewhere
Date: 2024-09-20
Files: PlanBoardShared/View+Navigation.swift
Decision: .planboardNavigationStyle() modifier uses .balanced on Mac, .automatic elsewhere.
Rationale: Balanced gives Mac users a familiar 3-equal-column layout; automatic adapts well on iPad.
Alternatives considered: .prominentDetail (Mac feels off); .automatic everywhere (Mac sidebar collapses too aggressively).
Revisit if: SwiftUI improves the default Mac sidebar behavior.
How to maintain this document
When you add an #if os(...) block:
- Append a new PDR entry below the last.
- Number sequentially.
- Always include date, files, decision, rationale, alternatives, revisit condition.
- In your PR description, link to the PDR entry.
When you remove an #if os(...) block:
- Add a new PDR entry noting the removal (don’t delete the historical one).
- Reference the original PDR.
- Explain why the conditional is no longer needed.
This way the file grows monotonically and contains the full history of cross-platform decisions for the app’s lifetime.
Continue to the Appendix.