TimePicker: Close overlay content when toolbar button is clicked for the second time (#77796)

Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com>
This commit is contained in:
Juan Cabanas 2023-11-08 11:39:37 -03:00 committed by GitHub
parent c13fd62b16
commit fa468fb17c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 14 deletions

View File

@ -15,6 +15,7 @@ export const Components = {
},
TimePicker: {
openButton: 'data-testid TimePicker Open Button',
overlayContent: 'data-testid TimePicker Overlay Content',
fromField: 'Time Range from field',
toField: 'Time Range to field',
applyTimeRange: 'data-testid TimePicker submit button',

View File

@ -1,10 +1,14 @@
import { render } from '@testing-library/react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { dateTime, TimeRange } from '@grafana/data';
import { selectors as e2eSelectors } from '@grafana/e2e-selectors';
import { TimeRangePicker } from './TimeRangePicker';
const selectors = e2eSelectors.components.TimePicker;
const from = dateTime('2019-12-17T07:48:27.433Z');
const to = dateTime('2019-12-18T07:48:27.433Z');
@ -29,4 +33,25 @@ describe('TimePicker', () => {
expect(container.queryByLabelText(/Time range selected/i)).toBeInTheDocument();
});
it('switches overlay content visibility when toolbar button is clicked twice', async () => {
render(
<TimeRangePicker
onChangeTimeZone={() => {}}
onChange={(value) => {}}
value={value}
onMoveBackward={() => {}}
onMoveForward={() => {}}
onZoom={() => {}}
/>
);
const openButton = screen.getByTestId(selectors.openButton);
const overlayContent = screen.queryByTestId(selectors.overlayContent);
expect(overlayContent).not.toBeInTheDocument();
await userEvent.click(openButton);
expect(screen.getByTestId(selectors.overlayContent)).toBeInTheDocument();
await userEvent.click(openButton);
expect(overlayContent).not.toBeInTheDocument();
});
});

View File

@ -2,7 +2,7 @@ import { css, cx } from '@emotion/css';
import { useDialog } from '@react-aria/dialog';
import { FocusScope } from '@react-aria/focus';
import { useOverlay } from '@react-aria/overlays';
import React, { memo, FormEvent, createRef, useState } from 'react';
import React, { memo, createRef, useState } from 'react';
import {
isDateTime,
@ -75,19 +75,28 @@ export function TimeRangePicker(props: TimeRangePickerProps) {
setOpen(false);
};
const onOpen = (event: FormEvent<HTMLButtonElement>) => {
event.stopPropagation();
event.preventDefault();
setOpen(!isOpen);
const onToolbarButtonSwitch = () => {
setOpen((prevState) => !prevState);
};
const onClose = () => {
setOpen(false);
};
const ref = createRef<HTMLElement>();
const { overlayProps, underlayProps } = useOverlay({ onClose, isDismissable: true, isOpen }, ref);
const { dialogProps } = useDialog({}, ref);
const overlayRef = createRef<HTMLElement>();
const buttonRef = createRef<HTMLElement>();
const { overlayProps, underlayProps } = useOverlay(
{
onClose,
isDismissable: true,
isOpen,
shouldCloseOnInteractOutside: (element) => {
return !buttonRef.current?.contains(element);
},
},
overlayRef
);
const { dialogProps } = useDialog({}, overlayRef);
const theme = useTheme2();
const styles = useStyles2(getStyles);
@ -109,14 +118,19 @@ export function TimeRangePicker(props: TimeRangePickerProps) {
/>
)}
<Tooltip content={<TimePickerTooltip timeRange={value} timeZone={timeZone} />} placement="bottom" interactive>
<Tooltip
ref={buttonRef}
content={<TimePickerTooltip timeRange={value} timeZone={timeZone} />}
placement="bottom"
interactive
>
<ToolbarButton
data-testid={selectors.components.TimePicker.openButton}
aria-label={t('time-picker.range-picker.current-time-selected', 'Time range selected: {{currentTimeRange}}', {
currentTimeRange,
})}
aria-controls="TimePickerContent"
onClick={onOpen}
onClick={onToolbarButtonSwitch}
icon="clock-nine"
isOpen={isOpen}
variant={variant}
@ -125,10 +139,10 @@ export function TimeRangePicker(props: TimeRangePickerProps) {
</ToolbarButton>
</Tooltip>
{isOpen && (
<div>
<div data-testid={selectors.components.TimePicker.overlayContent}>
<div role="presentation" className={cx(modalBackdrop, styles.backdrop)} {...underlayProps} />
<FocusScope contain autoFocus>
<section className={styles.content} ref={ref} {...overlayProps} {...dialogProps}>
<section className={styles.content} ref={overlayRef} {...overlayProps} {...dialogProps}>
<TimePickerContent
timeZone={timeZone}
fiscalYearStartMonth={fiscalYearStartMonth}

View File

@ -113,7 +113,6 @@ describe('TimePickerWithHistory', () => {
const timeRange = getDefaultTimeRange();
render(<TimePickerWithHistory value={timeRange} {...props} />);
await userEvent.click(screen.getByLabelText(/Time range selected/));
for (const [inputFrom, inputTo] of inputRanges) {
await userEvent.click(screen.getByLabelText(/Time range selected/));