diff --git a/packages/eui/.loki/reference/chrome_desktop_Forms_EuiSuperDatePicker_EuiSuperDatePicker_Custom_Time_Zone_Display.png b/packages/eui/.loki/reference/chrome_desktop_Forms_EuiSuperDatePicker_EuiSuperDatePicker_Custom_Time_Zone_Display.png new file mode 100644 index 00000000000..10eaaade32f Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Forms_EuiSuperDatePicker_EuiSuperDatePicker_Custom_Time_Zone_Display.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Forms_EuiSuperDatePicker_EuiSuperDatePicker_Time_Window_Buttons.png b/packages/eui/.loki/reference/chrome_desktop_Forms_EuiSuperDatePicker_EuiSuperDatePicker_Time_Window_Buttons.png index 05ef003b1d3..0ac5c0b4134 100644 Binary files a/packages/eui/.loki/reference/chrome_desktop_Forms_EuiSuperDatePicker_EuiSuperDatePicker_Time_Window_Buttons.png and b/packages/eui/.loki/reference/chrome_desktop_Forms_EuiSuperDatePicker_EuiSuperDatePicker_Time_Window_Buttons.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Forms_EuiSuperDatePicker_EuiSuperDatePicker_Custom_Time_Zone_Display.png b/packages/eui/.loki/reference/chrome_mobile_Forms_EuiSuperDatePicker_EuiSuperDatePicker_Custom_Time_Zone_Display.png new file mode 100644 index 00000000000..72b2be7986a Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Forms_EuiSuperDatePicker_EuiSuperDatePicker_Custom_Time_Zone_Display.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Forms_EuiSuperDatePicker_EuiSuperDatePicker_Time_Window_Buttons.png b/packages/eui/.loki/reference/chrome_mobile_Forms_EuiSuperDatePicker_EuiSuperDatePicker_Time_Window_Buttons.png index 94bac6e6ed1..fa0e3f51a13 100644 Binary files a/packages/eui/.loki/reference/chrome_mobile_Forms_EuiSuperDatePicker_EuiSuperDatePicker_Time_Window_Buttons.png and b/packages/eui/.loki/reference/chrome_mobile_Forms_EuiSuperDatePicker_EuiSuperDatePicker_Time_Window_Buttons.png differ diff --git a/packages/eui/changelogs/upcoming/9191.md b/packages/eui/changelogs/upcoming/9191.md new file mode 100644 index 00000000000..e1c2a0814a0 --- /dev/null +++ b/packages/eui/changelogs/upcoming/9191.md @@ -0,0 +1,2 @@ +- Updated `EuiSuperDatePicker` with new time zone information, opt-in via `timeZoneDisplayProps`. + diff --git a/packages/eui/src/components/date_picker/super_date_picker/date_popover/__snapshots__/timezone_display.test.tsx.snap b/packages/eui/src/components/date_picker/super_date_picker/date_popover/__snapshots__/timezone_display.test.tsx.snap new file mode 100644 index 00000000000..425a6430ce3 --- /dev/null +++ b/packages/eui/src/components/date_picker/super_date_picker/date_popover/__snapshots__/timezone_display.test.tsx.snap @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EuiTimeZoneDisplay renders 1`] = ` +
+
+ + + UTC-8 (America/Los_Angeles) + +
+
+`; diff --git a/packages/eui/src/components/date_picker/super_date_picker/date_popover/absolute_tab.test.tsx b/packages/eui/src/components/date_picker/super_date_picker/date_popover/absolute_tab.test.tsx index 36298eddfcf..2cac4931553 100644 --- a/packages/eui/src/components/date_picker/super_date_picker/date_popover/absolute_tab.test.tsx +++ b/packages/eui/src/components/date_picker/super_date_picker/date_popover/absolute_tab.test.tsx @@ -150,7 +150,7 @@ describe('EuiAbsoluteTab', () => { describe('allows several other common date formats, and autoformats them to the `dateFormat` prop', () => { const assertOutput = (input: HTMLInputElement) => { - // Exclude hours from assertion, because moment uses local machine timezone + // Exclude hours from assertion, because moment uses local machine time zone expect(input.value).toContain('Jan 1, 1970'); }; diff --git a/packages/eui/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx b/packages/eui/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx index f00c3b963d5..7f22a5597c2 100644 --- a/packages/eui/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx +++ b/packages/eui/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx @@ -17,7 +17,11 @@ import React, { import moment, { Moment, LocaleSpecifier } from 'moment'; import dateMath from '@elastic/datemath'; -import { useUpdateEffect, useEuiMemoizedStyles } from '../../../../services'; +import { + useUpdateEffect, + useEuiMemoizedStyles, + useGeneratedHtmlId, +} from '../../../../services'; import { useEuiI18n } from '../../../i18n'; import { EuiFormRow, EuiFieldText, EuiFormLabel } from '../../../form'; import { EuiFlexGroup } from '../../../flex'; @@ -26,6 +30,10 @@ import { EuiCode } from '../../../code'; import { EuiDatePicker, EuiDatePickerProps } from '../../date_picker'; import { EuiDatePopoverContentProps } from './date_popover_content'; +import { + EuiTimeZoneDisplay, + type EuiTimeZoneDisplayProps, +} from './timezone_display'; import { euiAbsoluteTabDateFormStyles } from './absolute_tab.styles'; // Allow users to paste in and have the datepicker parse multiple common date formats, @@ -47,6 +55,7 @@ export interface EuiAbsoluteTabProps { utcOffset?: number; minDate?: Moment; maxDate?: Moment; + timeZoneDisplayProps?: EuiTimeZoneDisplayProps; } export const EuiAbsoluteTab: FunctionComponent = ({ @@ -60,6 +69,7 @@ export const EuiAbsoluteTab: FunctionComponent = ({ minDate, maxDate, labelPrefix, + timeZoneDisplayProps = {}, }) => { const styles = useEuiMemoizedStyles(euiAbsoluteTabDateFormStyles); @@ -80,6 +90,7 @@ export const EuiAbsoluteTab: FunctionComponent = ({ [dateFormat] ); + const timeZomeDescriptionId = useGeneratedHtmlId(); const submitButtonLabel = useEuiI18n( 'euiAbsoluteTab.dateFormatButtonLabel', 'Parse date' @@ -181,6 +192,7 @@ export const EuiAbsoluteTab: FunctionComponent = ({ helpText={ hasUnparsedText && !isTextInvalid ? dateFormatError : undefined } + describedByIds={[timeZomeDescriptionId]} > = ({ /> )} + ); }; diff --git a/packages/eui/src/components/date_picker/super_date_picker/date_popover/date_popover_button.tsx b/packages/eui/src/components/date_picker/super_date_picker/date_popover/date_popover_button.tsx index ade5d2c1ed0..2b3f4b419ff 100644 --- a/packages/eui/src/components/date_picker/super_date_picker/date_popover/date_popover_button.tsx +++ b/packages/eui/src/components/date_picker/super_date_picker/date_popover/date_popover_button.tsx @@ -25,6 +25,7 @@ import { EuiDatePopoverContent, EuiDatePopoverContentProps, } from './date_popover_content'; +import { type EuiTimeZoneDisplayProps } from './timezone_display'; import { euiDatePopoverButtonStyles } from './date_popover_button.styles'; @@ -50,6 +51,7 @@ export interface EuiDatePopoverButtonProps { maxDate?: Moment; compressed?: boolean; timeOptions: TimeOptions; + timeZoneDisplayProps?: EuiTimeZoneDisplayProps; } export const EuiDatePopoverButton: FunctionComponent< @@ -76,6 +78,7 @@ export const EuiDatePopoverButton: FunctionComponent< onPopoverClose, compressed, timeOptions, + timeZoneDisplayProps = {}, ...rest } = props; @@ -157,6 +160,7 @@ export const EuiDatePopoverButton: FunctionComponent< timeOptions={timeOptions} minDate={minDate} maxDate={maxDate} + timeZoneDisplayProps={timeZoneDisplayProps} /> ); diff --git a/packages/eui/src/components/date_picker/super_date_picker/date_popover/date_popover_content.tsx b/packages/eui/src/components/date_picker/super_date_picker/date_popover/date_popover_content.tsx index 4ee97b3d971..7e584f710bb 100644 --- a/packages/eui/src/components/date_picker/super_date_picker/date_popover/date_popover_content.tsx +++ b/packages/eui/src/components/date_picker/super_date_picker/date_popover/date_popover_content.tsx @@ -26,6 +26,7 @@ import { import { EuiAbsoluteTab } from './absolute_tab'; import { EuiRelativeTab } from './relative_tab'; import { euiDatePopoverContentStyles } from './date_popover_content.styles'; +import { type EuiTimeZoneDisplayProps } from './timezone_display'; export interface EuiDatePopoverContentProps { value: string; @@ -40,6 +41,7 @@ export interface EuiDatePopoverContentProps { minDate?: Moment; maxDate?: Moment; timeOptions: TimeOptions; + timeZoneDisplayProps?: EuiTimeZoneDisplayProps; } export const EuiDatePopoverContent: FunctionComponent< @@ -57,6 +59,7 @@ export const EuiDatePopoverContent: FunctionComponent< timeOptions, minDate, maxDate, + timeZoneDisplayProps = {}, }) => { const styles = useEuiMemoizedStyles(euiDatePopoverContentStyles); @@ -107,6 +110,7 @@ export const EuiDatePopoverContent: FunctionComponent< utcOffset={utcOffset} minDate={minDate} maxDate={maxDate} + timeZoneDisplayProps={timeZoneDisplayProps} /> ), 'data-test-subj': 'superDatePickerAbsoluteTab', @@ -126,6 +130,7 @@ export const EuiDatePopoverContent: FunctionComponent< roundUp={roundUp} labelPrefix={labelPrefix} timeOptions={timeOptions} + timeZoneDisplayProps={timeZoneDisplayProps} /> ), 'data-test-subj': 'superDatePickerRelativeTab', diff --git a/packages/eui/src/components/date_picker/super_date_picker/date_popover/relative_tab.tsx b/packages/eui/src/components/date_picker/super_date_picker/date_popover/relative_tab.tsx index d3311977c66..8e885fe42b9 100644 --- a/packages/eui/src/components/date_picker/super_date_picker/date_popover/relative_tab.tsx +++ b/packages/eui/src/components/date_picker/super_date_picker/date_popover/relative_tab.tsx @@ -43,6 +43,10 @@ import { toRelativeStringFromParts, } from '../relative_utils'; import { EuiDatePopoverContentProps } from './date_popover_content'; +import { + EuiTimeZoneDisplay, + type EuiTimeZoneDisplayProps, +} from './timezone_display'; export interface EuiRelativeTabProps { dateFormat: string; @@ -52,6 +56,7 @@ export interface EuiRelativeTabProps { roundUp?: boolean; labelPrefix: string; timeOptions: TimeOptions; + timeZoneDisplayProps?: EuiTimeZoneDisplayProps; } export const EuiRelativeTab: FunctionComponent = ({ @@ -62,6 +67,7 @@ export const EuiRelativeTab: FunctionComponent = ({ onChange, roundUp, labelPrefix, + timeZoneDisplayProps = {}, }) => { const initialRelativeParts = useRef(parseRelativeParts(value)); const { roundUnit } = initialRelativeParts.current; @@ -115,6 +121,7 @@ export const EuiRelativeTab: FunctionComponent = ({ }, [isInvalid, value, roundUp, locale, dateFormat]); const relativeDateInputNumberDescriptionId = useGeneratedHtmlId(); + const timeZomeDescriptionId = useGeneratedHtmlId(); const numberAriaLabel = useEuiI18n( 'euiRelativeTab.numberInputLabel', 'Time span amount' @@ -174,6 +181,7 @@ export const EuiRelativeTab: FunctionComponent = ({ compressed value={formattedValue} readOnly + aria-describedby={timeZomeDescriptionId} prepend={{labelPrefix}} /> @@ -186,6 +194,10 @@ export const EuiRelativeTab: FunctionComponent = ({

+ { + const { euiTheme } = euiThemeContext; + + // This padding should probably not be part of this component to make it really reusable + + return { + euiTimeZoneDisplay: css` + ${logicalCSS('padding-horizontal', euiTheme.size.s)} + ${logicalCSS('padding-bottom', euiTheme.size.s)} + `, + }; +}; diff --git a/packages/eui/src/components/date_picker/super_date_picker/date_popover/timezone_display.test.tsx b/packages/eui/src/components/date_picker/super_date_picker/date_popover/timezone_display.test.tsx new file mode 100644 index 00000000000..0c59ad07b35 --- /dev/null +++ b/packages/eui/src/components/date_picker/super_date_picker/date_popover/timezone_display.test.tsx @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; + +import { render } from '../../../../test/rtl'; + +import { EuiTimeZoneDisplay } from './timezone_display'; + +import { EuiButtonIcon } from '../../../button'; + +describe('EuiTimeZoneDisplay', () => { + it('renders', () => { + const { container } = render( + + ); + + expect(container).toMatchSnapshot(); + }); + + it('handles "Browser" time zone name', () => { + const { getByTestSubject } = render( + + ); + + const browserTimeZone = new Intl.DateTimeFormat().resolvedOptions() + .timeZone; + + expect(getByTestSubject('euiTimeZoneDisplay')).toHaveTextContent( + browserTimeZone + ); + }); + + it('handles "UTC" time zone name', () => { + const { getByTestSubject } = render(); + + // No name displayed between parenthesis, only "UTC" + expect(getByTestSubject('euiTimeZoneDisplay')).toHaveTextContent('UTC'); + }); + + it('does not render with invalid time zone', () => { + const { queryByTestSubject } = render( + + ); + + expect(queryByTestSubject('euiTimeZoneDisplay')).not.toBeInTheDocument(); + }); + + test('timeZoneCustomDisplayRender render function', () => { + const customContent = ( + + ); + + const { getByTestSubject } = render( + ( + <> + {nameDisplay} + {customContent} + + )} + /> + ); + + expect(getByTestSubject('euiTimeZoneDisplay')).toHaveTextContent( + 'Helsinki' + ); + expect(getByTestSubject('customContent')).toBeInTheDocument(); + }); +}); diff --git a/packages/eui/src/components/date_picker/super_date_picker/date_popover/timezone_display.tsx b/packages/eui/src/components/date_picker/super_date_picker/date_popover/timezone_display.tsx new file mode 100644 index 00000000000..acd47c156c5 --- /dev/null +++ b/packages/eui/src/components/date_picker/super_date_picker/date_popover/timezone_display.tsx @@ -0,0 +1,133 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { type ReactNode, type ComponentPropsWithoutRef } from 'react'; +import { Moment } from 'moment'; + +import { euiTimeZoneDisplayStyles } from './timezone_display.styles'; + +import { useEuiMemoizedStyles } from '../../../../services'; +import { EuiFlexGroup } from '../../../flex'; +import { EuiIcon } from '../../../icon'; +import { EuiText } from '../../../text'; + +/** + * Available elements to render passed to the + * `customRender` render function. + */ +type TimeZoneCustomDisplayRenderOptions = { + nameDisplay?: ReactNode; +}; + +export type EuiTimeZoneDisplayProps = ComponentPropsWithoutRef<'div'> & { + /** + * A valid time zone name, from the IANA database, e.g. "America/Los_Angeles". + * + * @link https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + */ + timeZone?: string; + + /** + * Render prop function to add additional content to the time zone display. + * Useful for e.g. adding links to documentation or setting pages. + */ + customRender?: (options: TimeZoneCustomDisplayRenderOptions) => ReactNode; + + /** + * Reference date to be used while resolving the UTC offset. + * Only useful for edge cases involving daylight saving time. + */ + date?: Moment; +}; + +/** + * Display time zone information. + */ +export const EuiTimeZoneDisplay: React.FC = ({ + timeZone, + customRender, + date, + ...rest +}) => { + const color = 'subdued'; + const styles = useEuiMemoizedStyles(euiTimeZoneDisplayStyles); + const referenceDate = date ? date.toDate() : undefined; + const { utc, name, isInvalid } = useEuiUTCOffsetDisplay( + timeZone ?? 'Browser', + referenceDate + ); + + if (!timeZone || isInvalid) return null; + + const label = !name ? utc : `${utc} (${name})`; + const nameDisplay = ( + <> + + + {label} + + + ); + + return ( + + {typeof customRender === 'function' + ? customRender({ nameDisplay }) + : nameDisplay} + + ); +}; + +/** + * Get the UTC offset display in hours e.g. "UTC+2" from time zone name. + * + * @param timeZoneName IANA time zone name + * @param [date] Reference date to get offset with Intl.DateTimeFormat + */ +export function useEuiUTCOffsetDisplay(timeZoneName: string, date?: Date) { + try { + if (timeZoneName === 'UTC') { + return { + utc: 'UTC', + name: '', + isInvalid: false, + }; + } + + const ianaName = + timeZoneName === 'Browser' + ? new Intl.DateTimeFormat().resolvedOptions().timeZone + : timeZoneName; + const formatter = new Intl.DateTimeFormat(undefined, { + timeZone: ianaName, + timeZoneName: 'shortOffset', + }); + const formattedParts = formatter.formatToParts(date ?? new Date()); + const timeZoneNamePart = + formattedParts.find((part) => part.type === 'timeZoneName')?.value || ''; + + return { + utc: timeZoneNamePart.replace('GMT', 'UTC'), + name: ianaName, + isInvalid: false, + }; + } catch (err) { + return { + utc: '', + name: timeZoneName, + isInvalid: true, + }; + } +} diff --git a/packages/eui/src/components/date_picker/super_date_picker/super_date_picker.stories.tsx b/packages/eui/src/components/date_picker/super_date_picker/super_date_picker.stories.tsx index d70ffe34b5c..2b48127b9e4 100644 --- a/packages/eui/src/components/date_picker/super_date_picker/super_date_picker.stories.tsx +++ b/packages/eui/src/components/date_picker/super_date_picker/super_date_picker.stories.tsx @@ -28,6 +28,7 @@ import { } from './super_date_picker'; import { EuiFieldText } from '../../form'; import { EuiFlexGroup } from '../../flex'; +import { EuiButtonIcon } from '../../button'; const meta: Meta = { title: 'Forms/EuiSuperDatePicker/EuiSuperDatePicker', @@ -72,6 +73,7 @@ const meta: Meta = { commonlyUsedRanges: [{ start: 'now/d', end: 'now/d', label: 'Today' }], maxDate: undefined, minDate: undefined, + timeZoneDisplayProps: { timeZone: 'Browser' }, }, }; enableFunctionToggleControls(meta, ['onTimeChange']); @@ -198,6 +200,48 @@ export const TimeWindowButtons: Story = { render: (args) => , }; +export const CustomTimeZoneDisplay: Story = { + parameters: { + controls: { + include: ['timeZoneDisplayProps'], + }, + loki: { + chromeSelector: LOKI_SELECTORS.portal, + }, + }, + args: { + timeZoneDisplayProps: { + timeZone: 'America/Los_Angeles', + customRender: ({ nameDisplay }) => ( + <> + {nameDisplay} + + + ), + }, + }, + render: (args) => , + play: async ({ canvasElement, step }) => { + const canvas = within(canvasElement); + + await step('show popover on click of the date picker button', async () => { + await fireEvent.click( + canvas.getByTestSubject('superDatePickerShowDatesButton') + ); + + await canvas.waitForEuiPopoverVisible(); + + expect(await canvas.findByText(/Los_Angeles/)).toBeVisible(); + }); + }, +}; + /** * VRT only */ diff --git a/packages/eui/src/components/date_picker/super_date_picker/super_date_picker.tsx b/packages/eui/src/components/date_picker/super_date_picker/super_date_picker.tsx index 68e130e31d2..4b8128d4d5f 100644 --- a/packages/eui/src/components/date_picker/super_date_picker/super_date_picker.tsx +++ b/packages/eui/src/components/date_picker/super_date_picker/super_date_picker.tsx @@ -55,6 +55,7 @@ import { EuiQuickSelectButtonProps, } from './quick_select_popover/quick_select_popover'; import { EuiDatePopoverButton } from './date_popover/date_popover_button'; +import { type EuiTimeZoneDisplayProps } from './date_popover/timezone_display'; import { EuiDatePopoverContentProps } from './date_popover/date_popover_content'; import { @@ -234,6 +235,15 @@ export type EuiSuperDatePickerProps = CommonProps & { * input by the user, set this flag to `false`. */ canRoundRelativeUnits?: boolean; + + /** + * Props passed to the time zone display in the popovers {@link EuiTimeZoneDisplayProps} + * + * Setting `timeZoneDisplayProps.timeZone` with a valid time zone name will make + * the time zone information be visible below the start and end input fields. + * This is informational only, it will not affect how date/times are handled. + */ + timeZoneDisplayProps?: EuiTimeZoneDisplayProps; }; type EuiSuperDatePickerInternalProps = EuiSuperDatePickerProps & { @@ -575,6 +585,7 @@ export class EuiSuperDatePickerInternal extends Component< compressed, onFocus, memoizedStyles: styles, + timeZoneDisplayProps = {}, } = this.props; const autoRefreshAppend: EuiFormControlLayoutProps['append'] = !isPaused ? ( @@ -690,6 +701,7 @@ export class EuiSuperDatePickerInternal extends Component< onPopoverClose={this.onStartDatePopoverClose} timeOptions={timeOptions} buttonProps={{ onFocus }} + timeZoneDisplayProps={timeZoneDisplayProps} /> ) } @@ -717,6 +729,7 @@ export class EuiSuperDatePickerInternal extends Component< onPopoverClose={this.onEndDatePopoverClose} timeOptions={timeOptions} buttonProps={{ onFocus }} + timeZoneDisplayProps={timeZoneDisplayProps} /> ) } diff --git a/packages/eui/src/components/date_picker/super_date_picker/time_window_buttons.test.tsx b/packages/eui/src/components/date_picker/super_date_picker/time_window_buttons.test.tsx index 0be19f9c9e4..18d985db9ef 100644 --- a/packages/eui/src/components/date_picker/super_date_picker/time_window_buttons.test.tsx +++ b/packages/eui/src/components/date_picker/super_date_picker/time_window_buttons.test.tsx @@ -10,12 +10,7 @@ import moment from 'moment'; import { act, fireEvent } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { - render, - renderHook, - renderHookAct, - waitForEuiToolTipVisible, -} from '../../../test/rtl'; +import { render, renderHook, renderHookAct } from '../../../test/rtl'; import { TimeWindowButtons, @@ -188,7 +183,7 @@ describe('TimeWindowButtons', () => { const start = 'not a date'; const end = 'now'; - const { getByTestSubject, getByRole } = render( + const { getByTestSubject, findByText } = render( ); @@ -200,9 +195,12 @@ describe('TimeWindowButtons', () => { expect(apply).not.toHaveBeenCalled(); - fireEvent.mouseEnter(getByTestSubject('timeWindowButtonsZoomOut')); - await waitForEuiToolTipVisible(); + act(() => { + fireEvent.mouseEnter(getByTestSubject('timeWindowButtonsZoomOut')); + }); - expect(getByRole('tooltip')).toHaveTextContent(/Cannot/); + expect( + await findByText('Cannot zoom out invalid time window') + ).toBeInTheDocument(); }); }); diff --git a/packages/eui/src/components/date_picker/super_date_picker/time_window_buttons.tsx b/packages/eui/src/components/date_picker/super_date_picker/time_window_buttons.tsx index 38e0a2e68ba..69714faca19 100644 --- a/packages/eui/src/components/date_picker/super_date_picker/time_window_buttons.tsx +++ b/packages/eui/src/components/date_picker/super_date_picker/time_window_buttons.tsx @@ -48,6 +48,7 @@ export type TimeWindowButtonsProps = TimeWindowButtonsConfig & { isDisabled?: boolean; }; +// TODO rename to add eui prefix e.g. EuiTimeWindowButtons /** * Button group with time window controls for shifting the time window * forwards and backwards, and zooming out. diff --git a/packages/website/docs/components/forms/date-and-time/super-date-picker.mdx b/packages/website/docs/components/forms/date-and-time/super-date-picker.mdx index 5323c51e36b..a20e08aa14b 100644 --- a/packages/website/docs/components/forms/date-and-time/super-date-picker.mdx +++ b/packages/website/docs/components/forms/date-and-time/super-date-picker.mdx @@ -851,6 +851,67 @@ export default () => { }; ``` +## Time zone display + +Time zone information can be made visible in the date picker popovers. To do that, pass the time zone name in `timeZoneDisplayProps` e.g. `timeZoneDisplayProps={{ timeZone: "America/Los_Angeles" }}`. + +Additionally, custom content can be added to the time zone information by leveraging the `customRender` render function in `timeZoneDisplayProps`. + +:::note This is informational only, it **will not** affect how dates are handled internally by the component + +::: + +```tsx interactive +import React, { useState } from "react"; +import { + EuiSuperDatePicker, + EuiButtonIcon, + OnTimeChangeProps, +} from "@elastic/eui"; + +export default () => { + const [start, setStart] = useState("now-15m"); + const [end, setEnd] = useState("now"); + + const TIME_ZONE_NAME = "Browser"; + + const onTimeChange = ({ start, end }: OnTimeChangeProps) => { + setStart(start); + setEnd(end); + }; + + const customButton = ( + + ); + + return ( + <> + ( + <> + {nameDisplay} + {customButton} + + ), + }} + /> + + ); +}; +``` + ## Restricted range To limit the range from which users can choose a date, you can use `minDate` and `maxDate`. By updating the date input values for `start` and `end`, users get immediate feedback on what range values are allowed.