mirror of
https://github.com/grafana/grafana.git
synced 2024-11-25 10:20:29 -06:00
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:
parent
c13fd62b16
commit
fa468fb17c
@ -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',
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
@ -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}
|
||||
|
@ -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/));
|
||||
|
Loading…
Reference in New Issue
Block a user