From 5585be1f8916b3382f0703f8b51d334a112747b0 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Fri, 9 Dec 2022 15:16:30 +0000 Subject: [PATCH] [v9.3.x] TimePicker: Prevent TimePicker overflowing viewport on small screens (#60100) TimePicker: Prevent TimePicker overflowing viewport on small screens (#59808) * render timepicker in a modal style on small screens * remove top: -1 * apply styles * prevent bug where selecting a relative range wouldn't apply if the absolute ranges were expanded * Revert "prevent bug where selecting a relative range wouldn't apply if the absolute ranges were expanded" This reverts commit 7090443c121e52cc436b38deaebaf4e118371f8a. (cherry picked from commit 1497ad476084929f13ae24e071d147503da3c8db) Co-authored-by: Ashley Harrison --- .../DateTimePicker/DateTimePicker.tsx | 6 +- .../DateTimePickers/TimeRangePicker.tsx | 68 +++++++++++++------ .../TimeRangePicker/TimePickerCalendar.tsx | 23 +++---- .../TimeRangePicker/TimePickerContent.tsx | 3 - 4 files changed, 58 insertions(+), 42 deletions(-) diff --git a/packages/grafana-ui/src/components/DateTimePickers/DateTimePicker/DateTimePicker.tsx b/packages/grafana-ui/src/components/DateTimePickers/DateTimePicker/DateTimePicker.tsx index b94b60fa7f4d..2d478ca02935 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/DateTimePicker/DateTimePicker.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/DateTimePicker/DateTimePicker.tsx @@ -7,9 +7,9 @@ import { dateTimeFormat, DateTime, dateTime, GrafanaTheme2, isDateTime } from '@ import { Button, ClickOutsideWrapper, HorizontalGroup, Icon, InlineField, Input, Portal } from '../..'; import { useStyles2, useTheme2 } from '../../../themes'; +import { getModalStyles } from '../../Modal/getModalStyles'; import { TimeOfDayPicker } from '../TimeOfDayPicker'; import { getBodyStyles } from '../TimeRangePicker/CalendarBody'; -import { getStyles as getCalendarStyles } from '../TimeRangePicker/TimePickerCalendar'; import { isValid } from '../utils'; export interface Props { @@ -29,8 +29,8 @@ export const DateTimePicker: FC = ({ date, maxDate, label, onChange }) => const [isOpen, setOpen] = useState(false); const theme = useTheme2(); + const { modalBackdrop } = getModalStyles(theme); const isFullscreen = useMedia(`(min-width: ${theme.breakpoints.values.lg}px)`); - const containerStyles = useStyles2(getCalendarStyles); const styles = useStyles2(getStyles); const onApply = useCallback( @@ -69,7 +69,7 @@ export const DateTimePicker: FC = ({ date, maxDate, label, onChange }) =>
setOpen(false)} />
-
+
) diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx index ba5968020a01..129e9a3a2c13 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx @@ -1,4 +1,4 @@ -import { css } from '@emotion/css'; +import { css, cx } from '@emotion/css'; import { useDialog } from '@react-aria/dialog'; import { FocusScope } from '@react-aria/focus'; import { useOverlay } from '@react-aria/overlays'; @@ -16,9 +16,10 @@ import { } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; -import { useStyles2 } from '../../themes/ThemeContext'; +import { useStyles2, useTheme2 } from '../../themes/ThemeContext'; import { t, Trans } from '../../utils/i18n'; import { ButtonGroup } from '../Button'; +import { getModalStyles } from '../Modal/getModalStyles'; import { ToolbarButton } from '../ToolbarButton'; import { Tooltip } from '../Tooltip/Tooltip'; @@ -85,10 +86,12 @@ export function TimeRangePicker(props: TimeRangePickerProps) { }; const ref = createRef(); - const { overlayProps } = useOverlay({ onClose, isDismissable: true, isOpen }, ref); + const { overlayProps, underlayProps } = useOverlay({ onClose, isDismissable: true, isOpen }, ref); const { dialogProps } = useDialog({}, ref); + const theme = useTheme2(); const styles = useStyles2(getStyles); + const { modalBackdrop } = getModalStyles(theme); const hasAbsolute = isDateTime(value.raw.from) || isDateTime(value.raw.to); const variant = isSynced ? 'active' : isOnCanvas ? 'canvas' : 'default'; @@ -122,23 +125,26 @@ export function TimeRangePicker(props: TimeRangePickerProps) { {isOpen && ( -
- - - -
+ <> +
+
+ + + +
+ )} {timeSyncButton} @@ -219,13 +225,33 @@ const formattedRange = (value: TimeRange, timeZone?: TimeZone) => { return rangeUtil.describeTimeRange(adjustedTimeRange, timeZone); }; -const getStyles = () => { +const getStyles = (theme: GrafanaTheme2) => { return { container: css` position: relative; display: flex; vertical-align: middle; `, + backdrop: css({ + display: 'none', + [theme.breakpoints.down('sm')]: { + display: 'block', + }, + }), + content: css({ + position: 'absolute', + right: 0, + top: '116%', + zIndex: theme.zIndex.dropdown, + + [theme.breakpoints.down('sm')]: { + position: 'fixed', + right: '50%', + top: '50%', + transform: 'translate(50%, -50%)', + zIndex: theme.zIndex.modal, + }, + }), }; }; diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerCalendar.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerCalendar.tsx index 826707a4cbc4..6711766d100b 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerCalendar.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerCalendar.tsx @@ -8,6 +8,7 @@ import { DateTime, GrafanaTheme2, TimeZone } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { useTheme2 } from '../../../themes'; +import { getModalStyles } from '../../Modal/getModalStyles'; import { Body } from './CalendarBody'; import { Footer } from './CalendarFooter'; @@ -16,7 +17,7 @@ import { Header } from './CalendarHeader'; export const getStyles = (theme: GrafanaTheme2, isReversed = false) => { return { container: css` - top: -1px; + top: 0px; position: absolute; ${isReversed ? 'left' : 'right'}: 544px; box-shadow: ${theme.shadows.z3}; @@ -38,26 +39,17 @@ export const getStyles = (theme: GrafanaTheme2, isReversed = false) => { } `, modal: css` + box-shadow: ${theme.shadows.z3}; + left: 50%; position: fixed; - top: 20%; - width: 100%; + top: 50%; + transform: translate(-50%, -50%); z-index: ${theme.zIndex.modal}; `, content: css` margin: 0 auto; width: 268px; `, - backdrop: css` - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - background: #202226; - opacity: 0.7; - z-index: ${theme.zIndex.modalBackdrop}; - text-align: center; - `, }; }; @@ -77,6 +69,7 @@ const stopPropagation = (event: React.MouseEvent) => event.stopP function TimePickerCalendar(props: TimePickerCalendarProps) { const theme = useTheme2(); + const { modalBackdrop } = getModalStyles(theme); const styles = getStyles(theme, props.isReversed); const { isOpen, isFullscreen, onClose } = props; const ref = React.createRef(); @@ -112,6 +105,7 @@ function TimePickerCalendar(props: TimePickerCalendarProps) { return ( +
@@ -121,7 +115,6 @@ function TimePickerCalendar(props: TimePickerCalendarProps) {
-
); } diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerContent.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerContent.tsx index 5de2391d1821..65f106b8f989 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerContent.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerContent.tsx @@ -267,10 +267,7 @@ const getStyles = stylesFactory((theme: GrafanaTheme2, isReversed, hideQuickRang container: css` background: ${theme.colors.background.primary}; box-shadow: ${theme.shadows.z3}; - position: absolute; - z-index: ${theme.zIndex.dropdown}; width: ${isFullscreen ? '546px' : '262px'}; - top: 116%; border-radius: 2px; border: 1px solid ${theme.colors.border.weak}; ${isReversed ? 'left' : 'right'}: 0;