diff --git a/src-docs/src/views/theme/consuming_emotion_theme.tsx b/src-docs/src/views/theme/consuming_emotion_theme.tsx
new file mode 100644
index 00000000000..88cefedf66b
--- /dev/null
+++ b/src-docs/src/views/theme/consuming_emotion_theme.tsx
@@ -0,0 +1,49 @@
+import React from 'react';
+import { ThemeProvider, css } from '@emotion/react';
+import { EuiIcon, EuiText } from '../../../../src';
+
+export default () => {
+ return (
+
+ css`
+ background-color: ${euiTheme.colors.lightestShade};
+ padding: ${euiTheme.size.l};
+ `}
+ >
+ ({
+ color:
+ colorMode === 'LIGHT'
+ ? euiTheme.colors.primary
+ : euiTheme.colors.accent,
+ })}
+ />{' '}
+ This box sets its icon color, background color, and padding via Emotion
+ theme context
+
+
+
+ css`
+ color: ${theme.brandColor};
+ background-color: ${theme.backgroundColor};
+ padding: ${theme.padding};
+ `}
+ >
+ This box sets its own Emotion ThemeProvider and theme variables
+
+
+
+ );
+};
diff --git a/src-docs/src/views/theme/theme_example.js b/src-docs/src/views/theme/theme_example.js
index 7b469e1406b..969a9f6c230 100644
--- a/src-docs/src/views/theme/theme_example.js
+++ b/src-docs/src/views/theme/theme_example.js
@@ -12,6 +12,9 @@ const consumingSource = require('!!raw-loader!./consuming');
import { ConsumingHOC } from './consuming_hoc';
const consumingHOCSource = require('!!raw-loader!./consuming_hoc');
+import ConsumingEmotionTheme from './consuming_emotion_theme';
+const consumingEmotionThemeSource = require('!!raw-loader!./consuming_emotion_theme');
+
import OverrideSimple from './override_simple';
const overrideSimpleSource = require('!!raw-loader!./override_simple');
@@ -154,6 +157,36 @@ export const ThemeExample = {
),
demo: ,
},
+ {
+ title: "Consuming with Emotion's theming",
+ source: [
+ {
+ type: GuideSectionTypes.TSX,
+ code: consumingEmotionThemeSource,
+ },
+ ],
+ text: (
+ <>
+
+ EuiThemeProvider by default sets an{' '}
+
+ Emotion theme context
+ {' '}
+ with the results of useEuiTheme(). This is a
+ syntactical sugar convenience that allows you to take advantage of
+ Emotion's styled syntax, or use a function in the{' '}
+ css prop.
+
+
+ If you prefer to use or access your own custom Emotion theme, you
+ can completely override EUI's passed theme at any time with your own{' '}
+ ThemeProvider - see the second box below for an
+ example.
+
+ >
+ ),
+ demo: ,
+ },
{
title: 'Simple instance overrides',
source: [
diff --git a/src/custom_typings/emotion.d.ts b/src/custom_typings/emotion.d.ts
new file mode 100644
index 00000000000..53579effe97
--- /dev/null
+++ b/src/custom_typings/emotion.d.ts
@@ -0,0 +1,17 @@
+/*
+ * 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 '@emotion/react';
+import { UseEuiTheme } from '../services/theme';
+
+/**
+ * @see https://emotion.sh/docs/typescript#define-a-theme
+ */
+declare module '@emotion/react' {
+ export interface Theme extends UseEuiTheme {}
+}
diff --git a/src/services/theme/emotion.test.tsx b/src/services/theme/emotion.test.tsx
new file mode 100644
index 00000000000..b3c8cba2af1
--- /dev/null
+++ b/src/services/theme/emotion.test.tsx
@@ -0,0 +1,84 @@
+/*
+ * 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 { ThemeProvider } from '@emotion/react';
+import { render } from '../../test/rtl';
+
+import { EuiTextColor } from '../../components/text';
+import { EuiEmotionThemeProvider } from './emotion';
+
+describe('EuiEmotionThemeProvider', () => {
+ it("allows consumers to use Emotion's theme context by default", () => {
+ const { container, getByTestSubject } = render(
+
+ ({ color: euiTheme.colors.primary })}
+ data-test-subj="consumer"
+ >
+ hello world
+
+
+ );
+
+ expect(getByTestSubject('consumer')).toHaveStyleRule('color', '#07C');
+
+ expect(container.firstChild).toMatchInlineSnapshot(`
+
+ hello world
+
+ `);
+ });
+
+ it("allows consumers to override EUI's ThemeProvider with their own theme", () => {
+ const customTheme = {
+ brandColor: 'pink',
+ };
+
+ const { container, getByTestSubject } = render(
+
+ {/* @ts-ignore - consumers would set their own emotion.d.ts */}
+
+ ({ color: theme.brandColor })}
+ data-test-subj="consumer"
+ >
+ hello
+
+ {/* Custom Emotion themes should not break EUI's own Emotion styles */}
+
+ world
+
+
+
+ );
+
+ expect(getByTestSubject('consumer')).toHaveStyleRule('color', 'pink');
+ expect(getByTestSubject('eui')).toHaveStyleRule('color', '#ba3d76');
+
+ expect(container).toMatchInlineSnapshot(`
+
+
+ hello
+
+
+ world
+
+
+ `);
+ });
+});
diff --git a/src/services/theme/emotion.tsx b/src/services/theme/emotion.tsx
new file mode 100644
index 00000000000..a28788028ab
--- /dev/null
+++ b/src/services/theme/emotion.tsx
@@ -0,0 +1,28 @@
+/*
+ * 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, { FunctionComponent, PropsWithChildren } from 'react';
+import { ThemeProvider } from '@emotion/react';
+
+import { useEuiTheme } from './hooks';
+
+/**
+ * @see https://emotion.sh/docs/theming
+ * This Emotion theme provider is added for *consumer usage* & convenience only.
+ *
+ * EUI should stick to using our own context/`useEuiTheme` internally
+ * instead of Emotion's shorthand `css={theme => {}}` API. If consumers
+ * set their own theme via ; EUI's styles should continue
+ * working as-is.
+ */
+export const EuiEmotionThemeProvider: FunctionComponent<
+ PropsWithChildren<{}>
+> = ({ children }) => {
+ const euiThemeContext = useEuiTheme();
+ return {children};
+};
diff --git a/src/services/theme/hooks.test.tsx b/src/services/theme/hooks.test.tsx
index ca3a44c785d..ecbc819e855 100644
--- a/src/services/theme/hooks.test.tsx
+++ b/src/services/theme/hooks.test.tsx
@@ -10,7 +10,7 @@ import React from 'react';
import { renderHook } from '@testing-library/react-hooks';
import { render } from '@testing-library/react';
-import { setEuiDevProviderWarning } from './provider';
+import { setEuiDevProviderWarning } from './warning';
import {
useEuiTheme,
UseEuiTheme,
diff --git a/src/services/theme/hooks.tsx b/src/services/theme/hooks.tsx
index f23885726ed..ec74ac1b8ed 100644
--- a/src/services/theme/hooks.tsx
+++ b/src/services/theme/hooks.tsx
@@ -14,7 +14,7 @@ import {
EuiColorModeContext,
defaultComputedTheme,
} from './context';
-import { getEuiDevProviderWarning } from './provider';
+import { getEuiDevProviderWarning } from './warning';
import {
EuiThemeColorModeStandard,
EuiThemeModifications,
diff --git a/src/services/theme/index.ts b/src/services/theme/index.ts
index 76e898cb700..7c46c4f81ff 100644
--- a/src/services/theme/index.ts
+++ b/src/services/theme/index.ts
@@ -16,11 +16,8 @@ export {
export type { UseEuiTheme, WithEuiThemeProps } from './hooks';
export { useEuiTheme, withEuiTheme, RenderWithEuiTheme } from './hooks';
export type { EuiThemeProviderProps } from './provider';
-export {
- EuiThemeProvider,
- getEuiDevProviderWarning,
- setEuiDevProviderWarning,
-} from './provider';
+export { EuiThemeProvider } from './provider';
+export { getEuiDevProviderWarning, setEuiDevProviderWarning } from './warning';
export {
buildTheme,
computed,
diff --git a/src/services/theme/provider.tsx b/src/services/theme/provider.tsx
index 3d9195d7190..a2a7347d883 100644
--- a/src/services/theme/provider.tsx
+++ b/src/services/theme/provider.tsx
@@ -28,6 +28,7 @@ import {
EuiModificationsContext,
EuiColorModeContext,
} from './context';
+import { EuiEmotionThemeProvider } from './emotion';
import { buildTheme, getColorMode, getComputed, mergeDeep } from './utils';
import {
EuiThemeColorMode,
@@ -36,12 +37,6 @@ import {
EuiThemeModifications,
} from './types';
-type LEVELS = 'log' | 'warn' | 'error';
-let providerWarning: LEVELS | undefined = undefined;
-export const setEuiDevProviderWarning = (level: LEVELS | undefined) =>
- (providerWarning = level);
-export const getEuiDevProviderWarning = () => providerWarning;
-
export interface EuiThemeProviderProps {
theme?: EuiThemeSystem;
colorMode?: EuiThemeColorMode;
@@ -190,7 +185,9 @@ export const EuiThemeProvider = ({
- {renderedChildren}
+
+ {renderedChildren}
+
diff --git a/src/services/theme/warning.ts b/src/services/theme/warning.ts
new file mode 100644
index 00000000000..04311bc0d81
--- /dev/null
+++ b/src/services/theme/warning.ts
@@ -0,0 +1,16 @@
+/*
+ * 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.
+ */
+
+type LEVELS = 'log' | 'warn' | 'error';
+
+let providerWarning: LEVELS | undefined = undefined;
+
+export const setEuiDevProviderWarning = (level: LEVELS | undefined) =>
+ (providerWarning = level);
+
+export const getEuiDevProviderWarning = () => providerWarning;
diff --git a/upcoming_changelogs/6913.md b/upcoming_changelogs/6913.md
new file mode 100644
index 00000000000..6330e00f0f9
--- /dev/null
+++ b/upcoming_changelogs/6913.md
@@ -0,0 +1,2 @@
+- Updated `EuiThemeProvider` to set an Emotion theme context that returns the values of `useEuiTheme()`
+
diff --git a/wiki/contributing-to-eui/developing/writing-styles-with-emotion.md b/wiki/contributing-to-eui/developing/writing-styles-with-emotion.md
index b5156ee51e9..b353b3b3e12 100644
--- a/wiki/contributing-to-eui/developing/writing-styles-with-emotion.md
+++ b/wiki/contributing-to-eui/developing/writing-styles-with-emotion.md
@@ -545,3 +545,11 @@ Emotion provides its own `createElement` function; existing uses of `import {cre
Unfortunately, a limitation of the CSS-in-JS syntax parser we're using is that `//` comments throw this error (see https://github.com/hudochenkov/postcss-styled-syntax#known-issues).
You must convert all `//` comments to standard CSS `/* */` comments instead.
+
+### Should I use Emotion's `css={theme => {}}` API?
+
+No. The [Emotion theme context](https://emotion.sh/docs/theming) that we include by default in `EuiThemeProvider` is intended for **consumer usage** and convenience, particularly with the goal of making adoption by Kibana devs easier.
+
+It is not intended for internal EUI usage, primarily because it can be too easily overridden by consumers who want to use their own custom Emotion theme vars and set their own ``. If this happens, and we're relying on Emotion's theme context, all of EUI's styles will break.
+
+When you're styling EUI components internally, you should use only EUI's theme context/`useEuiTheme()`, and not on Emotion's theme context (i.e., do not use the `css={theme => {}}` API).