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
+ },
+};