diff --git a/CHANGELOG.md b/CHANGELOG.md index 58fd7d5a89d4..c878813e9c0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ All notable changes to this project will be documented in this file. - Fixed issue with timestamps being rendered incorrectly in segment menus and modals for some timezones - Fixed main graph being clipped when the browser's root font size is smaller than the default 16px - Fixed issue with users with billing role not being able to create personal segments +- Fixed period arrow keys hijacking custom-range calendar ## v3.2.0 - 2026-01-16 diff --git a/assets/js/dashboard/keybinding.tsx b/assets/js/dashboard/keybinding.tsx index 646b35bd206c..7fa707d88432 100644 --- a/assets/js/dashboard/keybinding.tsx +++ b/assets/js/dashboard/keybinding.tsx @@ -113,11 +113,13 @@ export function Keybind(opts: KeybindOptions) { export function NavigateKeybind({ keyboardKey, type, - navigateProps + navigateProps, + shouldAlsoIgnoreWhen = [] }: { keyboardKey: string type: KeyboardEventType navigateProps: AppNavigationTarget + shouldAlsoIgnoreWhen?: Array<(event: KeyboardEvent) => boolean> }) { const navigate = useAppNavigate() const handler = useCallback(() => { @@ -129,7 +131,7 @@ export function NavigateKeybind({ keyboardKey={keyboardKey} type={type} handler={handler} - shouldIgnoreWhen={[isModifierPressed, isTyping]} + shouldIgnoreWhen={[isModifierPressed, isTyping, ...shouldAlsoIgnoreWhen]} targetRef="document" /> ) diff --git a/assets/js/dashboard/nav-menu/query-periods/dashboard-dates.test.tsx b/assets/js/dashboard/nav-menu/query-periods/dashboard-dates.test.tsx index 64d3eca180ff..f57d6b80d552 100644 --- a/assets/js/dashboard/nav-menu/query-periods/dashboard-dates.test.tsx +++ b/assets/js/dashboard/nav-menu/query-periods/dashboard-dates.test.tsx @@ -150,6 +150,36 @@ test.each([ } ) +test('arrow keys shift the period when the custom-range calendar is closed, but not while it is open', async () => { + const localDomain = 'no-arrow-hijack.test' + const startUrl = `${getRouterBasepath({ domain: localDomain, shared: false })}${stringifySearch({ period: 'month', date: '2024-08-15' })}` + + render(, { + wrapper: (props) => ( + + ) + }) + + expect(screen.getByText('August 2024')).toBeVisible() + expect(document.querySelector('.flatpickr-calendar')).toBeNull() + + await userEvent.keyboard('{ArrowLeft}') + expect(screen.getByText('July 2024')).toBeVisible() + + await userEvent.keyboard('c') + expect(document.querySelector('.flatpickr-calendar')).not.toBeNull() + + await userEvent.keyboard('{ArrowLeft}') + await userEvent.keyboard('{ArrowLeft}') + + expect(screen.getByText('July 2024')).toBeVisible() + expect(document.querySelector('.flatpickr-calendar')).not.toBeNull() +}) + test('going back resets the stored dashboardState period to previous value', async () => { const BrowserBackButton = () => { const navigate = useNavigate() diff --git a/assets/js/dashboard/nav-menu/query-periods/date-range-calendar.tsx b/assets/js/dashboard/nav-menu/query-periods/date-range-calendar.tsx index dae81d15077c..021594b3a9a6 100644 --- a/assets/js/dashboard/nav-menu/query-periods/date-range-calendar.tsx +++ b/assets/js/dashboard/nav-menu/query-periods/date-range-calendar.tsx @@ -2,6 +2,9 @@ import React, { useLayoutEffect, useRef } from 'react' import DatePicker from 'react-flatpickr' import { CustomLocale } from 'flatpickr/dist/types/locale' +export const isDateRangeCalendarOpen = (): boolean => + !!document.querySelector('.flatpickr-calendar') + const calendarLocale: Partial = { weekdays: { shorthand: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], diff --git a/assets/js/dashboard/nav-menu/query-periods/move-period-arrows.tsx b/assets/js/dashboard/nav-menu/query-periods/move-period-arrows.tsx index f5aa35ce0561..bfce22d42ca3 100644 --- a/assets/js/dashboard/nav-menu/query-periods/move-period-arrows.tsx +++ b/assets/js/dashboard/nav-menu/query-periods/move-period-arrows.tsx @@ -11,6 +11,7 @@ import { AppNavigationLink } from '../../navigation/use-app-navigate' import { DashboardPeriod } from '../../dashboard-time-periods' import { useMatch } from 'react-router-dom' import { rootRoute } from '../../router' +import { isDateRangeCalendarOpen } from './date-range-calendar' const ArrowKeybind = ({ keyboardKey @@ -36,6 +37,8 @@ const ArrowKeybind = ({ type="keydown" keyboardKey={keyboardKey} navigateProps={{ search }} + // Don't hijack arrow keys flatpickr uses for its own day-cell navigation. + shouldAlsoIgnoreWhen={[isDateRangeCalendarOpen]} /> ) }