@@ -37,9 +37,20 @@ struct TimeRangePicker: View {
3737 // inverted or zero-width range selected (the menu already set
3838 // `option == .custom`). Sanitize on close so a backwards range can
3939 // never reach a query.
40− if !isShown && customEnd <= customStart {
40+ guard !isShown else { return }
41+ if customEnd <= customStart {
4142 customEnd = customStart.addingTimeInterval(3600)
4243 }
44+ // Commit on *every* close path, not just the "Done" button. Closing
45+ // the popover by clicking outside is the common dismissal gesture;
46+ // without this the picker reads "Custom" while results still reflect
47+ // the previously selected preset, since QueryView only re-queries on
48+ // `timeRangeOption` changes (which it skips for `.custom`) — never on
49+ // the custom dates. Done sets `showCustomPicker = false` and lets this
50+ // handler do the single commit, so there's no double-query.
51+ if option == .custom {
52+ onCommit?()
53+ }
4354 }
4455 .popover(isPresented: $showCustomPicker) {
4556 VStack(spacing: 12) {
@@ -88,8 +99,9 @@ struct TimeRangePicker: View {
8899 Spacer()
89100
90101 Button("Done") {
102+ // Just close — the `showCustomPicker` change handler is the
103+ // single commit point for all close paths (Done + click-out).
91104 showCustomPicker = false
92− onCommit?()
93105 }
94106 .buttonStyle(.borderedProminent)
95107 .disabled(customEnd <= customStart)