diff --git a/packages/eui/.storybook/decorator.tsx b/packages/eui/.storybook/decorator.tsx
new file mode 100644
index 00000000000..10e265a13de
--- /dev/null
+++ b/packages/eui/.storybook/decorator.tsx
@@ -0,0 +1,122 @@
+/*
+ * 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, useMemo, FunctionComponent } from 'react';
+import { css } from '@emotion/react';
+import type { Preview } from '@storybook/react';
+
+import { EuiThemeColorMode } from '../src/services';
+import { EuiProvider, EuiProviderProps } from '../src/components/provider';
+
+/**
+ * Primary EuiProvider decorator to wrap around all stories
+ * @see https://storybook.js.org/docs/writing-stories/decorators
+ */
+export const EuiProviderDecorator: FunctionComponent<
+ EuiProviderProps<{}> & {
+ writingMode: WritingModes;
+ }
+> = ({ children, writingMode, ...euiProviderProps }) => {
+ // Append portals into Storybook's root div (rather than
)
+ // so that loki correctly captures them for VRT screenshots
+ const [sibling, setPortalSibling] = useState(null);
+ const portalInsert = useMemo(() => {
+ if (sibling) {
+ return {
+ EuiPortal: { insert: { sibling, position: 'after' as const } },
+ };
+ }
+ }, [sibling]);
+
+ // Set CSS writing mode/direction on story-wrapper
+ const writingModeCss = useMemo(
+ () => [{ label: 'writingMode' }, writingModeStyles[writingMode]],
+ [writingMode]
+ );
+
+ return (
+
+
+ {portalInsert && children}
+
+
+ );
+};
+
+/**
+ * Styles used for testing CSS logical properties
+ * @see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_writing_modes
+ * @see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties
+ */
+const writingModeStyles = {
+ ltr: css`
+ direction: ltr;
+ `,
+ rtl: css`
+ direction: rtl;
+ `,
+ 'vertical-lr': css`
+ writing-mode: vertical-lr;
+ `,
+ 'vertical-rl': css`
+ writing-mode: vertical-rl;
+ `,
+ // Sideways RL is the same as vertical RL
+ sideways: css`
+ writing-mode: sideways-lr;
+ `,
+};
+type WritingModes = keyof typeof writingModeStyles;
+
+/**
+ * Storybook toolbar types - define these separately so that we can ensure
+ * their values match ones that EuiProviderDecorator expects
+ */
+type ToolbarDisplay = { title: string; icon: string };
+
+const storybookToolbarColorModes: Array<
+ ToolbarDisplay & { value: EuiThemeColorMode }
+> = [
+ { value: 'light', title: 'Light mode', icon: 'circlehollow' },
+ { value: 'dark', title: 'Dark mode', icon: 'circle' },
+];
+
+const storybookToolbarWritingModes: Array<
+ ToolbarDisplay & { value: WritingModes }
+> = [
+ { value: 'ltr', title: 'LTR', icon: 'arrowleft' },
+ { value: 'rtl', title: 'RTL', icon: 'arrowright' },
+ { value: 'vertical-lr', title: 'Vertical LTR', icon: 'arrowup' },
+ { value: 'vertical-rl', title: 'Vertical RTL', icon: 'arrowdown' },
+ { value: 'sideways', title: 'Sideways LTR', icon: 'collapse' },
+];
+
+/**
+ * Export Storybook toolbar globals/context that affect our EuiProvider decorator
+ * @see https://storybook.js.org/docs/essentials/toolbars-and-globals
+ */
+export const euiProviderDecoratorGlobals: Preview['globalTypes'] = {
+ colorMode: {
+ description: 'Color mode for EuiProvider theme',
+ defaultValue: 'light',
+ toolbar: {
+ title: 'Color mode',
+ items: storybookToolbarColorModes,
+ dynamicTitle: true,
+ },
+ },
+ writingMode: {
+ description: 'Writing mode for testing logical property directions',
+ defaultValue: 'ltr',
+ toolbar: {
+ title: 'Writing mode',
+ items: storybookToolbarWritingModes,
+ dynamicTitle: true,
+ },
+ },
+};
diff --git a/packages/eui/.storybook/preview.tsx b/packages/eui/.storybook/preview.tsx
index b103c083dd0..c34435f5032 100644
--- a/packages/eui/.storybook/preview.tsx
+++ b/packages/eui/.storybook/preview.tsx
@@ -10,7 +10,6 @@
import React from 'react';
import type { Preview } from '@storybook/react';
-import { useState, useMemo } from '@storybook/preview-api';
import { MINIMAL_VIEWPORTS } from '@storybook/addon-viewport';
/*
@@ -29,12 +28,6 @@ Object.entries(typeToPathMap).forEach(async ([iconType, iconFileName]) => {
});
appendIconComponentCache(iconCache);
-/*
- * Theming
- */
-import { EuiProvider } from '../src/components/provider';
-import { writingModeStyles } from './writing_mode.styles';
-
/**
* Ensure that any provider errors throw & warn us early
*/
@@ -42,82 +35,25 @@ import { setEuiDevProviderWarning } from '../src/services';
setEuiDevProviderWarning('error');
/**
- * Prop controls
+ * Custom global decorators
*/
-
-import type { CommonProps } from '../src/components/common';
-
import { customJsxDecorator } from './addons/code-snippet/decorators/jsx_decorator';
-import { hideStorybookControls } from './utils';
+import { EuiProviderDecorator, euiProviderDecoratorGlobals } from './decorator';
const preview: Preview = {
decorators: [
customJsxDecorator,
- (Story, context) => {
- const [portalSibling, setPortalSibling] = useState(
- null
- );
- const portalInsert = useMemo(() => {
- if (portalSibling) {
- return {
- EuiPortal: {
- insert: { sibling: portalSibling, position: 'after' as const },
- },
- };
- }
- }, [portalSibling]);
-
- return (
-
- */
- id="story-wrapper"
- css={[
- writingModeStyles.writingMode,
- // @ts-ignore - we're manually ensuring `writingMode` globals match our Emotion style keys
- writingModeStyles[context.globals.writingMode],
- ]}
- >
- {portalInsert && }
-
-
- );
- },
+ (Story, context) => (
+
+
+
+ ),
],
- globalTypes: {
- colorMode: {
- description: 'Color mode for EuiProvider theme',
- defaultValue: 'light',
- toolbar: {
- title: 'Color mode',
- items: [
- { value: 'light', title: 'Light mode', icon: 'circlehollow' },
- { value: 'dark', title: 'Dark mode', icon: 'circle' },
- ],
- dynamicTitle: true,
- },
- },
- writingMode: {
- description: 'Writing mode for testing logical property directions',
- defaultValue: 'ltr',
- toolbar: {
- title: 'Writing mode',
- items: [
- { value: 'ltr', title: 'LTR', icon: 'arrowleft' },
- { value: 'rtl', title: 'RTL', icon: 'arrowright' },
- { value: 'vertical-lr', title: 'Vertical LTR', icon: 'arrowup' },
- { value: 'vertical-rl', title: 'Vertical RTL', icon: 'arrowdown' },
- { value: 'sideways', title: 'Sideways LTR', icon: 'collapse' },
- ],
- dynamicTitle: true,
- },
- },
- },
+ globalTypes: { ...euiProviderDecoratorGlobals },
parameters: {
backgrounds: { disable: true }, // Use colorMode instead
options: {
@@ -154,10 +90,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, e.g. by passing
// `argTypes: { 'data-test-subj': { table: { disable: false } } }`
+import type { CommonProps } from '../src/components/common';
+import { hideStorybookControls } from './utils';
hideStorybookControls(preview, [
'css',
'className',
diff --git a/packages/eui/.storybook/writing_mode.styles.ts b/packages/eui/.storybook/writing_mode.styles.ts
deleted file mode 100644
index 9eb94d2793a..00000000000
--- a/packages/eui/.storybook/writing_mode.styles.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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 { css } from '@emotion/react';
-
-/**
- * Used for testing CSS logical properties
- * @see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_writing_modes
- * @see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties
- */
-export const writingModeStyles = {
- writingMode: css``,
- ltr: css`
- direction: ltr;
- `,
- rtl: css`
- direction: rtl;
- `,
- 'vertical-lr': css`
- writing-mode: vertical-lr;
- `,
- 'vertical-rl': css`
- writing-mode: vertical-rl;
- `,
- // Sideways RL is the same as vertical RL
- sideways: css`
- writing-mode: sideways-lr;
- `,
-};