From 8af260e7711de21c8c04df30a2834d2c8b260b75 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 22 Oct 2026 03:20:20 +0000 Subject: [PATCH] fix(macos): open the event form time list on the selected time like web The quarter-hour list always opened at 12 AM, so picking a time near the current one meant scrolling through the morning. Web centers the list on the selected time. Scroll to the selected row, or the quarter hour before it, when the list opens. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GKHjv2HDx1DFAnG4cfSxcr --- .../EventForm/EventFormTimeField.swift | 55 +++++++++++-------- docs/features/desktop-web-parity-checklist.md | 2 +- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/apps/calendar-macos/CompassUI/Sources/CompassUI/EventForm/EventFormTimeField.swift b/apps/calendar-macos/CompassUI/Sources/CompassUI/EventForm/EventFormTimeField.swift index 2fb19cd1a..85cf82eb6 100644 --- a/apps/calendar-macos/CompassUI/Sources/CompassUI/EventForm/EventFormTimeField.swift +++ b/apps/calendar-macos/CompassUI/Sources/CompassUI/EventForm/EventFormTimeField.swift @@ -16,6 +16,12 @@ struct EventFormTimeField: View { _showsMenu = State(initialValue: openPicker) } + /// The row for the selected time, or the quarter hour before it (3:10 opens on 3 PM). + private var selectedQuarterHourLabel: String { + let quarter = (date.timeIntervalSince1970 / 900).rounded(.down) * 900 + return EventFormTimeFormat.formatLabel(for: Date(timeIntervalSince1970: quarter)) + } + var body: some View { Button { showsMenu = true @@ -39,32 +45,37 @@ struct EventFormTimeField: View { .buttonStyle(.plain) .accessibilityIdentifier(accessibilityIdentifier) .popover(isPresented: $showsMenu, arrowEdge: .bottom) { - ScrollView { - LazyVStack(alignment: .leading, spacing: 0) { - ForEach(EventFormTimeFormat.quarterHourLabels(), id: \.self) { label in - Button { - if let merged = EventFormTimeFormat.mergeTime(into: date, label: label) { - date = merged + ScrollViewReader { proxy in + ScrollView { + LazyVStack(alignment: .leading, spacing: 0) { + ForEach(EventFormTimeFormat.quarterHourLabels(), id: \.self) { label in + Button { + if let merged = EventFormTimeFormat.mergeTime(into: date, label: label) { + date = merged + } + showsMenu = false + } label: { + Text(label) + .font(.rubik(NativeWebLayoutTokens.fontSizeBody)) + .foregroundStyle( + label == EventFormTimeFormat.formatLabel(for: date) + ? theme.onAccentColor : theme.textColor + ) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, 10) + .padding(.vertical, 6) + .background( + label == EventFormTimeFormat.formatLabel(for: date) + ? theme.accentColor : Color.clear + ) } - showsMenu = false - } label: { - Text(label) - .font(.rubik(NativeWebLayoutTokens.fontSizeBody)) - .foregroundStyle( - label == EventFormTimeFormat.formatLabel(for: date) - ? theme.onAccentColor : theme.textColor - ) - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.horizontal, 10) - .padding(.vertical, 6) - .background( - label == EventFormTimeFormat.formatLabel(for: date) - ? theme.accentColor : Color.clear - ) + .buttonStyle(.plain) + .id(label) } - .buttonStyle(.plain) } } + // Web opens the list centered on the selected time, not at 12 AM. + .onAppear { proxy.scrollTo(selectedQuarterHourLabel, anchor: .center) } } .frame(width: 120, height: 220) .background(theme.surfacePanelColor) diff --git a/docs/features/desktop-web-parity-checklist.md b/docs/features/desktop-web-parity-checklist.md index c5a70fb3b..8261a8fba 100644 --- a/docs/features/desktop-web-parity-checklist.md +++ b/docs/features/desktop-web-parity-checklist.md @@ -114,7 +114,7 @@ This checklist compares **apps/calendar-web** (reference UI) with **apps/calenda | Replaces sidebar body while open | βœ… | `EventFormView` in `RootView` | | Date field **MM.DD.YY** closed display | 🟑 | `EventFormCompactDateField` + `EventFormDateFormat`; verify parity capture after merge | | Datepicker open Enter/Space/ArrowDown | 🟑 | Audit `EventFormScheduleSection.swift` vs web | -| Time pickers | 🟑 | Visual parity pass needed | +| Time pickers | 🟑 | The list opens centered on the selected time (or the quarter hour before it) like web. Still differs: macOS shows the list and the date picker as AppKit popovers that can open to the side of the field, while web drops them below it | | Location / Meet / guests grouping | βœ… | #4607 single `EventFormCard` + description card (web #4599) | | Color row Mod+digit hint | 🟑 | Trailing ⌘ 6 keycaps like web `EventColorPicker`; web swaps to ← β†’ Β· Enter while a swatch has focus, macOS has no swatch arrow keys yet. The demo capture also shows a guest row on macOS only: the demo fixture calendar can invite (UI tests need it), the real local calendar cannot | | Save bar: accent fill, on-accent text, space-between, **⌘Enter** hint | 🟑 | macOS save bar matches accent + Mod+Enter keycap (#4610); sidebar shows web save-draft tip (#4614) |