From 9554450446f41878cb198b66ff0ca18986da1908 Mon Sep 17 00:00:00 2001
From: Cee Chen <549407+cee-chen@users.noreply.github.com>
Date: Tue, 3 Oct 2023 11:10:19 -0700
Subject: [PATCH 01/38] [EuiCollapsibleNavBeta] Add global CSS variable for
width offset (#7248)
---
.../collapsible_nav_beta.stories.tsx | 19 +++++++++++++++++++
.../collapsible_nav_beta.tsx | 18 ++++++++++++++++--
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/src/components/collapsible_nav_beta/collapsible_nav_beta.stories.tsx b/src/components/collapsible_nav_beta/collapsible_nav_beta.stories.tsx
index b8a21163188..15c1b1148f7 100644
--- a/src/components/collapsible_nav_beta/collapsible_nav_beta.stories.tsx
+++ b/src/components/collapsible_nav_beta/collapsible_nav_beta.stories.tsx
@@ -11,6 +11,7 @@ import type { Meta, StoryObj } from '@storybook/react';
import { EuiHeader, EuiHeaderSection, EuiHeaderSectionItem } from '../header';
import { EuiPageTemplate } from '../page_template';
+import { EuiBottomBar } from '../bottom_bar';
import { EuiFlyout } from '../flyout';
import { EuiButton } from '../button';
import { EuiTitle } from '../title';
@@ -469,6 +470,24 @@ export const FlyoutInFixedHeaders: Story = {
},
};
+export const GlobalCSSVariable: Story = {
+ render: ({ ...args }) => (
+ <>
+
+
+
+ This story tests the global `--euiCollapsibleNavOffset` CSS variable
+
+
+
+
+ This text should be visible at all times and the bar position should
+ update dynamically based on the nav width (including on mobile)
+
+ >
+ ),
+};
+
export const CollapsedStateInLocalStorage: Story = {
render: () => {
const key = 'EuiCollapsibleNav__isCollapsed';
diff --git a/src/components/collapsible_nav_beta/collapsible_nav_beta.tsx b/src/components/collapsible_nav_beta/collapsible_nav_beta.tsx
index 5d3a62e91a7..121e594b47d 100644
--- a/src/components/collapsible_nav_beta/collapsible_nav_beta.tsx
+++ b/src/components/collapsible_nav_beta/collapsible_nav_beta.tsx
@@ -18,7 +18,12 @@ import React, {
} from 'react';
import classNames from 'classnames';
-import { useEuiTheme, useGeneratedHtmlId, throttle } from '../../services';
+import {
+ useEuiTheme,
+ useEuiThemeCSSVariables,
+ useGeneratedHtmlId,
+ throttle,
+} from '../../services';
import { CommonProps } from '../common';
import { EuiFlyout, EuiFlyoutProps } from '../flyout';
@@ -88,6 +93,7 @@ const _EuiCollapsibleNavBeta: FunctionComponent = ({
focusTrapProps: _focusTrapProps,
...rest
}) => {
+ const { setGlobalCSSVariables } = useEuiThemeCSSVariables();
const euiTheme = useEuiTheme();
const headerHeight = euiHeaderVariables(euiTheme).height;
@@ -138,9 +144,17 @@ const _EuiCollapsibleNavBeta: FunctionComponent = ({
const width = useMemo(() => {
if (isOverlayFullWidth) return '100%';
if (isPush && isCollapsed) return headerHeight;
- return _width;
+ return `${_width}px`;
}, [_width, isOverlayFullWidth, isPush, isCollapsed, headerHeight]);
+ // Other UI elements may need to account for the nav width -
+ // set a global CSS variable that they can use
+ useEffect(() => {
+ setGlobalCSSVariables({
+ '--euiCollapsibleNavOffset': isOverlay ? '0' : width,
+ });
+ }, [width, isOverlay, setGlobalCSSVariables]);
+
/**
* Prop setup
*/
From febcec76839b24eaf80e74cf87b4bfb21f652186 Mon Sep 17 00:00:00 2001
From: Cee Chen
Date: Tue, 3 Oct 2023 11:34:55 -0700
Subject: [PATCH 02/38] i18n tokens and changelog
---
CHANGELOG.md | 4 ++++
i18ntokens.json | 8 ++++----
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9380fce9570..13c4d05a593 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## [`88.5.4`](https://github.com/elastic/eui/tree/v88.5.4)
+
+- This release contains internal changes to a beta component needed by Kibana.
+
## [`88.5.3`](https://github.com/elastic/eui/tree/v88.5.3)
**Bug fixes**
diff --git a/i18ntokens.json b/i18ntokens.json
index 94affb3d45f..57ffd236887 100644
--- a/i18ntokens.json
+++ b/i18ntokens.json
@@ -455,14 +455,14 @@
"highlighting": "string",
"loc": {
"start": {
- "line": 151,
+ "line": 165,
"column": 27,
- "index": 5087
+ "index": 5469
},
"end": {
- "line": 154,
+ "line": 168,
"column": 3,
- "index": 5157
+ "index": 5539
}
},
"filepath": "src/components/collapsible_nav_beta/collapsible_nav_beta.tsx"
From cdf1e43ac506b1bdfbe57d362088bdb569d97fd5 Mon Sep 17 00:00:00 2001
From: Cee Chen
Date: Tue, 3 Oct 2023 11:34:58 -0700
Subject: [PATCH 03/38] 88.5.4
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index ca6ad3ae8bc..ea4704ddff0 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "@elastic/eui",
"description": "Elastic UI Component Library",
- "version": "88.5.3",
+ "version": "88.5.4",
"license": "SEE LICENSE IN LICENSE.txt",
"main": "lib",
"module": "es",
From afb99a4a51d4fae77656e0a5151c564f38b6c5d6 Mon Sep 17 00:00:00 2001
From: Cee Chen <549407+cee-chen@users.noreply.github.com>
Date: Tue, 3 Oct 2023 14:25:28 -0700
Subject: [PATCH 04/38] [EuiIcon] Fix silenced test errors (#7249)
---
.../icon/__snapshots__/icon.test.tsx.snap | 102 +++++++++---------
src/components/icon/icon.test.tsx | 86 ++++++---------
2 files changed, 84 insertions(+), 104 deletions(-)
diff --git a/src/components/icon/__snapshots__/icon.test.tsx.snap b/src/components/icon/__snapshots__/icon.test.tsx.snap
index 28179a5e9b0..430ad7993c8 100644
--- a/src/components/icon/__snapshots__/icon.test.tsx.snap
+++ b/src/components/icon/__snapshots__/icon.test.tsx.snap
@@ -4617,7 +4617,7 @@ exports[`EuiIcon props type logoApache is rendered 1`] = `
xmlns="http://www.w3.org/2000/svg"
>
-
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
-
+
-
+
-
-
-
+
-
+
`;
@@ -5380,8 +5380,8 @@ exports[`EuiIcon props type logoGCP is rendered 1`] = `
role="img"
viewBox="0 0 32 32"
width="32"
- xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
>
-
-
+
`;
@@ -5886,7 +5886,7 @@ exports[`EuiIcon props type logoIBM is rendered 1`] = `
xmlns="http://www.w3.org/2000/svg"
>
-
-
-
+
-
-
+
-
-
+
-
-
+
-
+
-
-
-
+
-
-
+
-
-
+
-
+
-
-
+
{
@@ -28,50 +30,18 @@ jest.mock('./icon', () => {
beforeEach(() => clearIconComponentCache());
-const prettyHtml = cheerio.load('');
-
-function testIcon(props: PropsOf) {
- return () => {
- expect.assertions(1);
- return new Promise((resolve) => {
- const onIconLoad = () => {
- component.update();
- expect(prettyHtml(component.html())).toMatchSnapshot();
- resolve();
- };
- const component = mount();
- });
- };
-}
-
-describe('EuiIcon', () => {
- let consoleErrorOverride: jest.SpyInstance;
- beforeAll(() => {
- // Ignore EuiIcon update not wrapped in act() warnings as they are triggered
- // directly from the component componentDidUpdate() and loadIconComponent()
- // TODO: Refactor EuiIcon to not cause this issue and think of a simpler
- // implementation based on modern JS bundlers features instead of
- // the EuiIcon caching layer.
- const originalConsoleError: typeof console.error = console.error;
- consoleErrorOverride = jest
- .spyOn(console, 'error')
- .mockImplementation((message, ...args) => {
- if (
- message?.startsWith(
- 'Warning: An update to %s inside a test was not wrapped in act(...).'
- )
- ) {
- return;
- }
-
- originalConsoleError(message, ...args);
- });
+const testIcon = (props: PropsOf) => async () => {
+ act(() => {
+ render();
});
-
- afterAll(() => {
- consoleErrorOverride.mockRestore();
+ await waitFor(() => {
+ const icon = document.querySelector(`[data-icon-type=${props.type}]`);
+ expect(icon).toHaveAttribute('data-is-loaded', 'true');
+ expect(icon).toMatchSnapshot();
});
+};
+describe('EuiIcon', () => {
test('is rendered', testIcon({ type: 'search', ...requiredProps }));
shouldRenderCustomStyles();
@@ -84,6 +54,17 @@ describe('EuiIcon', () => {
});
describe('props', () => {
+ test('onIconLoad', async () => {
+ const onIconLoad = jest.fn();
+
+ render();
+ expect(onIconLoad).toHaveBeenCalledTimes(0);
+
+ await waitFor(() => {
+ expect(onIconLoad).toHaveBeenCalledTimes(1);
+ });
+ });
+
describe('other props', () => {
test(
'are passed through to the icon',
@@ -156,31 +137,30 @@ describe('EuiIcon', () => {
);
};
- const component = mount();
- expect(prettyHtml(component.html())).toMatchSnapshot();
+ const { container } = render();
+ expect(container.firstChild).toMatchSnapshot();
});
describe('appendIconComponentCache', () => {
it('does nothing if not called', () => {
- const component = mount();
- expect(component.find('svg').prop('data-is-loading')).toEqual(true);
+ const { container } = render();
+ expect(container.firstChild).toHaveAttribute('data-is-loading', 'true');
});
it('preloads the specified icon into the cache', () => {
appendIconComponentCache({
videoPlayer: EuiIconVideoPlayer,
});
- const component = mount();
- // Should not have either data-is-loading attr set to true, because it was pre-loaded
- expect(component.find('svg').prop('data-is-loading')).not.toEqual(true);
+ const { container } = render();
+ expect(container.firstChild).not.toHaveAttribute('data-is-loading');
});
it('does not impact non-loaded icons', () => {
appendIconComponentCache({
videoPlayer: EuiIconVideoPlayer,
});
- const component = mount();
- expect(component.find('svg').prop('data-is-loading')).toEqual(true);
+ const { container } = render();
+ expect(container.firstChild).toHaveAttribute('data-is-loading', 'true');
});
});
});
From ce5133227573a08076b757fae5a16f38291958a3 Mon Sep 17 00:00:00 2001
From: Cee Chen <549407+cee-chen@users.noreply.github.com>
Date: Tue, 3 Oct 2023 14:51:52 -0700
Subject: [PATCH 05/38] [Storybook] General consistency pass (#7245)
---
.storybook/preview.tsx | 21 +++-
.storybook/utils.test.ts | 49 ++++++++
.storybook/utils.ts | 64 ++++++++++
scripts/jest/config.js | 1 +
.../button_empty/button_empty.stories.tsx | 17 +--
.../button_group/button_group.stories.tsx | 49 ++++----
.../button_icon/button_icon.stories.tsx | 17 +--
.../collapsible_nav.stories.tsx | 11 +-
.../collapsible_nav_group.stories.tsx | 20 ++-
.../collapsible_nav_beta.stories.tsx | 118 +++++++++---------
.../empty_prompt/empty_prompt.stories.tsx | 20 ++-
.../error_boundary/error_boundary.stories.tsx | 31 ++---
.../filter_group/filter_button.stories.tsx | 35 ++++--
src/components/header/header.stories.tsx | 12 +-
.../header_alert/header_alert.stories.tsx | 30 ++---
.../header_links/header_links.stories.tsx | 9 +-
.../header_logo/header_logo.stories.tsx | 13 +-
.../key_pad_menu_item.stories.tsx | 10 +-
src/components/page/page.stories.tsx | 35 +++---
.../page/page_body/page_body.stories.tsx | 25 ++--
.../page/page_header/page_header.stories.tsx | 15 ++-
.../page_section/page_section.stories.tsx | 19 ++-
.../page_sidebar/page_sidebar.stories.tsx | 34 ++---
.../split_panel/split_panel_inner.stories.tsx | 15 +--
.../split_panel/split_panel_outer.stories.tsx | 10 +-
.../resizable_button.stories.tsx | 11 +-
.../resizable_collapse_button.stories.tsx | 32 +++--
src/components/side_nav/side_nav.stories.tsx | 59 +++++----
.../text_truncate/text_truncate.stories.tsx | 37 +++---
29 files changed, 478 insertions(+), 341 deletions(-)
create mode 100644 .storybook/utils.test.ts
create mode 100644 .storybook/utils.ts
diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx
index e2ba33fff7d..af501c4be44 100644
--- a/.storybook/preview.tsx
+++ b/.storybook/preview.tsx
@@ -38,6 +38,13 @@ import { writingModeStyles } from './writing_mode.styles';
// once all EUI components are converted to Emotion
import '../dist/eui_theme_light.css';
+/**
+ * Prop controls
+ */
+
+import type { CommonProps } from '../src/components/common';
+import { hideStorybookControls } from './utils';
+
const preview: Preview = {
decorators: [
(Story, context) => (
@@ -86,6 +93,7 @@ const preview: Preview = {
parameters: {
actions: { argTypesRegex: '^on[A-Z].*' },
backgrounds: { disable: true }, // Use colorMode instead
+ options: { showPanel: true }, // default to showing the controls panel
controls: {
expanded: true,
sort: 'requiredFirst',
@@ -100,12 +108,13 @@ const preview: Preview = {
},
// Due to CommonProps, these props appear on almost every Story, but generally
// aren't super useful to test - let's disable them by default and (if needed)
- // individual stories can re-enable them
- argTypes: {
- css: { table: { disable: true } },
- className: { table: { disable: true } },
- 'data-test-subj': { table: { disable: true } },
- },
+ // individual stories can re-enable them, e.g. by passing
+ // `argTypes: { 'data-test-subj': { table: { disable: false } } }`
+ argTypes: hideStorybookControls([
+ 'css',
+ 'className',
+ 'data-test-subj',
+ ]),
};
export default preview;
diff --git a/.storybook/utils.test.ts b/.storybook/utils.test.ts
new file mode 100644
index 00000000000..d570363a393
--- /dev/null
+++ b/.storybook/utils.test.ts
@@ -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 { hideStorybookControls, disableStorybookControls } from './utils';
+
+describe('hideStorybookControls', () => {
+ it('outputs the expected `argTypes` object when passed prop name strings', () => {
+ expect(
+ hideStorybookControls(['isDisabled', 'isLoading', 'isInvalid'])
+ ).toEqual({
+ isDisabled: { table: { disable: true } },
+ isLoading: { table: { disable: true } },
+ isInvalid: { table: { disable: true } },
+ });
+ });
+
+ it('throws a typescript error if a generic is passed and the prop names do not match', () => {
+ type TestComponentProps = { hello: boolean; world: boolean };
+ // No typescript error
+ hideStorybookControls(['hello', 'world']);
+ // @ts-expect-error - will fail `yarn lint` if a TS error is *not* produced
+ hideStorybookControls(['hello', 'world', 'error']);
+ });
+});
+
+describe('disableStorybookControls', () => {
+ it('outputs the expected `argTypes` object when passed prop name strings', () => {
+ expect(
+ disableStorybookControls(['isDisabled', 'isLoading', 'isInvalid'])
+ ).toEqual({
+ isDisabled: { control: false },
+ isLoading: { control: false },
+ isInvalid: { control: false },
+ });
+ });
+
+ it('throws a typescript error if a generic is passed and the prop names do not match', () => {
+ type TestComponentProps = { hello: boolean; world: boolean };
+ // No typescript error
+ disableStorybookControls(['hello', 'world']);
+ // @ts-expect-error - will fail `yarn lint` if a TS error is *not* produced
+ disableStorybookControls(['hello', 'world', 'error']);
+ });
+});
diff --git a/.storybook/utils.ts b/.storybook/utils.ts
new file mode 100644
index 00000000000..517b93421c2
--- /dev/null
+++ b/.storybook/utils.ts
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+/**
+ * argTypes configurations
+ */
+
+/**
+ * Completely hide props from Storybook's controls panel.
+ * Should be passed or spread to `argTypes`
+ */
+export const hideStorybookControls = (
+ propNames: Array
+): Record | {} => {
+ return propNames.reduce(
+ (obj, name) => ({ ...obj, [name]: HIDE_CONTROL }),
+ {}
+ );
+};
+const HIDE_CONTROL = { table: { disable: true } };
+
+/**
+ * Leave props visible in Storybook's controls panel, but disable them
+ * from being controllable (renders a `-`).
+ *
+ * Should be passed or spread to `argTypes`
+ */
+export const disableStorybookControls = (
+ propNames: Array
+): Record | {} => {
+ return propNames.reduce(
+ (obj, name) => ({ ...obj, [name]: DISABLE_CONTROL }),
+ {}
+ );
+};
+const DISABLE_CONTROL = { control: false };
+
+/**
+ * parameters configurations
+ */
+
+/**
+ * Will hide all props/controls. Pass to `parameters`
+ *
+ * TODO: Figure out some way to not show Storybook's "setup" text?
+ */
+export const hideAllStorybookControls = {
+ controls: { exclude: /.*/g },
+};
+
+/**
+ * Will hide the control/addon panel entirely for a specific story.
+ * Should be passed or spread to to `parameters`.
+ *
+ * Note that users can choose to re-show the panel in the UI
+ */
+export const hidePanel = {
+ options: { showPanel: false },
+};
diff --git a/scripts/jest/config.js b/scripts/jest/config.js
index 3174d93b6cb..84006d237aa 100644
--- a/scripts/jest/config.js
+++ b/scripts/jest/config.js
@@ -19,6 +19,7 @@ const config = {
'/scripts/babel',
'/scripts/tests',
'/scripts/eslint-plugin',
+ '/.storybook',
],
collectCoverageFrom: [
'src/{components,services,global_styling}/**/*.{ts,tsx,js,jsx}',
diff --git a/src/components/button/button_empty/button_empty.stories.tsx b/src/components/button/button_empty/button_empty.stories.tsx
index fcbfdc29e62..ccf9cd2c12a 100644
--- a/src/components/button/button_empty/button_empty.stories.tsx
+++ b/src/components/button/button_empty/button_empty.stories.tsx
@@ -20,14 +20,8 @@ const meta: Meta = {
},
iconType: { control: 'text' },
},
-};
-
-export default meta;
-type Story = StoryObj;
-
-export const Playground: Story = {
args: {
- children: 'Tertiary action',
+ // Component defaults
color: 'primary',
size: 'm',
iconSize: 'm',
@@ -37,3 +31,12 @@ export const Playground: Story = {
isSelected: false,
},
};
+
+export default meta;
+type Story = StoryObj;
+
+export const Playground: Story = {
+ args: {
+ children: 'Tertiary action',
+ },
+};
diff --git a/src/components/button/button_group/button_group.stories.tsx b/src/components/button/button_group/button_group.stories.tsx
index 9e3c8cdd3cc..d4f0eef2928 100644
--- a/src/components/button/button_group/button_group.stories.tsx
+++ b/src/components/button/button_group/button_group.stories.tsx
@@ -8,6 +8,7 @@
import React, { useState } from 'react';
import type { Meta, StoryObj } from '@storybook/react';
+import { disableStorybookControls } from '../../../../.storybook/utils';
import {
EuiButtonGroup,
@@ -19,11 +20,6 @@ const meta: Meta = {
title: 'EuiButtonGroup',
// @ts-ignore This still works for Storybook controls, even though Typescript complains
component: EuiButtonGroup,
- parameters: {
- controls: {
- exclude: ['data-test-subj'],
- },
- },
argTypes: {
type: {
options: ['single', 'multi'],
@@ -44,6 +40,15 @@ const meta: Meta = {
control: 'select',
},
},
+ args: {
+ // Component defaults
+ type: 'single',
+ buttonSize: 's',
+ color: 'text',
+ isDisabled: false,
+ isFullWidth: false,
+ isIconOnly: false,
+ },
};
export default meta;
@@ -76,6 +81,17 @@ const EuiButtonGroupSingle = (props: any) => {
);
};
+export const SingleSelection: Story = {
+ render: ({ ...args }) => ,
+ args: {
+ legend: 'EuiButtonGroup - single selection',
+ options,
+ type: 'single',
+ idSelected: 'button1',
+ },
+ argTypes: disableStorybookControls(['type']),
+};
+
const EuiButtonGroupMulti = (props: any) => {
const [idToSelectedMap, setIdToSelectedMap] = useState<
Record
@@ -100,24 +116,13 @@ const EuiButtonGroupMulti = (props: any) => {
);
};
-export const Playground: Story = {
- render: ({ ...args }) => {
- if (args.type === 'multi') {
- return ;
- } else {
- return ;
- }
- },
+export const MultiSelection: Story = {
+ render: ({ ...args }) => ,
args: {
- legend: 'EuiButtonGroup demo',
- type: 'single',
+ legend: 'EuiButtonGroup - multiple selections',
options,
- idSelected: 'button1',
+ type: 'multi',
idToSelectedMap: { button1: true },
- buttonSize: 's',
- color: 'text',
- isDisabled: false,
- isFullWidth: false,
- isIconOnly: false,
- } as any,
+ },
+ argTypes: disableStorybookControls(['type']),
};
diff --git a/src/components/button/button_icon/button_icon.stories.tsx b/src/components/button/button_icon/button_icon.stories.tsx
index 29d2e49cf62..8ef364ab30a 100644
--- a/src/components/button/button_icon/button_icon.stories.tsx
+++ b/src/components/button/button_icon/button_icon.stories.tsx
@@ -13,14 +13,8 @@ import { EuiButtonIcon, EuiButtonIconProps } from './button_icon';
const meta: Meta = {
title: 'EuiButtonIcon',
component: EuiButtonIcon,
-};
-
-export default meta;
-type Story = StoryObj;
-
-export const Playground: Story = {
args: {
- iconType: 'faceHappy',
+ // Component defaults
color: 'primary',
display: 'empty',
size: 'xs',
@@ -30,3 +24,12 @@ export const Playground: Story = {
isSelected: false,
},
};
+
+export default meta;
+type Story = StoryObj;
+
+export const Playground: Story = {
+ args: {
+ iconType: 'faceHappy',
+ },
+};
diff --git a/src/components/collapsible_nav/collapsible_nav.stories.tsx b/src/components/collapsible_nav/collapsible_nav.stories.tsx
index 77a89909ea2..efefaf47e94 100644
--- a/src/components/collapsible_nav/collapsible_nav.stories.tsx
+++ b/src/components/collapsible_nav/collapsible_nav.stories.tsx
@@ -15,6 +15,13 @@ import { EuiCollapsibleNav, EuiCollapsibleNavProps } from './collapsible_nav';
const meta: Meta = {
title: 'EuiCollapsibleNav',
component: EuiCollapsibleNav,
+ args: {
+ // Component defaults
+ isDocked: false,
+ dockedBreakpoint: 'l',
+ showButtonIfDocked: false,
+ size: 320,
+ },
// TODO: Improve props inherited from EuiFlyout, ideally through
// a DRY import from `flyout.stories.tsx` once that's created
};
@@ -43,9 +50,5 @@ export const Playground: Story = {
args: {
children: 'Collapsible nav content',
isOpen: true,
- isDocked: false,
- dockedBreakpoint: 'l',
- showButtonIfDocked: false,
- size: 240,
},
};
diff --git a/src/components/collapsible_nav/collapsible_nav_group/collapsible_nav_group.stories.tsx b/src/components/collapsible_nav/collapsible_nav_group/collapsible_nav_group.stories.tsx
index 4f761dc65a0..ae4d317761d 100644
--- a/src/components/collapsible_nav/collapsible_nav_group/collapsible_nav_group.stories.tsx
+++ b/src/components/collapsible_nav/collapsible_nav_group/collapsible_nav_group.stories.tsx
@@ -43,6 +43,14 @@ const meta: Meta = {
isDisabled: { if: { arg: 'isCollapsible' } },
element: { if: { arg: 'isCollapsible' } },
},
+ args: {
+ iconType: 'logoElastic',
+ // Component defaults
+ iconSize: 'l',
+ titleSize: 'xxs',
+ titleElement: 'h3',
+ background: 'none',
+ },
};
export default meta;
@@ -51,12 +59,7 @@ type Story = StoryObj;
export const Accordion: Story = {
args: {
children: 'This is an accordion group with a title',
- background: 'none',
title: 'Nav group - accordion',
- iconType: 'logoElastic',
- iconSize: 'l',
- titleElement: 'h3',
- titleSize: 'xxs',
initialIsOpen: true,
isCollapsible: true,
},
@@ -65,12 +68,6 @@ export const Accordion: Story = {
export const NonAccordion: StoryObj = {
args: {
children: 'This is a group with a title',
- background: 'none',
- title: 'Nav group - non-accordion',
- iconType: 'logoElastic',
- iconSize: 'l',
- titleElement: 'h3',
- titleSize: 'xxs',
isCollapsible: false,
},
};
@@ -78,6 +75,5 @@ export const NonAccordion: StoryObj = {
export const NoTitle: Story = {
args: {
children: 'This is a group without a title',
- background: 'none',
},
};
diff --git a/src/components/collapsible_nav_beta/collapsible_nav_beta.stories.tsx b/src/components/collapsible_nav_beta/collapsible_nav_beta.stories.tsx
index 15c1b1148f7..dc3bc82410b 100644
--- a/src/components/collapsible_nav_beta/collapsible_nav_beta.stories.tsx
+++ b/src/components/collapsible_nav_beta/collapsible_nav_beta.stories.tsx
@@ -8,6 +8,10 @@
import React, { FunctionComponent, PropsWithChildren, useState } from 'react';
import type { Meta, StoryObj } from '@storybook/react';
+import {
+ hideStorybookControls,
+ hideAllStorybookControls,
+} from '../../../.storybook/utils';
import { EuiHeader, EuiHeaderSection, EuiHeaderSectionItem } from '../header';
import { EuiPageTemplate } from '../page_template';
@@ -35,6 +39,7 @@ const meta: Meta = {
},
},
args: {
+ // Component defaults
side: 'left',
initialIsCollapsed: false,
width: 248,
@@ -417,21 +422,57 @@ export const SecurityExample: Story = {
),
};
-export const MultipleFixedHeaders: Story = {
- render: ({ ...args }) => (
+export const CollapsedStateInLocalStorage: Story = {
+ render: () => {
+ const key = 'EuiCollapsibleNav__isCollapsed';
+ const initialIsCollapsed = window.localStorage.getItem(key) === 'true';
+ const onCollapseToggle = (isCollapsed: boolean) =>
+ window.localStorage.setItem(key, String(isCollapsed));
+
+ return (
+ <>
+
+
+
+
+
+
+
+ Toggle the collapsed state and refresh the page. The collapsed state
+ should have been saved/remembered
+
+
+ >
+ );
+ },
+ argTypes: hideStorybookControls(['aria-label', 'side', 'width']),
+};
+
+export const GlobalCSSVariable: Story = {
+ render: ({ side, ...args }) => (
<>
- First header
-
-
- This story tests that EuiCollapsibleNav automatically adjusts its
- position & height for multiple fixed headers
+
+
+ This story tests the global `--euiCollapsibleNavOffset` CSS variable
- Second header
+ {/* In production, would just be `left="var(--euiCollapsibleNavOffset, 0)"` if the nav isn't changing sides */}
+
+ This text should be visible at all times and the bar position should
+ update dynamically based on the nav width (including on mobile)
+
>
),
+ argTypes: hideStorybookControls([
+ 'aria-label',
+ 'initialIsCollapsed',
+ 'onCollapseToggle',
+ ]),
};
const MockConsumerFlyout: FunctionComponent = () => {
@@ -439,13 +480,13 @@ const MockConsumerFlyout: FunctionComponent = () => {
return (
<>
setFlyoutOpen(!flyoutIsOpen)}>
- Toggle a flyout
+ Toggle flyout
{flyoutIsOpen && (
setFlyoutOpen(false)}>
- Some other mock consumer flyout that should overlap
- EuiCollapsibleNav
+ This flyout's mask should overlay / sit on top of the collapsible
+ nav, on both desktop and mobile
)}
@@ -453,12 +494,14 @@ const MockConsumerFlyout: FunctionComponent = () => {
);
};
-export const FlyoutInFixedHeaders: Story = {
- render: ({ ...args }) => {
+export const FlyoutOverlay: Story = {
+ render: (_) => {
return (
- Nav content
+
+ Click the "Toggle flyout" button in the top right hand corner
+
@@ -468,50 +511,5 @@ export const FlyoutInFixedHeaders: Story = {
);
},
-};
-
-export const GlobalCSSVariable: Story = {
- render: ({ ...args }) => (
- <>
-
-
-
- This story tests the global `--euiCollapsibleNavOffset` CSS variable
-
-
-
-
- This text should be visible at all times and the bar position should
- update dynamically based on the nav width (including on mobile)
-
- >
- ),
-};
-
-export const CollapsedStateInLocalStorage: Story = {
- render: () => {
- const key = 'EuiCollapsibleNav__isCollapsed';
- const initialIsCollapsed = window.localStorage.getItem(key) === 'true';
- const onCollapseToggle = (isCollapsed: boolean) =>
- window.localStorage.setItem(key, String(isCollapsed));
-
- return (
- <>
-
-
-
-
-
-
-
- Toggle the collapsed state and refresh the page. The collapsed state
- should have been saved/remembered
-
-
- >
- );
- },
+ parameters: hideAllStorybookControls,
};
diff --git a/src/components/empty_prompt/empty_prompt.stories.tsx b/src/components/empty_prompt/empty_prompt.stories.tsx
index b71e1f06a46..dcb64852d34 100644
--- a/src/components/empty_prompt/empty_prompt.stories.tsx
+++ b/src/components/empty_prompt/empty_prompt.stories.tsx
@@ -21,25 +21,24 @@ import { EuiEmptyPrompt, EuiEmptyPromptProps } from './empty_prompt';
const meta: Meta = {
title: 'EuiEmptyPrompt',
component: EuiEmptyPrompt,
+ args: {
+ // Component defaults
+ titleSize: 'm',
+ paddingSize: 'l',
+ color: 'plain', // Default is actually 'transparent', but for the purposes of easier testing in Storybook we'll set it to plain
+ layout: 'vertical',
+ hasBorder: false,
+ hasShadow: false,
+ },
};
export default meta;
type Story = StoryObj;
-const componentDefaults: EuiEmptyPromptProps = {
- titleSize: 'm',
- paddingSize: 'l',
- color: 'plain', // The component default is actually 'transparent', but for the purposes of easier testing in Storybook we'll set it to plain
- layout: 'vertical',
-};
-
export const Playground: Story = {
args: {
- ...componentDefaults,
title:
Start adding cases
,
iconType: 'logoSecurity',
- hasBorder: false,
- hasShadow: false,
body: 'Add a new case or change your filter settings.', // Should be wrapped in a `
` in production usage, but using a string makes this easier to edit in Storybook controls
actions: [
@@ -67,7 +66,6 @@ export const PageTemplate: Story = {
),
args: {
- ...componentDefaults,
title:
Create your first visualization
,
layout: 'horizontal',
icon: ,
diff --git a/src/components/error_boundary/error_boundary.stories.tsx b/src/components/error_boundary/error_boundary.stories.tsx
index 54b011ba4a7..f62dffba499 100644
--- a/src/components/error_boundary/error_boundary.stories.tsx
+++ b/src/components/error_boundary/error_boundary.stories.tsx
@@ -11,31 +11,26 @@ import type { Meta, StoryObj } from '@storybook/react';
import { EuiErrorBoundary, EuiErrorBoundaryProps } from './error_boundary';
-const ErrorContent = () => {
- throw new Error(
- "I'm here to kick butt and chew bubblegum.\n\nAnd I'm all out of gum."
- );
-};
-
const meta: Meta = {
title: 'EuiErrorBoundary',
- component: () => (
-
-
-
- ),
+ component: EuiErrorBoundary,
parameters: {
layout: 'fullscreen',
},
- argTypes: {
- onError: {
- description:
- 'TODO: extract prop descriptions, defaults, and types from Typescript ',
- },
- },
};
export default meta;
type Story = StoryObj;
-export const Default: Story = {};
+const ErrorContent = () => {
+ throw new Error(
+ "I'm here to kick butt and chew bubblegum.\n\nAnd I'm all out of gum."
+ );
+};
+
+export const Playground: Story = {
+ args: {
+ children: ,
+ onError: console.log,
+ },
+};
diff --git a/src/components/filter_group/filter_button.stories.tsx b/src/components/filter_group/filter_button.stories.tsx
index 49a2f3802ca..03eb27542b5 100644
--- a/src/components/filter_group/filter_button.stories.tsx
+++ b/src/components/filter_group/filter_button.stories.tsx
@@ -9,20 +9,26 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
+import { BUTTON_COLORS } from '../../themes/amsterdam/global_styling/mixins';
+
import { EuiFilterGroup } from './filter_group';
import { EuiFilterButton, EuiFilterButtonProps } from './filter_button';
const meta: Meta = {
title: 'EuiFilterButton',
component: EuiFilterButton as any,
-};
-
-const defaultProps = {
- hasActiveFilters: true,
- numFilters: 5,
- iconType: 'arrowDown',
- iconSide: 'right' as const,
- isDisabled: false,
+ argTypes: {
+ color: { control: 'select', options: BUTTON_COLORS },
+ },
+ args: {
+ // Component defaults
+ iconSide: 'right',
+ color: 'text',
+ badgeColor: 'accent',
+ grow: true,
+ isSelected: false,
+ isDisabled: false,
+ },
};
export default meta;
@@ -34,7 +40,11 @@ export const Playground: Story = {
Filter
),
- args: defaultProps,
+ args: {
+ hasActiveFilters: true,
+ numFilters: 5,
+ iconType: 'arrowDown',
+ },
};
export const MultipleButtons: Story = {
@@ -45,7 +55,11 @@ export const MultipleButtons: Story = {
Filter three
),
- args: defaultProps,
+ args: {
+ hasActiveFilters: true,
+ numFilters: 5,
+ iconType: 'arrowDown',
+ },
};
export const FullWidthAndGrow: Story = {
@@ -78,5 +92,4 @@ export const FullWidthAndGrow: Story = {
),
- args: { isDisabled: false },
};
diff --git a/src/components/header/header.stories.tsx b/src/components/header/header.stories.tsx
index 0e458880861..bb0b4a5bae8 100644
--- a/src/components/header/header.stories.tsx
+++ b/src/components/header/header.stories.tsx
@@ -26,18 +26,18 @@ import { EuiHeader, EuiHeaderProps } from './header';
const meta: Meta = {
title: 'EuiHeader',
component: EuiHeader,
-};
-
-export default meta;
-type Story = StoryObj;
-
-export const Playground: Story = {
args: {
+ // Component defaults
position: 'static',
theme: 'default',
},
};
+export default meta;
+type Story = StoryObj;
+
+export const Playground: Story = {};
+
export const Sections: Story = {
args: {
position: 'fixed',
diff --git a/src/components/header/header_alert/header_alert.stories.tsx b/src/components/header/header_alert/header_alert.stories.tsx
index 1ffe3335566..91749eee728 100644
--- a/src/components/header/header_alert/header_alert.stories.tsx
+++ b/src/components/header/header_alert/header_alert.stories.tsx
@@ -40,26 +40,24 @@ import { EuiHeaderAlert, EuiHeaderAlertProps } from './header_alert';
const meta: Meta = {
title: 'EuiHeaderAlert',
component: EuiHeaderAlert,
+ args: {
+ // Not default props, set for demo purposes
+ title: '7.0 release notes',
+ date: 'January 1st 1970',
+ text: 'Stay up-to-date on the latest and greatest features.',
+ action: (
+
+ Check out the docs
+
+ ),
+ badge: 7.0,
+ },
};
export default meta;
type Story = StoryObj;
-const defaultProps = {
- title: '7.0 release notes',
- date: 'January 1st 1970',
- text: 'Stay up-to-date on the latest and greatest features.',
- action: (
-
- Check out the docs
-
- ),
- badge: 7.0,
-};
-
-export const Playground: Story = {
- args: defaultProps,
-};
+export const Playground: Story = {};
/**
* Flyout example
@@ -121,7 +119,6 @@ const Flyout = (props: EuiHeaderAlertProps) => {
};
export const FlyoutExample: Story = {
render: ({ ...args }) => ,
- args: defaultProps,
};
/**
@@ -182,5 +179,4 @@ const Popover = (props: any) => {
};
export const PopoverExample: Story = {
render: ({ ...args }) => ,
- args: defaultProps,
};
diff --git a/src/components/header/header_links/header_links.stories.tsx b/src/components/header/header_links/header_links.stories.tsx
index 4a07d685a53..35ae96b895b 100644
--- a/src/components/header/header_links/header_links.stories.tsx
+++ b/src/components/header/header_links/header_links.stories.tsx
@@ -17,6 +17,11 @@ import { EuiHeaderLinks, EuiHeaderLinksProps } from './header_links';
const meta: Meta = {
title: 'EuiHeaderLinks',
component: EuiHeaderLinks,
+ args: {
+ // Component defaults
+ gutterSize: 's',
+ popoverBreakpoints: ['xs', 's'],
+ },
};
export default meta;
@@ -36,8 +41,4 @@ export const Playground: Story = {
),
- args: {
- gutterSize: 's',
- popoverBreakpoints: ['xs', 's'],
- },
};
diff --git a/src/components/header/header_logo/header_logo.stories.tsx b/src/components/header/header_logo/header_logo.stories.tsx
index 32eb29bf3ca..2ba258a2b84 100644
--- a/src/components/header/header_logo/header_logo.stories.tsx
+++ b/src/components/header/header_logo/header_logo.stories.tsx
@@ -15,6 +15,11 @@ import { EuiHeaderLogo, EuiHeaderLogoProps } from './header_logo';
const meta: Meta = {
title: 'EuiHeaderLogo',
component: EuiHeaderLogo,
+ args: {
+ // Not default props, set for demo purposes
+ iconType: 'logoElastic',
+ children: 'Elastic',
+ },
};
export default meta;
@@ -28,10 +33,6 @@ export const Playground: Story = {
),
- args: {
- iconType: 'logoElastic',
- iconTitle: 'Elastic',
- },
};
export const WithText: Story = {
@@ -42,8 +43,4 @@ export const WithText: Story = {
),
- args: {
- iconType: 'logoElastic',
- children: 'Elastic',
- },
};
diff --git a/src/components/key_pad_menu/key_pad_menu_item.stories.tsx b/src/components/key_pad_menu/key_pad_menu_item.stories.tsx
index 051c15ad95f..c6e829f7057 100644
--- a/src/components/key_pad_menu/key_pad_menu_item.stories.tsx
+++ b/src/components/key_pad_menu/key_pad_menu_item.stories.tsx
@@ -19,6 +19,12 @@ const meta: Meta = {
argTypes: {
checkable: { options: [undefined, 'multi', 'single'] },
},
+ args: {
+ label: 'Hello world', // String makes prop easier to change/toggle
+ // Component defaults
+ isDisabled: false,
+ isSelected: false,
+ },
};
export default meta;
@@ -27,9 +33,5 @@ type Story = StoryObj;
export const Playground: Story = {
args: {
children: ,
- // Make these props easier to change/toggle
- label: 'Hello world',
- isDisabled: false,
- isSelected: false,
},
};
diff --git a/src/components/page/page.stories.tsx b/src/components/page/page.stories.tsx
index 7da4e143873..7b1415eb09a 100644
--- a/src/components/page/page.stories.tsx
+++ b/src/components/page/page.stories.tsx
@@ -8,6 +8,7 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
+import { hideStorybookControls } from '../../../.storybook/utils';
import { EuiFlexGroup } from '../flex';
import { EuiSkeletonText } from '../skeleton';
@@ -19,23 +20,22 @@ import { EuiPage, EuiPageProps } from './page';
const meta: Meta = {
title: 'EuiPage',
component: EuiPage,
+ argTypes: {
+ restrictWidth: { control: 'boolean' },
+ },
+ args: {
+ // Component defaults
+ paddingSize: 'none',
+ grow: true,
+ direction: 'row',
+ restrictWidth: false,
+ },
};
export default meta;
type Story = StoryObj;
-const componentDefaults: EuiPageProps = {
- paddingSize: 'none',
- grow: true,
- direction: 'row',
- restrictWidth: false,
-};
-
export const Playground: Story = {
- args: componentDefaults,
- argTypes: {
- restrictWidth: { control: 'boolean' },
- },
render: ({ ...args }) => (
([
+ 'grow',
+ 'direction',
+ 'paddingSize',
+ ]),
render: ({ ...args }) => {_pageContent},
};
diff --git a/src/components/page/page_body/page_body.stories.tsx b/src/components/page/page_body/page_body.stories.tsx
index 9c0229a919c..4e9621b5107 100644
--- a/src/components/page/page_body/page_body.stories.tsx
+++ b/src/components/page/page_body/page_body.stories.tsx
@@ -9,28 +9,31 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
+import { BORDER_RADII, EuiPanelProps } from '../../panel/panel';
import { EuiSkeletonText } from '../../skeleton';
import { EuiPage } from '../page';
import { EuiPageBody, EuiPageBodyProps } from './page_body';
-const meta: Meta = {
+const meta: Meta> = {
title: 'EuiPageBody',
component: EuiPageBody,
+ argTypes: {
+ borderRadius: { control: 'radio', options: BORDER_RADII },
+ },
+ args: {
+ // Component defaults
+ restrictWidth: false,
+ paddingSize: 'none',
+ borderRadius: 'none',
+ component: 'main', // This is not a component default, but for the purposes of easier testing in the DOM in Storybook we'll set it to main
+ },
};
export default meta;
type Story = StoryObj;
-const componentDefaults: EuiPageBodyProps = {
- panelled: true,
- restrictWidth: false,
- paddingSize: 'm', // The component default is actually 'none', but for nicer visuals in Storybook we'll set it to 'm'
- component: 'main', // This is not a component default, but for the purposes of easier testing in the DOM in Storybook we'll set it to main
-};
-
export const Playground: Story = {
- args: componentDefaults,
render: ({ ...args }) => (
@@ -43,4 +46,8 @@ export const Playground: Story = {
),
+ args: {
+ panelled: true,
+ paddingSize: 'm',
+ },
};
diff --git a/src/components/page/page_header/page_header.stories.tsx b/src/components/page/page_header/page_header.stories.tsx
index aa0ec8a28d4..d692656150f 100644
--- a/src/components/page/page_header/page_header.stories.tsx
+++ b/src/components/page/page_header/page_header.stories.tsx
@@ -24,21 +24,20 @@ const meta: Meta = {
breadcrumbProps: { control: 'object' },
tabsProps: { control: 'object' },
},
+ args: {
+ // Component defaults
+ paddingSize: 'none',
+ responsive: true,
+ restrictWidth: false,
+ alignItems: undefined,
+ },
};
export default meta;
type Story = StoryObj;
-const componentDefaults: EuiPageHeaderProps = {
- paddingSize: 'none',
- responsive: true,
- restrictWidth: false,
- alignItems: undefined,
-};
-
export const Playground: Story = {
args: {
- ...componentDefaults,
pageTitle: 'Page title',
iconType: 'logoKibana',
description: 'Example of a description.',
diff --git a/src/components/page/page_section/page_section.stories.tsx b/src/components/page/page_section/page_section.stories.tsx
index 13a939dc511..89559bc065c 100644
--- a/src/components/page/page_section/page_section.stories.tsx
+++ b/src/components/page/page_section/page_section.stories.tsx
@@ -19,22 +19,21 @@ const meta: Meta = {
argTypes: {
bottomBorder: { control: 'select', options: [true, false, 'extended'] },
},
+ args: {
+ // Component defaults
+ restrictWidth: false,
+ color: 'plain', // The component default is actually 'transparent', but for the purposes of easier testing in Storybook we'll set it to plain
+ paddingSize: 'l',
+ alignment: 'top',
+ grow: false,
+ component: 'section', // This is not a component default, but for the purposes of easier testing in the DOM in Storybook we'll set it to section
+ },
};
export default meta;
type Story = StoryObj;
-const componentDefaults: EuiPageSectionProps = {
- restrictWidth: false,
- color: 'plain', // The component default is actually 'transparent', but for the purposes of easier testing in Storybook we'll set it to plain
- paddingSize: 'l',
- alignment: 'top',
- grow: false,
- component: 'section', // This is not a component default, but for the purposes of easier testing in the DOM in Storybook we'll set it to section
-};
-
export const Playground: Story = {
- args: componentDefaults,
render: ({ ...args }) => (
// Block size demos the grow prop
diff --git a/src/components/page/page_sidebar/page_sidebar.stories.tsx b/src/components/page/page_sidebar/page_sidebar.stories.tsx
index ec1096e72d7..5b0d1d7959c 100644
--- a/src/components/page/page_sidebar/page_sidebar.stories.tsx
+++ b/src/components/page/page_sidebar/page_sidebar.stories.tsx
@@ -8,6 +8,7 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
+import { hideStorybookControls } from '../../../../.storybook/utils';
import { EuiSkeletonText } from '../../skeleton';
import { EuiPageSection } from '../page_section';
@@ -21,23 +22,22 @@ const meta: Meta = {
parameters: {
layout: 'fullscreen',
},
+ argTypes: {
+ sticky: { control: 'boolean' },
+ },
+ args: {
+ // Component defaults
+ paddingSize: 'm', // The component default is actually 'none', but for nicer visuals in Storybook we'll set it to 'm'
+ sticky: false,
+ minWidth: 248,
+ responsive: ['xs', 's'],
+ },
};
export default meta;
type Story = StoryObj;
-const componentDefaults: EuiPageSidebarProps = {
- paddingSize: 'm', // The component default is actually 'none', but for nicer visuals in Storybook we'll set it to 'm'
- sticky: false,
- minWidth: 248,
- responsive: ['xs', 's'],
-};
-
export const Playground: Story = {
- args: componentDefaults,
- argTypes: {
- sticky: { control: 'boolean' },
- },
render: ({ ...args }) => (
({
@@ -60,14 +60,18 @@ export const Playground: Story = {
export const StickyOffset: Story = {
args: {
- ...componentDefaults,
sticky: { offset: 50 },
},
argTypes: {
+ sticky: {
+ control: 'object',
+ },
// This story demos the sticky functionality; removing other props to prevent confusion
- minWidth: { table: { disable: true } },
- paddingSize: { table: { disable: true } },
- responsive: { table: { disable: true } },
+ ...hideStorybookControls([
+ 'minWidth',
+ 'paddingSize',
+ 'responsive',
+ ]),
},
render: ({ ...args }) => (
= {
component: EuiSplitPanel.Inner,
argTypes: {
color: { control: 'select', options: COLORS },
- panelRef: { control: false },
+ ...disableStorybookControls<_EuiSplitPanelInnerProps>(['panelRef']),
+ },
+ args: {
+ // Component defaults
+ color: 'transparent',
+ paddingSize: 'm',
+ grow: true,
},
};
@@ -25,12 +32,6 @@ export default meta;
type Story = StoryObj<_EuiSplitPanelInnerProps>;
export const SplitPanelInner: Story = {
- args: {
- // Default props
- color: 'transparent',
- paddingSize: 'm',
- grow: true,
- },
render: ({ ...args }) => (
Top panel
diff --git a/src/components/panel/split_panel/split_panel_outer.stories.tsx b/src/components/panel/split_panel/split_panel_outer.stories.tsx
index b612dfc8c3c..e6b89dc0254 100644
--- a/src/components/panel/split_panel/split_panel_outer.stories.tsx
+++ b/src/components/panel/split_panel/split_panel_outer.stories.tsx
@@ -14,17 +14,17 @@ import { EuiSplitPanel, _EuiSplitPanelOuterProps } from './split_panel';
const meta: Meta<_EuiSplitPanelOuterProps> = {
title: 'EuiSplitPanel',
component: EuiSplitPanel.Outer,
+ args: {
+ // Component defaults
+ direction: 'column',
+ responsive: ['xs', 's'],
+ },
};
export default meta;
type Story = StoryObj<_EuiSplitPanelOuterProps>;
export const SplitPanelOuter: Story = {
- args: {
- // Default props
- direction: 'column',
- responsive: ['xs', 's'],
- },
render: ({ ...args }) => (
Top or left panel
diff --git a/src/components/resizable_container/resizable_button.stories.tsx b/src/components/resizable_container/resizable_button.stories.tsx
index c3a2c33fddf..4cd4b2261b0 100644
--- a/src/components/resizable_container/resizable_button.stories.tsx
+++ b/src/components/resizable_container/resizable_button.stories.tsx
@@ -19,6 +19,12 @@ import {
const meta: Meta = {
title: 'EuiResizableButton',
component: EuiResizableButton,
+ args: {
+ // Component defaults
+ alignIndicator: 'center',
+ disabled: false,
+ isHorizontal: false,
+ },
};
export default meta;
@@ -30,9 +36,4 @@ export const Playground: Story = {
),
- args: {
- isHorizontal: true,
- alignIndicator: 'center',
- disabled: false,
- },
};
diff --git a/src/components/resizable_container/resizable_collapse_button.stories.tsx b/src/components/resizable_container/resizable_collapse_button.stories.tsx
index 9b318e4291c..efc09176eff 100644
--- a/src/components/resizable_container/resizable_collapse_button.stories.tsx
+++ b/src/components/resizable_container/resizable_collapse_button.stories.tsx
@@ -8,6 +8,7 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
+import { hideStorybookControls } from '../../../.storybook/utils';
import { EuiPanel } from '../panel';
import { EuiResizableContainer } from './resizable_container';
@@ -19,19 +20,20 @@ import {
const meta: Meta = {
title: 'EuiResizableCollapseButton',
component: EuiResizableCollapseButton,
-};
-
-export default meta;
-type Story = StoryObj;
-
-export const Playground: Story = {
args: {
+ isVisible: true,
+ // Component defaults
direction: 'horizontal',
externalPosition: 'before',
internalPosition: 'middle',
- isVisible: true,
isCollapsed: false,
},
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Playground: Story = {
render: ({ isCollapsed, direction, ...args }) => (
([
+ 'externalPosition',
+ 'isVisible',
+ 'isCollapsed',
+ ]),
render: ({ direction, internalPosition }) => (
{(EuiResizablePanel, EuiResizableButton) => (
diff --git a/src/components/side_nav/side_nav.stories.tsx b/src/components/side_nav/side_nav.stories.tsx
index fdbfae7c9e1..9baf22f8336 100644
--- a/src/components/side_nav/side_nav.stories.tsx
+++ b/src/components/side_nav/side_nav.stories.tsx
@@ -8,6 +8,7 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
+import { hideStorybookControls } from '../../../.storybook/utils';
import { EuiText } from '../text';
@@ -16,6 +17,12 @@ import { EuiSideNav, EuiSideNavProps } from './side_nav';
const meta: Meta = {
title: 'EuiSideNav',
component: EuiSideNav,
+ args: {
+ // Component defaults
+ mobileBreakpoints: ['xs', 's'],
+ items: [],
+ isOpenOnMobile: false,
+ },
decorators: [
(Story) => (
@@ -29,14 +36,6 @@ const meta: Meta = {
export default meta;
type Story = StoryObj;
-const componentDefaults: EuiSideNavProps = {
- mobileBreakpoints: ['xs', 's'],
- items: [],
- // mobileTitle does not have defaults; they are being set here as they are shared between examples
- mobileTitle: 'Mobile navigation header',
- isOpenOnMobile: false,
-};
-
const sharedSideNavItems = [
{
name: 'Has nested children',
@@ -83,29 +82,28 @@ const sharedSideNavItems = [
export const Playground: Story = {
args: {
- ...componentDefaults,
heading: 'Elastic',
headingProps: { element: 'h1', screenReaderOnly: false },
items: sharedSideNavItems,
+ mobileTitle: 'Mobile navigation header',
},
};
export const MobileSideNav: Story = {
args: {
- ...componentDefaults,
isOpenOnMobile: true,
items: sharedSideNavItems,
mobileTitle: 'Toggle isOpenOnMobile in the controls panel',
},
- argTypes: {
- // This story demos the side nav on smaller screens; removing other props to streamline controls
- 'aria-label': { table: { disable: true } },
- heading: { table: { disable: true } },
- headingProps: { table: { disable: true } },
- items: { table: { disable: true } },
- renderItem: { table: { disable: true } },
- truncate: { table: { disable: true } },
- },
+ // This story demos the side nav on smaller screens; removing other props to streamline controls
+ argTypes: hideStorybookControls([
+ 'aria-label',
+ 'heading',
+ 'headingProps',
+ 'items',
+ 'renderItem',
+ 'truncate',
+ ]),
parameters: {
viewport: {
defaultViewport: 'mobile1',
@@ -115,7 +113,6 @@ export const MobileSideNav: Story = {
export const RenderItem: Story = {
args: {
- ...componentDefaults,
renderItem: ({ children }) => {children},
items: [
{
@@ -135,15 +132,15 @@ export const RenderItem: Story = {
},
],
},
- argTypes: {
- // This story demos the renderItem prop; removing other props to streamline controls
- 'aria-label': { table: { disable: true } },
- heading: { table: { disable: true } },
- headingProps: { table: { disable: true } },
- toggleOpenOnMobile: { table: { disable: true } },
- isOpenOnMobile: { table: { disable: true } },
- mobileBreakpoints: { table: { disable: true } },
- mobileTitle: { table: { disable: true } },
- truncate: { table: { disable: true } },
- },
+ // This story demos the renderItem prop; removing other props to streamline controls
+ argTypes: hideStorybookControls([
+ 'aria-label',
+ 'heading',
+ 'headingProps',
+ 'toggleOpenOnMobile',
+ 'isOpenOnMobile',
+ 'mobileBreakpoints',
+ 'mobileTitle',
+ 'truncate',
+ ]),
};
diff --git a/src/components/text_truncate/text_truncate.stories.tsx b/src/components/text_truncate/text_truncate.stories.tsx
index 82efe8a7755..d72d8f8cd90 100644
--- a/src/components/text_truncate/text_truncate.stories.tsx
+++ b/src/components/text_truncate/text_truncate.stories.tsx
@@ -9,6 +9,10 @@
import React, { useState } from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { css } from '@emotion/react';
+import {
+ hideStorybookControls,
+ disableStorybookControls,
+} from '../../../.storybook/utils';
import { EuiHighlight, EuiMark } from '../../components';
@@ -21,17 +25,17 @@ const meta: Meta = {
truncationOffset: { if: { arg: 'truncation', neq: 'startEnd' } }, // Should also not show on `middle`, but Storybook doesn't currently support multiple if conditions :(
truncationPosition: { if: { arg: 'truncation', eq: 'startEnd' } },
},
+ args: {
+ text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
+ // Component defaults
+ truncation: 'end',
+ ellipsis: '…',
+ },
};
export default meta;
type Story = StoryObj;
-const componentDefaults = {
- text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
- truncation: 'end',
- ellipsis: '…',
-} as const;
-
export const Playground: Story = {
render: (props) => (
@@ -39,7 +43,6 @@ export const Playground: Story = {
+ EuiTextTruncate provides customizable and
+ size-aware single line text truncation.
+
+
+ The four truncation styles supported are{' '}
+ start, end,{' '}
+ startEnd, and middle.
+ Resize the below demo to see how different truncation styles
+ respond to dynamic width changes.
+
- EuiTextTruncate provides customizable and
- size-aware single line text truncation.
-
-
- The four truncation styles supported are start,{' '}
- end, startEnd, and{' '}
- middle. Resize the below demo to see how
- different truncation styles respond to dynamic width changes.
-
- EuiTextTruncate attempts to mimic the behavior of{' '}
- text-overflow: ellipsis as closely as possible,
- although there may be edge cases and cross-browser issues, as this
- is essentially a{' '}
-
+
- browser implementation
- {' '}
- we are trying to polyfill.
+
+ EuiTextTruncate attempts to mimic the
+ behavior of text-overflow: ellipsis as
+ closely as possible, although there may be edge cases and
+ cross-browser issues, as this is essentially a{' '}
+
+ browser implementation
+ {' '}
+ we are trying to polyfill.
+
+
+
+ Screen readers should ignore the truncated text and only
+ read out the full text.
+
+
+ Sighted mouse users will be able to briefly hover over the
+ truncated text and read the full text in a native browser
+ title tooltip.
+
+
+ For mouse users, double clicking to select the truncated
+ line should allow copying the full untruncated text.
+
+ By default, EuiTextTruncate uses the unicode
+ character for horizontal ellipis. It can be customized via the{' '}
+ ellipsis prop as necessary (e.g. for specific
+ languages, extra punctuation, etc).
-
-
- Screen readers should ignore the truncated text and only read
- out the full text.
-
-
- Sighted mouse users will be able to briefly hover over the
- truncated text and read the full text in a native browser title
- tooltip.
-
-
- For mouse users, double clicking to select the truncated line
- should allow copying the full untruncated text.
-
+ The start and end truncation
+ types support a truncationOffset property that
+ allows preserving a specified number of characters at either the
+ start or end of the text. Increase or decrease the number control
+ below to see the prop in action.
+
+ The startEnd truncation type supports a{' '}
+ truncationPosition property. By default,{' '}
+ startEnd anchors the displayed text to the
+ middle of the string. However, you may prefer to display a
+ specific subsection of the full text closer to the start or end,
+ which this prop allows.
+
+
+ This behavior will intelligently detect when positions are near
+ enough to the start or end of the text to omit leading or
+ trailing ellipses when necessary.
+
+
+ Increase or decrease the number control below to see the prop in
+ action.
+
- By default, EuiTextTruncate uses the unicode
- character for horizontal ellipis. It can be customized via the{' '}
- ellipsis prop as necessary (e.g. for specific
- languages, extra punctuation, etc).
-
+ By default, EuiTextTruncate will automatically
+ output the calculated truncated string. You can optionally
+ override this by passing a render prop function to{' '}
+ children, which allows for more flexible text
+ rendering.
+
+
+ The below example demonstrates a primary use case for the render
+ prop and the truncationPosition prop. If a
+ user is searching for a specific word in truncated text, you can
+ use{' '}
+
+ EuiHighlight or EuiMark
+ {' '}
+ to highlight the search term, and passing the index of the found
+ word to truncationPosition ensures the search
+ term is always visible to the user.
+
- The start and end truncation
- types support a truncationOffset property that
- allows preserving a specified number of characters at either the start
- or end of the text. Increase or decrease the number control below to
- see the prop in action.
-
+ EuiTextTruncate uses a canvas element under the
+ hood to manipulate text and calculate whether the text width
+ fits within the available width. Additionally, by default, the
+ component will include its own resize observer in order to react
+ to width changes.
+
+
+ These functionalities can cause performance issues if the
+ component is rendered over hundreds of times per page, and we
+ would strongly recommend using caution when doing so. Several
+ escape hatches are available for performance improvements:
+
+ Pass a width prop to skip initializing a
+ resize observer for each component instance. For text within a
+ container of the same width, we would strongly recommend
+ applying a single resize observer to the parent container and
+ passing that width to all child{' '}
+ EuiTextTruncates. Additionally, you may want
+ to consider{' '}
+
+ throttling
+ {' '}
+ any resize observers or width-based logic.
+
+
+ Use{' '}
+
+ virtualization
+ {' '}
+ to reduce the number of rendered elements visible at any given
+ time. For over hundreds of instances, this will generally be
+ the most effective solution for performance or rerender
+ issues.
+
+
+ If necessary, consider pulling out the underlying{' '}
+ TruncationUtils and re-using the same
+ canvas context, as opposed to repeatedly creating new ones.
+
- The startEnd truncation type supports a{' '}
- truncationPosition property. By default,{' '}
- startEnd anchors the displayed text to the middle
- of the string. However, you may prefer to display a specific
- subsection of the full text closer to the start or end, which this
- prop allows.
-
-
- This behavior will intelligently detect when positions are near
- enough to the start or end of the text to omit leading or trailing
- ellipses when necessary.
-
-
- Increase or decrease the number control below to see the prop in
- action.
-
+ EuiTextBlockTruncate allows truncating text
+ after a set number of wrapping lines.
+
+
+ Please note: This component is currently a quick shortcut for
+ the{' '}
+
+ CSS line-clamp
+ {' '}
+ property. This means that truncating at the end of the text is
+ the default, and there are currently no plans to add JavaScript
+ customization for this behavior.
+
- By default, EuiTextTruncate will automatically
- output the calculated truncated string. You can optionally override
- this by passing a render prop function to{' '}
- children, which allows for more flexible text
- rendering.
-
-
- The below example demonstrates a primary use case for the render
- prop and the truncationPosition prop. If a user
- is searching for a specific word in truncated text, you can use{' '}
-
- EuiHighlight or EuiMark
- {' '}
- to highlight the search term, and passing the index of the found
- word to truncationPosition ensures the search
- term is always visible to the user.
-
- EuiTextTruncate uses a canvas element under the
- hood to manipulate text and calculate whether the text width fits
- within the available width. Additionally, by default, the component
- will include its own resize observer in order to react to width
- changes.
-
-
- These functionalities can cause performance issues if the component
- is rendered over hundreds of times per page, and we would strongly
- recommend using caution when doing so. Several escape hatches are
- available for performance improvements:
-
- Pass a width prop to skip initializing a resize
- observer for each component instance. For text within a container
- of the same width, we would strongly recommend applying a single
- resize observer to the parent container and passing that width to
- all child EuiTextTruncates. Additionally, you may
- want to consider{' '}
-
- throttling
- {' '}
- any resize observers or width-based logic.
-
-
- Use{' '}
-
- virtualization
- {' '}
- to reduce the number of rendered elements visible at any given
- time. For over hundreds of instances, this will generally be the
- most effective solution for performance or rerender issues.
-
-
- If necessary, consider pulling out the underlying{' '}
- TruncationUtils and re-using the same canvas
- context, as opposed to repeatedly creating new ones.
-
-
- >
- ),
- demo: ,
- source: [{ type: GuideSectionTypes.TSX, code: performanceSource }],
- props: { EuiTextTruncate },
- snippet: ``,
},
],
};
diff --git a/src/components/text_truncate/index.ts b/src/components/text_truncate/index.ts
index a2785e5a6c7..4d5bbcb18b0 100644
--- a/src/components/text_truncate/index.ts
+++ b/src/components/text_truncate/index.ts
@@ -12,4 +12,7 @@ export type {
} from './text_truncate';
export { EuiTextTruncate } from './text_truncate';
+export type { EuiTextBlockTruncateProps } from './text_block_truncate';
+export { EuiTextBlockTruncate } from './text_block_truncate';
+
export { TruncationUtils } from './utils';
diff --git a/src/components/text_truncate/text_block_truncate.stories.tsx b/src/components/text_truncate/text_block_truncate.stories.tsx
new file mode 100644
index 00000000000..fae93b3b2ca
--- /dev/null
+++ b/src/components/text_truncate/text_block_truncate.stories.tsx
@@ -0,0 +1,45 @@
+/*
+ * 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 { EuiPanel } from '../panel';
+
+import {
+ EuiTextBlockTruncate,
+ EuiTextBlockTruncateProps,
+} from './text_block_truncate';
+
+const meta: Meta = {
+ title: 'EuiTextBlockTruncate',
+ component: EuiTextBlockTruncate,
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Playground: Story = {
+ render: ({ children, ...args }) => (
+
+
{children}
+
+ ),
+ args: {
+ lines: 3,
+ children:
+ "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
+ },
+};
diff --git a/src/components/text_truncate/text_block_truncate.test.tsx b/src/components/text_truncate/text_block_truncate.test.tsx
new file mode 100644
index 00000000000..d954c93d6bf
--- /dev/null
+++ b/src/components/text_truncate/text_block_truncate.test.tsx
@@ -0,0 +1,45 @@
+/*
+ * 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 { shouldRenderCustomStyles } from '../../test/internal';
+
+import { EuiTextBlockTruncate } from './text_block_truncate';
+
+describe('EuiTextBlockTruncate', () => {
+ shouldRenderCustomStyles();
+
+ it('renders', () => {
+ const { container } = render(
+ Hello world
+ );
+ expect(container.firstChild).toMatchInlineSnapshot(`
+
+ Hello world
+
+ `);
+ });
+
+ it('allows cloning styles onto the child element instead of rendering an extra div wrapper', () => {
+ const { container } = render(
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eu
+ condimentum ipsum, nec ornare metus. Sed egestas elit nec placerat
+ suscipit. Cras pulvinar nisi eget enim sodales fringilla. Aliquam
+ lobortis lorem at ornare aliquet. Mauris laoreet laoreet mollis.
+ Pellentesque aliquet tortor dui, non luctus turpis pulvinar vitae.
+ Nunc ultrices scelerisque erat eu rutrum. Nam at ligula enim. Ut nec
+ nisl faucibus, euismod neque ut, aliquam nisl. Donec eu ante ut arcu
+ rutrum blandit nec ac nisl. In elementum id enim vitae aliquam. In
+ sagittis, neque vitae ultricies interdum, sapien justo efficitur
+ ligula, sit amet fermentum nisl magna sit amet turpis. Nulla facilisi.
+ Proin nec viverra mi. Morbi dolor arcu, ornare non consequat et,
+ viverra dapibus tellus.
+
{
/>
+
+
+ We strongly recommend using relative (rem or{' '}
+ em) units instead of px when
+ possible{' '}
+ >
+ }
+ >
+
+ Relative font units respect configured browser default font sizes,
+ which some users may set to larger than than the 16px default due to,
+ e.g. visual impairment, monitor size, or personal preference.{' '}
+
+ Read more on accessible text resizing.
+
+
+
tableLayout="auto"
diff --git a/src/components/provider/provider.stories.tsx b/src/components/provider/provider.stories.tsx
new file mode 100644
index 00000000000..7eb59fe5767
--- /dev/null
+++ b/src/components/provider/provider.stories.tsx
@@ -0,0 +1,43 @@
+/*
+ * 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 { EuiProvider, EuiProviderProps } from './provider';
+
+const meta: Meta> = {
+ title: 'EuiProvider',
+ component: EuiProvider,
+ argTypes: {
+ colorMode: {
+ control: 'select',
+ options: ['light', 'dark', 'inverse', 'LIGHT', 'DARK', 'INVERSE'],
+ },
+ modify: { control: 'object' },
+ componentDefaults: { control: 'object' },
+ globalStyles: { control: 'boolean' },
+ utilityClasses: { control: 'boolean' },
+ },
+};
+
+export default meta;
+type Story = StoryObj>;
+
+export const FontDefaultUnits: Story = {
+ render: () => (
+ <>
+ Change `modify.font.defaultUnits` to{' '}
+ `rem`, `em`, or `px` and then inspect this demo's `html`
+ CSS
+ >
+ ),
+ args: {
+ modify: { font: { defaultUnits: 'rem' } },
+ },
+};
diff --git a/src/global_styling/reset/global_styles.tsx b/src/global_styling/reset/global_styles.tsx
index f485bd0199c..55cd8d5cc2c 100644
--- a/src/global_styling/reset/global_styles.tsx
+++ b/src/global_styling/reset/global_styles.tsx
@@ -37,12 +37,15 @@ export const EuiGlobalStyles = ({}: EuiGlobalStylesProps) => {
* This font reset sets all our base font/typography related properties
* that are needed to override browser-specific element settings.
*/
- const fontReset = `
- font-family: ${font.family};
- font-size: ${`${font.scale[font.body.scale] * base}px`};
- line-height: ${base / (font.scale[font.body.scale] * base)};
- font-weight: ${font.weight[font.body.weight]};
- `;
+ const fontBodyScale = font.scale[font.body.scale];
+ const fontReset = {
+ fontFamily: font.family,
+ fontSize: `${
+ font.defaultUnits === 'px' ? fontBodyScale * base : fontBodyScale
+ }${font.defaultUnits}`,
+ lineHeight: base / (fontBodyScale * base),
+ fontWeight: font.weight[font.body.weight],
+ };
/**
* Final styles
@@ -70,7 +73,10 @@ export const EuiGlobalStyles = ({}: EuiGlobalStylesProps) => {
input,
textarea,
select {
- ${fontReset}
+ ${{
+ ...fontReset,
+ fontSize: '1rem', // Inherit from html root
+ }}
}
// Chrome has opinionated select:disabled opacity styles that need to be overridden
diff --git a/upcoming_changelogs/7182.md b/upcoming_changelogs/7182.md
new file mode 100644
index 00000000000..aa34dd7ed82
--- /dev/null
+++ b/upcoming_changelogs/7182.md
@@ -0,0 +1,7 @@
+**Breaking changes**
+
+- EUI's global body font-size now respects the `font.defaultUnits` token. This means that the global font size will use the `rem` unit by default, instead of `px`.
+
+**Accessibility**
+
+- When using `rem` or `em` font units, EUI now respects, instead of ignoring, browser default font sizes set by end users.
From e09776c31e8f068a0643a57c373f7067dd37ab04 Mon Sep 17 00:00:00 2001
From: Cee Chen <549407+cee-chen@users.noreply.github.com>
Date: Wed, 4 Oct 2023 19:35:59 -0700
Subject: [PATCH 11/38] [EuiComboBox] Update to dogfood `EuiInputPopover`
(#7246)
---
src-docs/src/views/popover/input_popover.tsx | 1 +
.../__snapshots__/combo_box.test.tsx.snap | 1408 +++++------------
src/components/combo_box/combo_box.spec.tsx | 237 ++-
src/components/combo_box/combo_box.test.tsx | 934 ++++++-----
src/components/combo_box/combo_box.tsx | 420 ++---
.../combo_box_input/combo_box_input.tsx | 25 +-
.../_combo_box_options_list.scss | 20 +-
.../combo_box_options_list.tsx | 239 +--
src/components/combo_box/index.ts | 1 -
src/components/combo_box/types.ts | 5 -
src/components/popover/input_popover.spec.tsx | 52 +
src/components/popover/input_popover.tsx | 51 +-
src/test/rtl/component_helpers.d.ts | 2 +
src/test/rtl/component_helpers.ts | 14 +-
upcoming_changelogs/7246.md | 2 +
15 files changed, 1361 insertions(+), 2050 deletions(-)
create mode 100644 upcoming_changelogs/7246.md
diff --git a/src-docs/src/views/popover/input_popover.tsx b/src-docs/src/views/popover/input_popover.tsx
index 1e87b9ee1a3..1b2fd51d14d 100644
--- a/src-docs/src/views/popover/input_popover.tsx
+++ b/src-docs/src/views/popover/input_popover.tsx
@@ -21,6 +21,7 @@ export default () => {
setIsPopoverOpen(false)}
+ closeOnScroll={true}
input={
setIsPopoverOpen(true)}
diff --git a/src/components/combo_box/__snapshots__/combo_box.test.tsx.snap b/src/components/combo_box/__snapshots__/combo_box.test.tsx.snap
index 6bf8b35fb61..a1e7f5f4028 100644
--- a/src/components/combo_box/__snapshots__/combo_box.test.tsx.snap
+++ b/src/components/combo_box/__snapshots__/combo_box.test.tsx.snap
@@ -1,1094 +1,430 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`EuiComboBox is rendered 1`] = `
+exports[`EuiComboBox renders 1`] = `
-
-
-
-
+
+
+
+
+
+
+
`;
-exports[`props aria-label attribute is rendered 1`] = `
-