diff --git a/packages/eui/.loki/reference/chrome_desktop_Display_EuiGlobalToastList_EuiGlobalToastListItem_Playground.png b/packages/eui/.loki/reference/chrome_desktop_Display_EuiGlobalToastList_EuiGlobalToastListItem_Playground.png new file mode 100644 index 00000000000..0195eb0e3f3 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Display_EuiGlobalToastList_EuiGlobalToastListItem_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Display_EuiGlobalToastList_EuiGlobalToastList_Playground.png b/packages/eui/.loki/reference/chrome_desktop_Display_EuiGlobalToastList_EuiGlobalToastList_Playground.png new file mode 100644 index 00000000000..8e9c2410b25 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Display_EuiGlobalToastList_EuiGlobalToastList_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItemEvent_Playground.png b/packages/eui/.loki/reference/chrome_desktop_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItemEvent_Playground.png new file mode 100644 index 00000000000..68076f5684a Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItemEvent_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItemIcon_Playground.png b/packages/eui/.loki/reference/chrome_desktop_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItemIcon_Playground.png new file mode 100644 index 00000000000..8d2c84571d0 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItemIcon_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItem_Playground.png b/packages/eui/.loki/reference/chrome_desktop_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItem_Playground.png new file mode 100644 index 00000000000..5cad6a358a7 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItem_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Display_EuiTimeline_EuiTimeline_Playground.png b/packages/eui/.loki/reference/chrome_desktop_Display_EuiTimeline_EuiTimeline_Playground.png new file mode 100644 index 00000000000..d07a11f2258 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Display_EuiTimeline_EuiTimeline_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Display_EuiToast_Playground.png b/packages/eui/.loki/reference/chrome_desktop_Display_EuiToast_Playground.png new file mode 100644 index 00000000000..ba6832c5ba6 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Display_EuiToast_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiStepNumber_Playground.png b/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiStepNumber_Playground.png new file mode 100644 index 00000000000..7bf02caf777 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiStepNumber_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiStepsHorizontal_EuiStepHorizontal_Playground.png b/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiStepsHorizontal_EuiStepHorizontal_Playground.png new file mode 100644 index 00000000000..3d640acae97 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiStepsHorizontal_EuiStepHorizontal_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiStepsHorizontal_EuiStepsHorizontal_Playground.png b/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiStepsHorizontal_EuiStepsHorizontal_Playground.png new file mode 100644 index 00000000000..40d8b72fb70 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiStepsHorizontal_EuiStepsHorizontal_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiSteps_EuiStep_Playground.png b/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiSteps_EuiStep_Playground.png new file mode 100644 index 00000000000..734ca8d2edd Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiSteps_EuiStep_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiSteps_Playground.png b/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiSteps_Playground.png new file mode 100644 index 00000000000..1f3f7c6e2a6 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiSteps_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiSubSteps_Playground.png b/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiSubSteps_Playground.png new file mode 100644 index 00000000000..86bfd32a537 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_desktop_Navigation_EuiSteps_EuiSubSteps_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Display_EuiGlobalToastList_EuiGlobalToastListItem_Playground.png b/packages/eui/.loki/reference/chrome_mobile_Display_EuiGlobalToastList_EuiGlobalToastListItem_Playground.png new file mode 100644 index 00000000000..dff08f1bf73 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Display_EuiGlobalToastList_EuiGlobalToastListItem_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Display_EuiGlobalToastList_EuiGlobalToastList_Playground.png b/packages/eui/.loki/reference/chrome_mobile_Display_EuiGlobalToastList_EuiGlobalToastList_Playground.png new file mode 100644 index 00000000000..42568ee57fe Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Display_EuiGlobalToastList_EuiGlobalToastList_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItemEvent_Playground.png b/packages/eui/.loki/reference/chrome_mobile_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItemEvent_Playground.png new file mode 100644 index 00000000000..abe37e4d208 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItemEvent_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItemIcon_Playground.png b/packages/eui/.loki/reference/chrome_mobile_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItemIcon_Playground.png new file mode 100644 index 00000000000..9c2ccab6d4f Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItemIcon_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItem_Playground.png b/packages/eui/.loki/reference/chrome_mobile_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItem_Playground.png new file mode 100644 index 00000000000..a2c405d24d5 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Display_EuiTimeline_EuiTimelineItem_EuiTimelineItem_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Display_EuiTimeline_EuiTimeline_Playground.png b/packages/eui/.loki/reference/chrome_mobile_Display_EuiTimeline_EuiTimeline_Playground.png new file mode 100644 index 00000000000..9a7149bc669 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Display_EuiTimeline_EuiTimeline_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Display_EuiToast_Playground.png b/packages/eui/.loki/reference/chrome_mobile_Display_EuiToast_Playground.png new file mode 100644 index 00000000000..21f6ca86e3b Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Display_EuiToast_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiStepNumber_Playground.png b/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiStepNumber_Playground.png new file mode 100644 index 00000000000..e664d626483 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiStepNumber_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiStepsHorizontal_EuiStepHorizontal_Playground.png b/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiStepsHorizontal_EuiStepHorizontal_Playground.png new file mode 100644 index 00000000000..19250c6d35a Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiStepsHorizontal_EuiStepHorizontal_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiStepsHorizontal_EuiStepsHorizontal_Playground.png b/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiStepsHorizontal_EuiStepsHorizontal_Playground.png new file mode 100644 index 00000000000..4ee49045ca0 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiStepsHorizontal_EuiStepsHorizontal_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiSteps_EuiStep_Playground.png b/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiSteps_EuiStep_Playground.png new file mode 100644 index 00000000000..afc41cb47d5 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiSteps_EuiStep_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiSteps_Playground.png b/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiSteps_Playground.png new file mode 100644 index 00000000000..51fcd27407a Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiSteps_Playground.png differ diff --git a/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiSubSteps_Playground.png b/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiSubSteps_Playground.png new file mode 100644 index 00000000000..f5ddc9f7603 Binary files /dev/null and b/packages/eui/.loki/reference/chrome_mobile_Navigation_EuiSteps_EuiSubSteps_Playground.png differ diff --git a/packages/eui/changelogs/upcoming/7732.md b/packages/eui/changelogs/upcoming/7732.md new file mode 100644 index 00000000000..c38e7a34ca2 --- /dev/null +++ b/packages/eui/changelogs/upcoming/7732.md @@ -0,0 +1 @@ +- Updated `EuiSuperDatePicker`'s absolute tab UX to support setting manual timestamps via mouse click as well as enter key diff --git a/packages/eui/src/components/date_picker/super_date_picker/date_popover/_absolute_tab.scss b/packages/eui/src/components/date_picker/super_date_picker/date_popover/_absolute_tab.scss index 58db086692a..9e86650d7e2 100644 --- a/packages/eui/src/components/date_picker/super_date_picker/date_popover/_absolute_tab.scss +++ b/packages/eui/src/components/date_picker/super_date_picker/date_popover/_absolute_tab.scss @@ -1,24 +1,19 @@ -.euiSuperDatePicker__absoluteDateFormRow { +.euiSuperDatePicker__absoluteDateForm { padding: 0 $euiSizeS $euiSizeS; +} - /* A bit of a visual trickery to make the format "hint" become an "error" text. - NOTE: Normally reordering visually (vs DOM) isn't super great for screen reader users, - but as the help text is already read out via `aria-describedby`, and the error text - is read out immediately via `aria-live`, we can fairly safely prioritize visuals instead */ - .euiFormRow__fieldWrapper { - display: flex; - flex-direction: column; - }; - - .euiFormControlLayout { - order: 0; - } +.euiSuperDatePicker__absoluteDateFormSubmit { + flex-shrink: 0; +} - .euiFormHelpText { - order: 1; - } +.euiSuperDatePicker__absoluteDateFormRow { + flex-grow: 1; - .euiFormErrorText { - order: 2; + // CSS hack to make the help/error text extend to the submit button. + // We can't actually put the submit button within an EuiFormRow due to + // cloneElement limitations (https://github.com/elastic/eui/issues/2493#issuecomment-561278494) + // TODO: Remove this and clean up DOM rendering once we can + .euiFormRow__text { + margin-inline-end: -1 * ($euiSizeXL + $euiSizeS); // XL - size of the button, S - size of the flex gap } } 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 0a6ef20758f..10f49342d61 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 @@ -36,35 +36,40 @@ describe('EuiAbsoluteTab', () => { }; describe('user input', () => { - it('displays the enter key help text when the input has been edited and the date has not yet been parsed', () => { - const { getByTestSubject, queryByText } = render( + const formatHelpText = /Allowed formats: /; + + it('displays helptext and a submit button when the input has been edited and the date has not yet been parsed', () => { + const { getByTestSubject, queryByTestSubject, queryByText } = render( ); - const helpText = 'Press the Enter key to parse as a date.'; - expect(queryByText(helpText)).not.toBeInTheDocument(); + expect(queryByText(formatHelpText)).not.toBeInTheDocument(); + expect( + queryByTestSubject('parseAbsoluteDateFormat') + ).not.toBeInTheDocument(); const input = getByTestSubject('superDatePickerAbsoluteDateInput'); fireEvent.change(input, { target: { value: 'test' } }); - expect(queryByText(helpText)).toBeInTheDocument(); + expect(queryByText(formatHelpText)).toBeInTheDocument(); + expect(queryByTestSubject('parseAbsoluteDateFormat')).toBeInTheDocument(); }); it('displays the formats as a hint before parse, but as an error if invalid', () => { const { getByTestSubject, queryByText } = render( ); - const formatHelpText = /Allowed formats: /; expect(queryByText(formatHelpText)).not.toBeInTheDocument(); - const input = getByTestSubject('superDatePickerAbsoluteDateInput'); - fireEvent.change(input, { target: { value: 'test' } }); + fireEvent.change(getByTestSubject('superDatePickerAbsoluteDateInput'), { + target: { value: 'test' }, + }); expect(queryByText(formatHelpText)).toHaveClass('euiFormHelpText'); - fireEvent.keyDown(input, { key: 'Enter' }); + fireEvent.click(getByTestSubject('parseAbsoluteDateFormat')); expect(queryByText(formatHelpText)).toHaveClass('euiFormErrorText'); }); - it('immediately parses pasted text without needing an extra enter keypress', () => { + it('immediately parses pasted text without needing an extra click or keypress', () => { const { getByTestSubject, queryByText } = render( ); @@ -84,15 +89,14 @@ describe('EuiAbsoluteTab', () => { }); expect(input).toBeInvalid(); - expect(queryByText(/Allowed formats: /)).toBeInTheDocument(); - expect(queryByText(/Press the Enter key /)).not.toBeInTheDocument(); + expect(queryByText(formatHelpText)).toBeInTheDocument(); }); }); describe('date parsing', () => { const changeInput = (input: HTMLElement, value: string) => { - fireEvent.change(input, { target: { value } }); - fireEvent.keyDown(input, { key: 'Enter' }); + fireEvent.change(input, { target: { value: `${value}` } }); + fireEvent.submit(input.closest('form')!); }; it('parses the passed `dateFormat` prop', () => { 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 a0cd792a165..69035c0d22c 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 @@ -6,14 +6,15 @@ * Side Public License, v 1. */ -import React, { Component, ChangeEvent } from 'react'; +import React, { Component, ChangeEvent, FormEvent } from 'react'; import moment, { Moment, LocaleSpecifier } from 'moment'; // eslint-disable-line import/named import dateMath from '@elastic/datemath'; -import { keys } from '../../../../services'; import { EuiFormRow, EuiFieldText, EuiFormLabel } from '../../../form'; +import { EuiFlexGroup } from '../../../flex'; +import { EuiButtonIcon } from '../../../button'; import { EuiCode } from '../../../code'; import { EuiI18n } from '../../../i18n'; @@ -167,45 +168,63 @@ export class EuiAbsoluteTab extends Component< /> {dateFormat} }} > - {([dateFormatHint, dateFormatError]: string[]) => ( - ( + { + e.preventDefault(); // Prevents a page refresh/reload + this.parseUserDateInput(textInputValue); + }} + className="euiSuperDatePicker__absoluteDateForm" + gutterSize="s" + responsive={false} > - { - this.parseUserDateInput(event.clipboardData.getData('text')); - }} - onKeyDown={(event) => { - if (event.key === keys.ENTER) { - this.parseUserDateInput(textInputValue); - } - }} - data-test-subj="superDatePickerAbsoluteDateInput" - prepend={{labelPrefix}} - /> - + error={isTextInvalid ? dateFormatError : undefined} + helpText={ + hasUnparsedText && !isTextInvalid + ? dateFormatError + : undefined + } + > + { + this.parseUserDateInput( + event.clipboardData.getData('text') + ); + }} + data-test-subj="superDatePickerAbsoluteDateInput" + prepend={{labelPrefix}} + /> + + {hasUnparsedText && ( + + )} + )} diff --git a/packages/eui/src/components/steps/step.stories.tsx b/packages/eui/src/components/steps/step.stories.tsx new file mode 100644 index 00000000000..5d04e8b1342 --- /dev/null +++ b/packages/eui/src/components/steps/step.stories.tsx @@ -0,0 +1,37 @@ +/* + * 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 type { Meta, StoryObj } from '@storybook/react'; + +import { hideStorybookControls } from '../../../.storybook/utils'; +import { STATUS } from './step_number'; +import { EuiStep, EuiStepProps } from './step'; + +const meta: Meta = { + title: 'Navigation/EuiSteps/EuiSteps/EuiStep', + component: EuiStep, + argTypes: { + status: { options: [undefined, ...STATUS] }, + }, + args: { + headingElement: 'p', + titleSize: 's', + step: 1, + }, +}; +hideStorybookControls(meta, ['aria-label']); + +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + args: { + title: 'Step 1', + children: 'lorem ipsum', + }, +}; diff --git a/packages/eui/src/components/steps/step_horizontal.stories.tsx b/packages/eui/src/components/steps/step_horizontal.stories.tsx new file mode 100644 index 00000000000..b94c66699c5 --- /dev/null +++ b/packages/eui/src/components/steps/step_horizontal.stories.tsx @@ -0,0 +1,39 @@ +/* + * 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 type { Meta, StoryObj } from '@storybook/react'; + +import { + enableFunctionToggleControls, + hideStorybookControls, +} from '../../../.storybook/utils'; +import { EuiStepHorizontal, EuiStepHorizontalProps } from './step_horizontal'; + +const meta: Meta = { + title: 'Navigation/EuiSteps/EuiStepsHorizontal/EuiStepHorizontal', + component: EuiStepHorizontal, + args: { + size: 'm', + step: 1, + status: 'incomplete', + // set up for easier testing/QA + disabled: false, + }, +}; +hideStorybookControls(meta, ['aria-label']); +enableFunctionToggleControls(meta, ['onClick']); + +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + args: { + title: 'Step 1', + children: 'lorem ipsum', + }, +}; diff --git a/packages/eui/src/components/steps/step_number.stories.tsx b/packages/eui/src/components/steps/step_number.stories.tsx new file mode 100644 index 00000000000..4b61359ab26 --- /dev/null +++ b/packages/eui/src/components/steps/step_number.stories.tsx @@ -0,0 +1,33 @@ +/* + * 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 type { Meta, StoryObj } from '@storybook/react'; + +import { hideStorybookControls } from '../../../.storybook/utils'; +import { EuiStepNumber, EuiStepNumberProps, STATUS } from './step_number'; + +const meta: Meta = { + title: 'Navigation/EuiSteps/Subcomponents/EuiStepNumber', + component: EuiStepNumber, + argTypes: { + status: { options: [undefined, ...STATUS] }, + }, + args: { + titleSize: 's', + }, +}; +hideStorybookControls(meta, ['aria-label']); + +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + args: { + number: 1, + }, +}; diff --git a/packages/eui/src/components/steps/steps.stories.tsx b/packages/eui/src/components/steps/steps.stories.tsx new file mode 100644 index 00000000000..45f21b860c1 --- /dev/null +++ b/packages/eui/src/components/steps/steps.stories.tsx @@ -0,0 +1,76 @@ +/* + * 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 type { Meta, StoryObj } from '@storybook/react'; + +import { moveStorybookControlsToCategory } from '../../../.storybook/utils'; +import { EuiSteps, EuiStepsProps } from './steps'; + +const meta: Meta = { + title: 'Navigation/EuiSteps/EuiSteps', + component: EuiSteps, + args: { + firstStepNumber: 1, + headingElement: 'p', + titleSize: 's', + }, +}; +moveStorybookControlsToCategory( + meta, + ['headingElement', 'titleSize'], + 'EuiStep props' +); + +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + args: { + steps: [ + { + title: 'Step 1', + children: 'lorem ipsum', + }, + { + title: 'Step 2', + children: 'lorem ipsum', + status: 'current', + }, + { + title: 'Step 3', + children: 'lorem ipsum', + status: 'complete', + }, + { + title: 'Step 4', + children: 'lorem ipsum', + status: 'incomplete', + }, + { + title: 'Step 5', + children: 'lorem ipsum', + status: 'warning', + }, + { + title: 'Step 6', + children: 'lorem ipsum', + status: 'danger', + }, + { + title: 'Step 7', + children: 'lorem ipsum', + status: 'loading', + }, + { + title: 'Step 8', + children: 'lorem ipsum', + status: 'disabled', + }, + ], + }, +}; diff --git a/packages/eui/src/components/steps/steps_horizontal.stories.tsx b/packages/eui/src/components/steps/steps_horizontal.stories.tsx new file mode 100644 index 00000000000..2c9846d309a --- /dev/null +++ b/packages/eui/src/components/steps/steps_horizontal.stories.tsx @@ -0,0 +1,76 @@ +/* + * 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 type { Meta, StoryObj } from '@storybook/react'; +import { action } from '@storybook/addon-actions'; + +import { moveStorybookControlsToCategory } from '../../../.storybook/utils'; +import { + EuiStepsHorizontal, + EuiStepsHorizontalProps, +} from './steps_horizontal'; + +const meta: Meta = { + title: 'Navigation/EuiSteps/EuiStepsHorizontal', + component: EuiStepsHorizontal, + args: { + size: 'm', + }, +}; +moveStorybookControlsToCategory(meta, ['size'], 'EuiStepHorizontal props'); + +export default meta; +type Story = StoryObj; + +const onClick = action('onClick'); + +export const Playground: Story = { + args: { + steps: [ + { + title: 'Step 1', + onClick, + }, + { + title: 'Step 2', + status: 'current', + onClick, + }, + { + title: 'Step 3', + status: 'complete', + onClick, + }, + { + title: 'Step 4', + status: 'incomplete', + onClick, + }, + { + title: 'Step 5', + status: 'warning', + onClick, + }, + { + title: 'Step 6', + status: 'danger', + onClick, + }, + { + title: 'Step 7', + status: 'loading', + onClick, + }, + { + title: 'Step 8', + status: 'disabled', + onClick, + }, + ], + }, +}; diff --git a/packages/eui/src/components/steps/sub_steps.stories.tsx b/packages/eui/src/components/steps/sub_steps.stories.tsx new file mode 100644 index 00000000000..279ec176869 --- /dev/null +++ b/packages/eui/src/components/steps/sub_steps.stories.tsx @@ -0,0 +1,25 @@ +/* + * 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 type { Meta, StoryObj } from '@storybook/react'; + +import { EuiSubSteps, EuiSubStepsProps } from './sub_steps'; + +const meta: Meta = { + title: 'Navigation/EuiSteps/Subcomponents/EuiSubSteps', + component: EuiSubSteps, +}; + +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + args: { + children: 'lorem ipsum dolor sit', + }, +}; diff --git a/packages/eui/src/components/timeline/timeline.stories.tsx b/packages/eui/src/components/timeline/timeline.stories.tsx new file mode 100644 index 00000000000..486926538f3 --- /dev/null +++ b/packages/eui/src/components/timeline/timeline.stories.tsx @@ -0,0 +1,46 @@ +/* + * 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 type { Meta, StoryObj } from '@storybook/react'; + +import { EuiTimeline, EuiTimelineProps } from './timeline'; + +const meta: Meta = { + title: 'Display/EuiTimeline/EuiTimeline', + component: EuiTimeline, + args: { + gutterSize: 'xl', + }, +}; + +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + args: { + items: [ + { + icon: 'pencil', + children: 'Project renamed to "Revenue Dashboard".', + }, + { + icon: 'email', + children: ( + <> + dev@elastic.co was invited to the project. + + ), + }, + { + icon: 'folderClosed', + children: 'The project was archived.', + }, + ], + }, +}; diff --git a/packages/eui/src/components/timeline/timeline_item.stories.tsx b/packages/eui/src/components/timeline/timeline_item.stories.tsx new file mode 100644 index 00000000000..c34514678c4 --- /dev/null +++ b/packages/eui/src/components/timeline/timeline_item.stories.tsx @@ -0,0 +1,48 @@ +/* + * 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 type { Meta, StoryObj } from '@storybook/react'; + +import { EuiTimelineItem, EuiTimelineItemProps } from './timeline_item'; + +const meta: Meta = { + title: 'Display/EuiTimeline/EuiTimelineItem/EuiTimelineItem', + component: EuiTimelineItem, + argTypes: { + // re-adding type descriptions that are not resolved (removed in Omit<> type) + children: { + description: 'Accepts any node. But preferably `EuiPanel`', + // @ts-ignore - overwritting to ensure correct expected type + type: 'ReactNode', + }, + icon: { + description: + "Any `ReactNode`, but preferably `EuiAvatar`, or a string as an `EuiIcon['type']`.", + // @ts-ignore - overwritting to ensure correct expected type + type: 'ReactNode | IconType', + }, + iconAriaLabel: { + description: + 'Specify an `aria-label` for the icon when passed as an `IconType`. If no `aria-label` is passed we assume the icon is purely decorative.', + }, + }, + args: { + verticalAlign: 'center', + iconAriaLabel: '', + }, +}; + +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + args: { + children: 'timeline item', + icon: 'email', + }, +}; diff --git a/packages/eui/src/components/timeline/timeline_item_event.stories.tsx b/packages/eui/src/components/timeline/timeline_item_event.stories.tsx new file mode 100644 index 00000000000..1cbe1aaa35f --- /dev/null +++ b/packages/eui/src/components/timeline/timeline_item_event.stories.tsx @@ -0,0 +1,39 @@ +/* + * 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 type { Meta, StoryObj } from '@storybook/react'; + +import { + EuiTimelineItemEvent, + EuiTimelineItemEventProps, +} from './timeline_item_event'; + +const meta: Meta = { + title: 'Display/EuiTimeline/EuiTimelineItem/EuiTimelineItemEvent', + component: EuiTimelineItemEvent, + decorators: [ + (Story, { args }) => ( +
+ +
+ ), + ], + args: { + verticalAlign: 'center', + }, +}; + +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + args: { + children: 'timeline item event', + }, +}; diff --git a/packages/eui/src/components/timeline/timeline_item_icon.stories.tsx b/packages/eui/src/components/timeline/timeline_item_icon.stories.tsx new file mode 100644 index 00000000000..c938ebff92f --- /dev/null +++ b/packages/eui/src/components/timeline/timeline_item_icon.stories.tsx @@ -0,0 +1,39 @@ +/* + * 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 type { Meta, StoryObj } from '@storybook/react'; + +import { + EuiTimelineItemIcon, + EuiTimelineItemIconProps, +} from './timeline_item_icon'; + +const meta: Meta = { + title: 'Display/EuiTimeline/EuiTimelineItem/EuiTimelineItemIcon', + component: EuiTimelineItemIcon, + decorators: [ + (Story, { args }) => ( +
+ +
+ ), + ], + args: { + verticalAlign: 'center', + }, +}; + +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + args: { + icon: 'email', + }, +}; diff --git a/packages/eui/src/components/toast/global_toast_list.stories.tsx b/packages/eui/src/components/toast/global_toast_list.stories.tsx new file mode 100644 index 00000000000..5eaeed9e86a --- /dev/null +++ b/packages/eui/src/components/toast/global_toast_list.stories.tsx @@ -0,0 +1,99 @@ +/* + * 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, { useState } from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; + +import { enableFunctionToggleControls } from '../../../.storybook/utils'; +import { EuiButton } from '../button'; +import { + EuiGlobalToastList, + EuiGlobalToastListProps, + Toast, +} from './global_toast_list'; + +const staticToasts: Toast[] = [ + { + id: 'static-toast-1', + title: 'Hello from Toast!', + text: 'toast message', + color: 'success' as const, + }, + { + id: 'static-toast-2', + title: 'Warning from Toast!', + text: 'toast message', + color: 'warning' as const, + iconType: 'warning', + }, +]; + +const meta: Meta = { + title: 'Display/EuiToast/EuiGlobalToastList/EuiGlobalToastList', + component: EuiGlobalToastList, + argTypes: { + role: { control: { type: 'select' }, options: ['log', 'alert'] }, + showClearAllButtonAt: { control: { type: 'number', min: 0 } }, + }, + args: { + role: 'log', + side: 'right', + showClearAllButtonAt: 3, + // stub for testing/QA + dismissToast: () => {}, + }, +}; +enableFunctionToggleControls(meta, ['onClearAllToasts']); + +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + args: { + toasts: [staticToasts[0]], + toastLifeTimeMs: 15000, + }, + render: (args) => , +}; + +let toastId = 0; + +const StatefulGlobalToastList = ({ + toasts, + dismissToast, + ...rest +}: EuiGlobalToastListProps) => { + const [_toasts, setToasts] = useState(toasts ?? []); + + const handleAddToast = () => { + const randomToast = { + ...staticToasts[Math.floor(Math.random() * staticToasts.length)], + id: `toast-${toastId}`, + }; + + toastId += 1; + setToasts((prevToasts) => [...prevToasts, randomToast]); + }; + + const handleRemoveToast = (removedToast: Toast) => { + setToasts((prevToasts) => + prevToasts.filter((toast) => toast.id !== removedToast.id) + ); + }; + + return ( + <> + Add toast + + + ); +}; diff --git a/packages/eui/src/components/toast/global_toast_list_item.stories.tsx b/packages/eui/src/components/toast/global_toast_list_item.stories.tsx new file mode 100644 index 00000000000..9b311bde40d --- /dev/null +++ b/packages/eui/src/components/toast/global_toast_list_item.stories.tsx @@ -0,0 +1,35 @@ +/* + * 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 type { Meta, StoryObj } from '@storybook/react'; + +import { hideStorybookControls } from '../../../.storybook/utils'; +import { EuiToast } from './toast'; +import { + EuiGlobalToastListItem, + EuiGlobalToastListItemProps, +} from './global_toast_list_item'; + +const meta: Meta = { + title: 'Display/EuiToast/EuiGlobalToastList/EuiGlobalToastListItem', + component: EuiGlobalToastListItem, + args: { + isDismissed: false, + }, +}; +hideStorybookControls(meta, ['aria-label']); + +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + args: { + children: Lorem ipsum, + }, +}; diff --git a/packages/eui/src/components/toast/global_toast_list_item.tsx b/packages/eui/src/components/toast/global_toast_list_item.tsx index 25eeb345a17..d9b0a942876 100644 --- a/packages/eui/src/components/toast/global_toast_list_item.tsx +++ b/packages/eui/src/components/toast/global_toast_list_item.tsx @@ -12,7 +12,7 @@ import { useEuiTheme, cloneElementWithCss } from '../../services'; import { CommonProps } from '../common'; import { euiGlobalToastListItemStyles } from './global_toast_list.styles'; -export interface EuiGlobalToastListItemProps { +export interface EuiGlobalToastListItemProps extends CommonProps { isDismissed?: boolean; /** * ReactElement to render as this component's content @@ -21,7 +21,7 @@ export interface EuiGlobalToastListItemProps { } export const EuiGlobalToastListItem: FunctionComponent< - CommonProps & EuiGlobalToastListItemProps + EuiGlobalToastListItemProps > = ({ children, className, isDismissed }) => { const euiTheme = useEuiTheme(); if (!children) { diff --git a/packages/eui/src/components/toast/toast.stories.tsx b/packages/eui/src/components/toast/toast.stories.tsx new file mode 100644 index 00000000000..9b93f321fc5 --- /dev/null +++ b/packages/eui/src/components/toast/toast.stories.tsx @@ -0,0 +1,49 @@ +/* + * 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 type { Meta, StoryObj } from '@storybook/react'; + +import { + enableFunctionToggleControls, + hideStorybookControls, +} from '../../../.storybook/utils'; +import { EuiToast, EuiToastProps, COLORS } from './toast'; + +const meta: Meta = { + title: 'Display/EuiToast', + component: EuiToast, + argTypes: { + children: { + control: 'text', + // @ts-ignore - overwritten to output proper type as inferred type is not correct + type: 'ReactNode', + }, + color: { control: 'select', options: [undefined, ...COLORS] }, + title: { control: 'text' }, + iconType: { control: 'text' }, + }, + args: { + // set up for easier testing/QA + title: '', + iconType: '', + }, +}; +enableFunctionToggleControls(meta, ['onClose']); +hideStorybookControls(meta, ['aria-label']); + +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + args: { + title: "It's a Toast!", + children: 'Toast content', + // @ts-ignore - using story specific types + onClose: false, // overwriting to false to mimick the default state without close button + }, +};