diff --git a/apps/Shared/Support/ApproachNoteButton.swift b/apps/Shared/Support/ApproachNoteButton.swift index 22d09e4..b6abce8 100644 --- a/apps/Shared/Support/ApproachNoteButton.swift +++ b/apps/Shared/Support/ApproachNoteButton.swift @@ -97,7 +97,7 @@ private struct ApproachNoteButtonStyle: ButtonStyle { .font(ApproachNoteTheme.headline()) .foregroundColor(appearance.foreground) .frame(maxWidth: .infinity) - .padding(.vertical, 14) + .padding(.vertical, ApproachNoteTheme.controlVerticalPadding) .padding(.horizontal, ApproachNoteTheme.spacingXL) .background( RoundedRectangle(cornerRadius: 10, style: .continuous) diff --git a/apps/Shared/Support/ApproachNoteTheme.swift b/apps/Shared/Support/ApproachNoteTheme.swift index 1b771f6..196239d 100644 --- a/apps/Shared/Support/ApproachNoteTheme.swift +++ b/apps/Shared/Support/ApproachNoteTheme.swift @@ -376,6 +376,17 @@ extension ApproachNoteTheme { static let spacingXL: CGFloat = 24 } +// Component metrics that intentionally sit *outside* the spacing scale above. +// These are not inter-element spacing — they size the interior of a specific +// control to hit a comfortable tap target, and are deliberately named so the +// off-scale value reads as intentional rather than a stray literal. +extension ApproachNoteTheme { + /// Vertical padding inside the filled/outlined pill control + /// (`ApproachNoteButton`). Tuned for tap-target height, not section rhythm, + /// so it sits between `spacingSM` (12) and `spacingMD` (16). + static let controlVerticalPadding: CGFloat = 14 +} + // MARK: - Semantic Color Tokens // // Colors are organized by *role*, not pigment. Pick the token that matches diff --git a/apps/iOS/Support/ToastView.swift b/apps/iOS/Support/ToastView.swift index 503a9cb..b53afcc 100644 --- a/apps/iOS/Support/ToastView.swift +++ b/apps/iOS/Support/ToastView.swift @@ -71,7 +71,7 @@ struct ToastView: View { .buttonStyle(.plain) } .padding(.horizontal, ApproachNoteTheme.spacingMD) - .padding(.vertical, 14) + .padding(.vertical, ApproachNoteTheme.spacingMD) .background( RoundedRectangle(cornerRadius: 12) .fill(.white) diff --git a/doc/design/layout.md b/doc/design/layout.md index cc70f36..4ac9673 100644 --- a/doc/design/layout.md +++ b/doc/design/layout.md @@ -136,3 +136,18 @@ extension ApproachNoteTheme { Reference these tokens in views instead of literals — `SongDetailView` is the adopted template. Treat any spacing value outside this set as a smell. Issue #199 tracks rolling adoption through the remaining screens. + +### Component metrics (intentionally off-scale) + +A few values size the *interior of a specific control* rather than the rhythm +between elements, so they live outside the spacing scale by design. They get +named tokens so the off-scale number reads as intentional, not a stray literal: + +```swift +static let controlVerticalPadding: CGFloat = 14 // ApproachNoteButton pill, tap-target height +``` + +`ApproachNoteButton` uses `controlVerticalPadding` (14) — kept off-scale to hold +its tap-target height; snapping to `sm`/`md` would shift the pill's proportions. +`ToastView`, by contrast, was snapped to `spacingMD` (16): its padding is card +breathing room, not a tap target, so it belongs on the scale. (Per #202.)