+ While all props can be individually customized via props, some
+ components can have their default props customized globally via{' '}
+ EuiProvider's{' '}
+ componentDefaults API.{' '}
+
+ Read more in EuiProvider's documentation
+
+ .
+
+
+
+
+ {euiProviderComponentDefaultsSnippet}
+
+ >
+ ),
+ },
],
};
diff --git a/src-docs/src/views/provider/provider_component_defaults.tsx b/src-docs/src/views/provider/provider_component_defaults.tsx
new file mode 100644
index 000000000000..f2561c5a6f1f
--- /dev/null
+++ b/src-docs/src/views/provider/provider_component_defaults.tsx
@@ -0,0 +1,22 @@
+import React, { FunctionComponent } from 'react';
+
+import { EuiComponentDefaults } from '../../../../src/components/provider/component_defaults';
+
+// Used to generate a "component" that is parsed for its types
+// and used to generate a prop table
+export const EuiComponentDefaultsProps: FunctionComponent<
+ EuiComponentDefaults
+> = () => <>>;
+
+// Used by both getting started and EuiProvider component documentation pages
+// Exported in one place for DRYness
+export const euiProviderComponentDefaultsSnippet = `
+
+
+`;
diff --git a/src-docs/src/views/provider/provider_example.js b/src-docs/src/views/provider/provider_example.js
index a6ac1a53ec6f..c01f8a9b5247 100644
--- a/src-docs/src/views/provider/provider_example.js
+++ b/src-docs/src/views/provider/provider_example.js
@@ -8,6 +8,7 @@ import {
EuiCodeBlock,
EuiLink,
EuiSpacer,
+ EuiCallOut,
} from '../../../../src/components';
import { GuideSectionPropsTable } from '../../components/guide_section/guide_section_parts/guide_section_props_table';
@@ -15,6 +16,10 @@ import { GuideSectionPropsTable } from '../../components/guide_section/guide_sec
import Setup from './provider_setup';
import GlobalStyles from './provider_styles';
import Warnings from './provider_warning';
+import {
+ EuiComponentDefaultsProps,
+ euiProviderComponentDefaultsSnippet,
+} from './provider_component_defaults';
export const ProviderExample = {
title: 'Provider',
@@ -135,6 +140,66 @@ export const ProviderExample = {
),
},
+ {
+ title: 'Component defaults',
+ isBeta: true,
+ text: (
+
+
+
+ This functionality is still currently in beta, and the list of
+ components as well as defaults that EUI will be supporting is
+ still under consideration. If you have a component you would like
+ to see added, feel free to{' '}
+
+ discuss that request in EUI's GitHub repo
+
+ .
+
+
+
+
+
+ All EUI components ship with a set of baseline defaults that can
+ usually be configured via props. For example,{' '}
+
+ EuiFocusTrap
+ {' '}
+ defaults to crossFrame={'{false}'} - i.e., it
+ does not trap focus between iframes. If you wanted to change that
+ behavior in your app across all instances of{' '}
+ EuiFocusTrap, you would be stuck manually passing
+ that prop over and over again, including in higher-level components
+ (like modals, popovers, and flyouts) that utilize focus traps.
+
+
+ EuiProvider allows overriding some component
+ defaults across all component usages globally via the{' '}
+ componentDefaults prop like so:
+
+
+
+ {euiProviderComponentDefaultsSnippet}
+
+
+
+ The above example would override EUI's default table pagination size
+ (50) across all usages of EUI tables and data grids, all EUI focus
+ traps would trap focus even from iframes, and all EUI portals would
+ be inserted at a specified position (instead of the end of the
+ document body).
+
+
+ The current list of supported components and the prop defaults they
+ accept are:
+
+
+
+ ),
+ },
{
title: 'Enforce usage',
text: (
diff --git a/src/components/portal/portal.tsx b/src/components/portal/portal.tsx
index 72cc1c52cb2c..07d91baea5e4 100644
--- a/src/components/portal/portal.tsx
+++ b/src/components/portal/portal.tsx
@@ -37,7 +37,14 @@ export interface EuiPortalProps {
* ReactNode to render as this component's content
*/
children: ReactNode;
+ /**
+ * If not specified, `EuiPortal` will insert itself
+ * into the end of the `document.body` by default
+ */
insert?: { sibling: HTMLElement; position: 'before' | 'after' };
+ /**
+ * Optional ref callback
+ */
portalRef?: (ref: HTMLDivElement | null) => void;
}
diff --git a/src/components/provider/component_defaults/component_defaults.test.tsx b/src/components/provider/component_defaults/component_defaults.test.tsx
new file mode 100644
index 000000000000..f982654c51cb
--- /dev/null
+++ b/src/components/provider/component_defaults/component_defaults.test.tsx
@@ -0,0 +1,50 @@
+/*
+ * 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, { PropsWithChildren } from 'react';
+import { renderHook } from '@testing-library/react-hooks';
+
+import {
+ EuiComponentDefaultsProvider,
+ useEuiComponentDefaults,
+} from './component_defaults';
+
+describe('EuiComponentDefaultsProvider', () => {
+ it('sets up context that allows accessing the passed `componentDefaults` from anywhere', () => {
+ const wrapper = ({ children }: PropsWithChildren<{}>) => (
+
+ {children}
+
+ );
+ const { result } = renderHook(useEuiComponentDefaults, { wrapper });
+
+ expect(result.current).toMatchInlineSnapshot(`
+ Object {
+ "EuiPortal": Object {
+ "insert": Object {
+ "position": "before",
+ "sibling": ,
+ },
+ },
+ }
+ `);
+ });
+
+ // NOTE: Components are in charge of their own testing to ensure that the props
+ // coming from `useEuiComponentDefaults()` were properly applied. This file
+ // is simply a very light wrapper that carries prop data.
+});
diff --git a/src/components/provider/component_defaults/component_defaults.tsx b/src/components/provider/component_defaults/component_defaults.tsx
new file mode 100644
index 000000000000..954508b323c8
--- /dev/null
+++ b/src/components/provider/component_defaults/component_defaults.tsx
@@ -0,0 +1,55 @@
+/*
+ * 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, { createContext, useContext, FunctionComponent } from 'react';
+
+import { EuiPortalProps } from '../../portal';
+
+export type EuiComponentDefaults = {
+ /**
+ * Provide a global setting for EuiPortal's default insertion position.
+ */
+ EuiPortal?: { insert: EuiPortalProps['insert'] };
+ /**
+ * TODO
+ */
+ EuiFocusTrap?: unknown;
+ /**
+ * TODO
+ */
+ EuiPagination?: unknown;
+};
+
+// Declaring as a static const for reference integrity/reducing rerenders
+const emptyDefaults = {};
+
+/*
+ * Context
+ */
+export const EuiComponentDefaultsContext =
+ createContext(emptyDefaults);
+
+/*
+ * Component
+ */
+export const EuiComponentDefaultsProvider: FunctionComponent<{
+ componentDefaults?: EuiComponentDefaults;
+}> = ({ componentDefaults = emptyDefaults, children }) => {
+ return (
+
+ {children}
+
+ );
+};
+
+/*
+ * Hook
+ */
+export const useEuiComponentDefaults = () => {
+ return useContext(EuiComponentDefaultsContext);
+};
diff --git a/src/components/provider/component_defaults/index.ts b/src/components/provider/component_defaults/index.ts
new file mode 100644
index 000000000000..74e16dcac4af
--- /dev/null
+++ b/src/components/provider/component_defaults/index.ts
@@ -0,0 +1,9 @@
+/*
+ * 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.
+ */
+
+export * from './component_defaults';
diff --git a/upcoming_changelogs/6923.md b/upcoming_changelogs/6923.md
new file mode 100644
index 000000000000..e78ffcbf2333
--- /dev/null
+++ b/upcoming_changelogs/6923.md
@@ -0,0 +1 @@
+- Added beta `componentDefaults` prop to `EuiProvider`, which will allow configuring certain default props globally. This list of components and defaults is still under consideration.