From adcb4ca4f94401af737d7a237a09b0dd590a5b50 Mon Sep 17 00:00:00 2001 From: Tomasz Kajtoch Date: Tue, 23 Jul 2024 15:06:11 +0200 Subject: [PATCH 01/10] feat(docusaurus-theme): patch `react-live` to use the new `jsx` pragma and inject Emotion's jsx wrapper --- .../react-live-npm-4.1.7-7b41625faa.patch | 26 +++++++++++++++++++ packages/docusaurus-theme/package.json | 2 +- .../src/components/demo/scope.ts | 14 ++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 .yarn/patches/react-live-npm-4.1.7-7b41625faa.patch diff --git a/.yarn/patches/react-live-npm-4.1.7-7b41625faa.patch b/.yarn/patches/react-live-npm-4.1.7-7b41625faa.patch new file mode 100644 index 00000000000..b761b9d8550 --- /dev/null +++ b/.yarn/patches/react-live-npm-4.1.7-7b41625faa.patch @@ -0,0 +1,26 @@ +diff --git a/dist/index.js b/dist/index.js +index 7bcfee33d9cfaa6c5f9d7da40335ec2551f932b6..4c29438cb94412d25aed193f9c86f20ccebb9009 100644 +--- a/dist/index.js ++++ b/dist/index.js +@@ -168,7 +168,7 @@ var import_sucrase = require("sucrase"); + var defaultTransforms = ["jsx", "imports"]; + function transform(opts = {}) { + const transforms = Array.isArray(opts.transforms) ? opts.transforms.filter(Boolean) : defaultTransforms; +- return (code) => (0, import_sucrase.transform)(code, { transforms }).code; ++ return (code) => (0, import_sucrase.transform)(code, { transforms, jsxPragma: 'jsx' }).code; + } + + // src/utils/transpile/errorBoundary.tsx +diff --git a/dist/index.mjs b/dist/index.mjs +index 44a3fbed4fc0545b75235add7369a262e8ee5220..6cfad17b4ce81553bac1243b7421f5f75ade43fc 100644 +--- a/dist/index.mjs ++++ b/dist/index.mjs +@@ -127,7 +127,7 @@ import { transform as _transform } from "sucrase"; + var defaultTransforms = ["jsx", "imports"]; + function transform(opts = {}) { + const transforms = Array.isArray(opts.transforms) ? opts.transforms.filter(Boolean) : defaultTransforms; +- return (code) => _transform(code, { transforms }).code; ++ return (code) => _transform(code, { transforms, jsxPragma: 'jsx' }).code; + } + + // src/utils/transpile/errorBoundary.tsx diff --git a/packages/docusaurus-theme/package.json b/packages/docusaurus-theme/package.json index 3f7a8e12b4e..8a0c34fd66e 100644 --- a/packages/docusaurus-theme/package.json +++ b/packages/docusaurus-theme/package.json @@ -39,7 +39,7 @@ "moment": "^2.30.1", "prism-react-renderer": "^2.3.1", "react-is": "^18.3.1", - "react-live": "^4.1.7" + "react-live": "patch:react-live@npm%3A4.1.7#~/.yarn/patches/react-live-npm-4.1.7-7b41625faa.patch" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/docusaurus-theme/src/components/demo/scope.ts b/packages/docusaurus-theme/src/components/demo/scope.ts index 1a09137b908..ecaa993a7b2 100644 --- a/packages/docusaurus-theme/src/components/demo/scope.ts +++ b/packages/docusaurus-theme/src/components/demo/scope.ts @@ -1,5 +1,14 @@ import React from 'react'; import * as EUI from '@elastic/eui'; +import * as EmotionReact from '@emotion/react'; + +/** + * A custom client-side require() alternative to inform users it's not available + * and + */ +const clientSideRequire = () => { + throw new Error('require() is not accessible in the interactive demo environment! All EUI and React exports are available in the global scope for you to use without the need to import them.'); +} export const demoDefaultScope: Record = { // React @@ -8,4 +17,9 @@ export const demoDefaultScope: Record = { // EUI exports ...EUI, + + // Emotion + ...EmotionReact, + + require: clientSideRequire, }; From 4406614975e1181f35be7cad17f7e2b43df7f482 Mon Sep 17 00:00:00 2001 From: Tomasz Kajtoch Date: Tue, 23 Jul 2024 15:11:39 +0200 Subject: [PATCH 02/10] feat(docusaurus-theme): support defining interactive demos with `interactive` metastring on markdown codeblocks --- .../src/theme/CodeBlock/index.tsx | 44 +++++++++++++++++++ .../src/theme/MDXComponents/Code.tsx | 28 ++++++------ .../docusaurus-theme/src/theme/theme.d.ts | 25 +++++++++++ 3 files changed, 83 insertions(+), 14 deletions(-) create mode 100644 packages/docusaurus-theme/src/theme/CodeBlock/index.tsx diff --git a/packages/docusaurus-theme/src/theme/CodeBlock/index.tsx b/packages/docusaurus-theme/src/theme/CodeBlock/index.tsx new file mode 100644 index 00000000000..89df9db28e4 --- /dev/null +++ b/packages/docusaurus-theme/src/theme/CodeBlock/index.tsx @@ -0,0 +1,44 @@ +import React, { isValidElement, type ReactNode } from 'react'; +import { EuiCodeBlock } from '@elastic/eui'; +import type { Props } from '@theme/CodeBlock'; +import { Demo } from '../../components/demo'; + +/** + * Best attempt to make the children a plain string so it is copyable. If there + * are react elements, we will not be able to copy the content, and it will + * return `children` as-is; otherwise, it concatenates the string children + * together. + */ +function maybeStringifyChildren(children: ReactNode): ReactNode { + if (React.Children.toArray(children).some((el) => isValidElement(el))) { + return children; + } + // The children is now guaranteed to be one/more plain strings + return Array.isArray(children) ? children.join('') : (children as string); +} + +export default function CodeBlock({ + children: rawChildren, + metastring, + className, + ...props +}: Props): JSX.Element { + const children = maybeStringifyChildren(rawChildren); + const language = className?.replace('language-', '') || undefined; + + if (metastring?.startsWith('interactive')) { + return {children}; + } + + return ( + + {children} + + ); +} diff --git a/packages/docusaurus-theme/src/theme/MDXComponents/Code.tsx b/packages/docusaurus-theme/src/theme/MDXComponents/Code.tsx index 56b15d04f18..0fe77bd753a 100644 --- a/packages/docusaurus-theme/src/theme/MDXComponents/Code.tsx +++ b/packages/docusaurus-theme/src/theme/MDXComponents/Code.tsx @@ -1,13 +1,9 @@ import React from 'react'; import type CodeType from '@theme-init/MDXComponents/Code'; +import CodeBlock from '@theme/CodeBlock'; import type { WrapperProps } from '@docusaurus/types'; import { css } from '@emotion/react'; -import { - EuiCode, - EuiCodeBlock, - useEuiMemoizedStyles, - UseEuiTheme, -} from '@elastic/eui'; +import { EuiCode, useEuiMemoizedStyles, UseEuiTheme } from '@elastic/eui'; type Props = WrapperProps; @@ -33,15 +29,19 @@ const Code = ({ children, className, ...rest }: Props): JSX.Element => { ) : false; - return isInlineCode ? ( - - {children} - - ) : ( - + if (isInlineCode) { + return ( + + {children} + + ); + } + + return ( + {children} - - ); + + ) }; export default Code; diff --git a/packages/docusaurus-theme/src/theme/theme.d.ts b/packages/docusaurus-theme/src/theme/theme.d.ts index 7cf34e65f34..2625fbd5a7d 100644 --- a/packages/docusaurus-theme/src/theme/theme.d.ts +++ b/packages/docusaurus-theme/src/theme/theme.d.ts @@ -118,6 +118,31 @@ declare module '@theme-original/EditThisPage' { export default function EditThisPage(props: Props): JSX.Element; } +// original: https://github.com/facebook/docusaurus/blob/fa743c81defd24e22eae45c81bd79eb8ec2c4ef0/packages/docusaurus-theme-classic/src/theme-classic.d.ts#L364 +declare module '@theme/CodeBlock' { + import type { ReactNode } from 'react'; + + export interface Props { + readonly children: ReactNode; + readonly className?: string; + readonly metastring?: string; + readonly title?: string; + readonly language?: string; + readonly showLineNumbers?: boolean; + } + + export default function CodeBlock(props: Props): JSX.Element; +} + +// original: https://github.com/facebook/docusaurus/blob/8b877d27d4b1bcd5c2ee13dde8332407a1c26447/packages/docusaurus-theme-classic/src/theme-classic.d.ts#L510 +declare module '@theme/MDXComponents/Code' { + import type {ComponentProps} from 'react'; + + export interface Props extends ComponentProps<'code'> {} + + export default function MDXCode(props: Props): JSX.Element; +} + // original: https://github.com/facebook/docusaurus/blob/fa743c81defd24e22eae45c81bd79eb8ec2c4ef0/packages/docusaurus-theme-classic/src/theme-classic.d.ts#L563 declare module '@theme-original/DocSidebar' { import type { PropSidebarItem } from '@docusaurus/plugin-content-docs'; From 9daa6de20ae3317f38fc7188995e757a93c09359 Mon Sep 17 00:00:00 2001 From: Tomasz Kajtoch Date: Tue, 23 Jul 2024 21:17:51 +0200 Subject: [PATCH 03/10] feat(docusaurus-theme): allow setting preview padding on `` component --- .../src/components/demo/demo.tsx | 9 ++++++--- .../src/components/demo/preview/preview.tsx | 18 ++++++++++++++---- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/docusaurus-theme/src/components/demo/demo.tsx b/packages/docusaurus-theme/src/components/demo/demo.tsx index 7159a26a421..144851a00d0 100644 --- a/packages/docusaurus-theme/src/components/demo/demo.tsx +++ b/packages/docusaurus-theme/src/components/demo/demo.tsx @@ -21,6 +21,7 @@ import { DemoSource } from './source'; import { demoDefaultScope } from './scope'; import { DemoActionsBar } from './actions_bar'; import { demoCodeTransformer } from './code_transformer'; +import { DemoPreviewProps } from './preview/preview'; export interface DemoSourceMeta { code: string; @@ -40,6 +41,7 @@ export interface DemoProps extends PropsWithChildren { * The default scope exposes all React and EUI exports. */ scope?: Record; + previewPadding?: DemoPreviewProps['padding']; } const getDemoStyles = (euiTheme: UseEuiTheme) => ({ @@ -56,12 +58,13 @@ const getDemoStyles = (euiTheme: UseEuiTheme) => ({ export const Demo = ({ children, scope, - isSourceOpen: _isSourceOpen = true + isSourceOpen: _isSourceOpen = true, + previewPadding, }: DemoProps) => { const styles = useEuiMemoizedStyles(getDemoStyles); const [sources, setSources] = useState([]); const [isSourceOpen, setIsSourceOpen] = useState(_isSourceOpen); - const activeSource = sources[0]; + const activeSource = sources[0] || null; // liveProviderKey restarts the demo to its initial state const [liveProviderKey, setLiveProviderKey] = useState(0); @@ -101,7 +104,7 @@ export const Demo = ({ theme={prismThemes.dracula} scope={finalScope} > - + ({ previewWrapper: css` - padding: ${euiTheme.euiTheme.size.l}; + padding: var(--docs-demo-preview-padding); border-radius: var(--docs-demo-border-radius); `, }); @@ -21,16 +26,21 @@ const PreviewLoader = () => (
Loading...
); -export const DemoPreview = () => { +export const DemoPreview = ({ padding = 'l' }: DemoPreviewProps) => { const euiTheme = useEuiTheme(); const styles = getPreviewStyles(euiTheme); + const paddingSize = euiPaddingSize(euiTheme, padding); + + const style = { + '--docs-demo-preview-padding': paddingSize, + } as CSSProperties; return ( }> {() => ( <> }> -
+
From e09ca6dfdf7d1ffc35bf72fe7db725ed9af63e10 Mon Sep 17 00:00:00 2001 From: Tomasz Kajtoch Date: Tue, 23 Jul 2024 21:20:44 +0200 Subject: [PATCH 04/10] feat(docusaurus-theme): support non-MDX usage of the `` component --- .../src/components/demo/source/get_source_from_children.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/docusaurus-theme/src/components/demo/source/get_source_from_children.ts b/packages/docusaurus-theme/src/components/demo/source/get_source_from_children.ts index 6dff6b4da38..15c04eb03e1 100644 --- a/packages/docusaurus-theme/src/components/demo/source/get_source_from_children.ts +++ b/packages/docusaurus-theme/src/components/demo/source/get_source_from_children.ts @@ -12,6 +12,11 @@ export interface SourceMeta { * Get source string from given children. */ export const getSourceFromChildren = (children: ReactNode): string | null => { + // Direct (non-MDX) usage almost always passes a string + if (typeof children === 'string') { + return children; + } + if (Children.count(children) !== 1 || !isElement(children)) { // This should never happen return null; From bc1ac47ca783d80ad11b46d2b5da914f3816d566 Mon Sep 17 00:00:00 2001 From: Tomasz Kajtoch Date: Tue, 23 Jul 2024 21:21:18 +0200 Subject: [PATCH 05/10] feat(docusaurus-theme): default to `isSourceOpen = false` in `` component --- packages/docusaurus-theme/src/components/demo/demo.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docusaurus-theme/src/components/demo/demo.tsx b/packages/docusaurus-theme/src/components/demo/demo.tsx index 144851a00d0..aae631f5d56 100644 --- a/packages/docusaurus-theme/src/components/demo/demo.tsx +++ b/packages/docusaurus-theme/src/components/demo/demo.tsx @@ -58,7 +58,7 @@ const getDemoStyles = (euiTheme: UseEuiTheme) => ({ export const Demo = ({ children, scope, - isSourceOpen: _isSourceOpen = true, + isSourceOpen: _isSourceOpen = false, previewPadding, }: DemoProps) => { const styles = useEuiMemoizedStyles(getDemoStyles); From 76c5535768f7194e9b3cd8de53eedab0eb8aa9ad Mon Sep 17 00:00:00 2001 From: Tomasz Kajtoch Date: Tue, 23 Jul 2024 21:21:37 +0200 Subject: [PATCH 06/10] chore(docusaurus-theme): cleanup --- packages/docusaurus-theme/src/components/demo/context.ts | 8 ++++++++ .../src/components/demo/editor/editor.tsx | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus-theme/src/components/demo/context.ts b/packages/docusaurus-theme/src/components/demo/context.ts index 2e4de44707c..7ed16e30379 100644 --- a/packages/docusaurus-theme/src/components/demo/context.ts +++ b/packages/docusaurus-theme/src/components/demo/context.ts @@ -2,7 +2,15 @@ import { createContext, useContext } from 'react'; import { DemoSourceMeta } from './demo'; export interface DemoContextObject { + /** + * Array of all available sources for this demo instance + */ sources: DemoSourceMeta[]; + + /** + * Add source to the list of available sources + * This should only be used internally when initializing the component! + */ addSource(source: DemoSourceMeta): void; } diff --git a/packages/docusaurus-theme/src/components/demo/editor/editor.tsx b/packages/docusaurus-theme/src/components/demo/editor/editor.tsx index 6ebeb7eb0c1..6544e2da8ac 100644 --- a/packages/docusaurus-theme/src/components/demo/editor/editor.tsx +++ b/packages/docusaurus-theme/src/components/demo/editor/editor.tsx @@ -8,7 +8,7 @@ import { LiveEditor, LiveError } from 'react-live'; import { css } from '@emotion/react'; -import { useEuiMemoizedStyles, useEuiTheme } from '@elastic/eui'; +import { useEuiMemoizedStyles } from '@elastic/eui'; const getEditorStyles = () => ({ editor: css` From 7e988fb3f5cfc9b66bd5751737cf8cf6b962864d Mon Sep 17 00:00:00 2001 From: Tomasz Kajtoch Date: Tue, 23 Jul 2024 22:01:41 +0200 Subject: [PATCH 07/10] chore: update yarn.lock --- yarn.lock | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index c9cc6259bef..2531716dd68 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5703,7 +5703,7 @@ __metadata: moment: "npm:^2.30.1" prism-react-renderer: "npm:^2.3.1" react-is: "npm:^18.3.1" - react-live: "npm:^4.1.7" + react-live: "patch:react-live@npm%3A4.1.7#~/.yarn/patches/react-live-npm-4.1.7-7b41625faa.patch" typescript: "npm:~5.4.5" peerDependencies: react: ^18.0.0 @@ -31278,7 +31278,7 @@ __metadata: languageName: node linkType: hard -"react-live@npm:^4.1.7": +"react-live@npm:4.1.7": version: 4.1.7 resolution: "react-live@npm:4.1.7" dependencies: @@ -31292,6 +31292,20 @@ __metadata: languageName: node linkType: hard +"react-live@patch:react-live@npm%3A4.1.7#~/.yarn/patches/react-live-npm-4.1.7-7b41625faa.patch": + version: 4.1.7 + resolution: "react-live@patch:react-live@npm%3A4.1.7#~/.yarn/patches/react-live-npm-4.1.7-7b41625faa.patch::version=4.1.7&hash=33c21c" + dependencies: + prism-react-renderer: "npm:^2.0.6" + sucrase: "npm:^3.31.0" + use-editable: "npm:^2.3.3" + peerDependencies: + react: ">=18.0.0" + react-dom: ">=18.0.0" + checksum: 10c0/f26c208a9d2e885a1c0a0a3eae8126ac6e772e37507a53d36f802bc993449f8765dff621d51cfba681c68de4da9aad5f01c2fb1c2df716d27c96ccd94cacf188 + languageName: node + linkType: hard + "react-loadable-ssr-addon-v5-slorber@npm:^1.0.1": version: 1.0.1 resolution: "react-loadable-ssr-addon-v5-slorber@npm:1.0.1" From af96d4911c65718a669c67c8c4916ea05dc85744 Mon Sep 17 00:00:00 2001 From: Tomasz Kajtoch Date: Tue, 23 Jul 2024 22:11:25 +0200 Subject: [PATCH 08/10] docs(website): convert button examples to use the simplified interactive component examples syntax --- .../navigation/button/overview.mdx | 2084 ++++++++--------- 1 file changed, 1029 insertions(+), 1055 deletions(-) diff --git a/packages/website/docs/02_components/navigation/button/overview.mdx b/packages/website/docs/02_components/navigation/button/overview.mdx index 72664cb9049..bb807c9c9a8 100644 --- a/packages/website/docs/02_components/navigation/button/overview.mdx +++ b/packages/website/docs/02_components/navigation/button/overview.mdx @@ -20,421 +20,413 @@ The most standard button component is **EuiButton** which comes in two styles an When using colors other than `primary`, be sure that either the words or an icon also represents the status. For instance, don't rely on color alone to represent dangerous actions but use words like "Delete" not "Confirm". The `text` and `accent` colors should be used sparingly as they can easily be confused with other states like disabled and danger. - - ```tsx - import React from 'react'; - import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; - - const buttons = [ - 'primary', - 'success', - 'warning', - 'danger', - 'text', - 'accent', - 'disabled', - ]; +```tsx interactive +import React from 'react'; +import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; + +const buttons = [ + 'primary', + 'success', + 'warning', + 'danger', + 'text', + 'accent', + 'disabled', +]; + +export default () => ( +
+ {buttons.map((value) => ( + <> + + + {}} + > + {value.charAt(0).toUpperCase() + value.slice(1)} + + - export default () => ( -
- {buttons.map((value) => ( - <> - - - {}} - > - {value.charAt(0).toUpperCase() + value.slice(1)} - - - - - {}} - > - Filled - - - - - {}} - > - Small - - - - - {}} - > - Small and filled - - - - - {}} - > - Full width - - - - - - ))} -
- ); - ``` - + + {}} + > + Filled + + + + + {}} + > + Small + + + + + {}} + > + Small and filled + + + + + {}} + > + Full width + + +
+ + + ))} +
+); +``` ## Empty button Use **EuiButtonEmpty** when you want to reduce the importance of the button, but still want to align it to the rest of the buttons. It is also the only button component that supports down to size `xs`. - - ```tsx - import React from 'react'; - import { - EuiButtonEmpty, - EuiFlexGroup, - EuiFlexItem, - EuiSpacer, - } from '@elastic/eui'; - - const buttons = ['primary', 'success', 'warning', 'danger', 'text', 'disabled']; - - export default () => ( -
- {buttons.map((value) => ( - <> - - - {}} - > - {value.charAt(0).toUpperCase() + value.slice(1)} - - - - - {}} - > - Small - - - - - {}} - > - Extra small - - - - - - ))} -
- ); - ``` -
+```tsx interactive +import React from 'react'; +import { + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, +} from '@elastic/eui'; + +const buttons = ['primary', 'success', 'warning', 'danger', 'text', 'disabled']; + +export default () => ( +
+ {buttons.map((value) => ( + <> + + + {}} + > + {value.charAt(0).toUpperCase() + value.slice(1)} + + + + + {}} + > + Small + + + + + {}} + > + Extra small + + + + + + ))} +
+); +``` ## Flush empty button When aligning **EuiButtonEmpty** components to the left or the right, you should make sure they’re flush with the edge of their container, so that they’re horizontally aligned with the other content in the container. - - ```tsx - import React from 'react'; - import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +```tsx interactive +import React from 'react'; +import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; - export default () => ( - - - Flush left - +export default () => ( + + + Flush left + - - Flush right - + + Flush right + - - Flush both - - - ); - ``` - + + Flush both + + +); +``` ## Buttons with icons All button components accept an `iconType` which must be an acceptable [**EuiIcon**](#/display/icons) type. Multi-color icons like app icons will be converted to single color. Icons can be displayed on the opposite side by passing `iconSide="right"`. - - ```tsx - import React from 'react'; - import { - EuiButton, - EuiFlexGroup, - EuiFlexItem, - EuiButtonEmpty, - EuiSpacer, - } from '@elastic/eui'; - - export default () => ( -
- - - {}} iconType="heart"> - Primary - - +```tsx interactive +import React from 'react'; +import { + EuiButton, + EuiFlexGroup, + EuiFlexItem, + EuiButtonEmpty, + EuiSpacer, +} from '@elastic/eui'; - - {}}> - Filled - - +export default () => ( +
+ + + {}} iconType="heart"> + Primary + + - - {}}> - Small - - + + {}}> + Filled + + - - {}}> - Small and filled - - + + {}}> + Small + + - - {}}> - Full width - - - + + {}}> + Small and filled + + - + + {}}> + Full width + + + - - - {}} iconType="lensApp"> - Empty button - - + - - {}} iconType="lensApp" size="s"> - Small empty - - + + + {}} iconType="lensApp"> + Empty button + + - - {}} iconType="lensApp" size="xs"> - Extra small empty - - - + + {}} iconType="lensApp" size="s"> + Small empty + + - + + {}} iconType="lensApp" size="xs"> + Extra small empty + + + - - - {}} iconType="arrowDown"> - Icon right - - + - - {}} - > - Filled - - + + + {}} iconType="arrowDown"> + Icon right + + - - {}} - > - Small - - + + {}} + > + Filled + + - - {}} - > - Small and filled - - + + {}} + > + Small + + - - {}} - > - Full width - - - + + {}} + > + Small and filled + + - + + {}} + > + Full width + + + - - - {}} - iconType="arrowDown" - > - Icon right - - + - - {}} - iconType="arrowDown" - size="s" - > - Small empty - - + + + {}} + iconType="arrowDown" + > + Icon right + + - - {}} - iconType="arrowDown" - size="xs" - > - Extra small empty - - - + + {}} + iconType="arrowDown" + size="s" + > + Small empty + + - + + {}} + iconType="arrowDown" + size="xs" + > + Extra small empty + + + - - - {}} iconType="heart" isDisabled> - Disabled - - + - - {}} isDisabled> - Filled - - + + + {}} iconType="heart" isDisabled> + Disabled + + - - {}} isDisabled> - Small - - + + {}} isDisabled> + Filled + + - - {}} - isDisabled - > - Small and filled - - + + {}} isDisabled> + Small + + - - {}} isDisabled> - Full width - - - + + {}} + isDisabled + > + Small and filled + + - + + {}} isDisabled> + Full width + + + - - - {}} - iconType="dashboardApp" - > - Disabled app icon - - + - - {}} - iconType="arrowDown" - iconSide="right" - size="xs" - > - Disabled icon right - - - -
- ); - ``` - + + + {}} + iconType="dashboardApp" + > + Disabled app icon + + + + + {}} + iconType="arrowDown" + iconSide="right" + size="xs" + > + Disabled icon right + + + +
+); +``` ## Icon buttons @@ -446,142 +438,140 @@ An **EuiButtonIcon** is a button that only contains an icon (no text). Use the ` **EuiButtonIcon** requires an `aria-label` to express the meaning to screen readers. -::: - - - ```tsx - import React from 'react'; - import { - EuiButtonIcon, - EuiFlexGroup, - EuiFlexItem, - EuiSpacer, - EuiTitle, - EuiCode, - } from '@elastic/eui'; - - const colors = ['primary', 'success', 'warning', 'danger', 'text', 'accent']; - - export default () => ( - <> - - {colors.map((color) => ( - - {}} - iconType="help" - aria-label="Help" - /> - - ))} - - - -

- Display (empty, base,{' '} - fill) -

-
- - - - - - - - - - - - - - -

Disabled

-
- - - - - - - - - - - - - - -

- Size (xs, s, m) -

-
- - - - - - - - - - - - - - -

All icons types inherit button color

-
- - - - - - - - - +::: + +```tsx interactive +import React from 'react'; +import { + EuiButtonIcon, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiTitle, + EuiCode, +} from '@elastic/eui'; + +const colors = ['primary', 'success', 'warning', 'danger', 'text', 'accent']; + +export default () => ( + <> + + {colors.map((color) => ( + {}} + iconType="help" + aria-label="Help" /> - - - - - - ); - ``` -
+ ))} + + + +

+ Display (empty, base,{' '} + fill) +

+
+ + + + + + + + + + + + + + +

Disabled

+
+ + + + + + + + + + + + + + +

+ Size (xs, s, m) +

+
+ + + + + + + + + + + + + + +

All icons types inherit button color

+
+ + + + + + + + + + + + + + + + +); +``` ## Buttons as links @@ -593,117 +583,113 @@ it is not usually recommended. For more specific information on how to integrate If you are creating a purely text-based link, like the one in the previous paragraph, use [**EuiLink**](#/navigation/link) instead. - - ```tsx - import React, { Fragment } from 'react'; - import { - EuiButton, - EuiButtonEmpty, - EuiButtonIcon, - EuiFlexGroup, - EuiFlexItem, - EuiSpacer, +```tsx interactive +import React, { Fragment } from 'react'; +import { + EuiButton, + EuiButtonEmpty, + EuiButtonIcon, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, } from '@elastic/eui'; - export default () => ( - - - - Link to elastic.co - - - - - Link to elastic.co - - - - - - - - - - - - - - Disabled link - - - - - - Disabled empty link - - - - - - - - - ); - ``` - - -## Loading state - -Setting the `isLoading` prop to true will add the loading spinner or swap the existing icon for the loading spinner -and set the button to disabled. It is good practice to also rename the button to "Loading…". - - - ```tsx - import React from 'react'; - import { - EuiButton, - EuiFlexGroup, - EuiFlexItem, - EuiButtonEmpty, - } from '@elastic/eui'; - - export default () => ( +export default () => ( + - Loading… + Link to elastic.co - - Loading… - + + Link to elastic.co + + + + + + + + + - - Loading… + + Disabled link - {}} isLoading> - Loading… + + Disabled empty link - {}} isLoading iconSide="right"> - Loading… - + - - ); - ``` - + + +); +``` + +## Loading state + +Setting the `isLoading` prop to true will add the loading spinner or swap the existing icon for the loading spinner +and set the button to disabled. It is good practice to also rename the button to "Loading…". + +```tsx interactive +import React from 'react'; +import { + EuiButton, + EuiFlexGroup, + EuiFlexItem, + EuiButtonEmpty, +} from '@elastic/eui'; + +export default () => ( + + + Loading… + + + + + Loading… + + + + + + Loading… + + + + + {}} isLoading> + Loading… + + + + + {}} isLoading iconSide="right"> + Loading… + + + +); +``` ## Split buttons @@ -711,80 +697,78 @@ EUI [does not support](https://github.com/elastic/eui/issues/4171) split buttons we recommend using separate buttons for the main and overflow actions. You can achieve this by simply using the `display` and `size` props **EuiButtonIcon** to match that of the primary action button. - - ```tsx - import React, { useState } from 'react'; - import { - EuiButton, - EuiButtonIcon, - EuiFlexGroup, - EuiFlexItem, - EuiContextMenuPanel, - EuiContextMenuItem, - EuiPopover, - useGeneratedHtmlId, - } from '@elastic/eui'; - - export default () => { - const [isPopoverOpen, setPopover] = useState(false); - const splitButtonPopoverId = useGeneratedHtmlId({ - prefix: 'splitButtonPopover', - }); - - const onButtonClick = () => { - setPopover(!isPopoverOpen); - }; +```tsx interactive +import React, { useState } from 'react'; +import { + EuiButton, + EuiButtonIcon, + EuiFlexGroup, + EuiFlexItem, + EuiContextMenuPanel, + EuiContextMenuItem, + EuiPopover, + useGeneratedHtmlId, +} from '@elastic/eui'; - const closePopover = () => { - setPopover(false); - }; +export default () => { + const [isPopoverOpen, setPopover] = useState(false); + const splitButtonPopoverId = useGeneratedHtmlId({ + prefix: 'splitButtonPopover', + }); - const items = [ - - Copy - , - - Edit - , - - Share - , - ]; - - return ( - <> - - - - Last 15 min - - - - - } - isOpen={isPopoverOpen} - closePopover={closePopover} - panelPaddingSize="none" - anchorPosition="downLeft" - > - - - - - - ); + const onButtonClick = () => { + setPopover(!isPopoverOpen); + }; + + const closePopover = () => { + setPopover(false); }; - ``` - + + const items = [ + + Copy + , + + Edit + , + + Share + , + ]; + + return ( + <> + + + + Last 15 min + + + + + } + isOpen={isPopoverOpen} + closePopover={closePopover} + panelPaddingSize="none" + anchorPosition="downLeft" + > + + + + + + ); +}; +``` ## Toggle buttons @@ -795,38 +779,36 @@ Though there are two **exclusive** situations to consider. 1. If your button changes its readable **text**, via children or `aria-label`, then there is no additional accessibility concern. - - ```tsx - import React, { useState } from 'react'; - import { EuiButton, EuiButtonIcon } from '@elastic/eui'; +```tsx interactive +import React, { useState } from 'react'; +import { EuiButton, EuiButtonIcon } from '@elastic/eui'; - export default () => { - const [toggle0On, setToggle0On] = useState(false); - const [toggle1On, setToggle1On] = useState(true); +export default () => { + const [toggle0On, setToggle0On] = useState(false); + const [toggle1On, setToggle1On] = useState(true); - return ( - <> - { - setToggle0On((isOn) => !isOn); - }} - > - {toggle0On ? 'Hey there good lookin' : 'Toggle me'} - -   - { - setToggle1On((isOn) => !isOn); - }} - /> - - ); - }; - ``` - + return ( + <> + { + setToggle0On((isOn) => !isOn); + }} + > + {toggle0On ? 'Hey there good lookin' : 'Toggle me'} + +   + { + setToggle1On((isOn) => !isOn); + }} + /> + + ); +}; +``` 2. If your button only changes the **visual** appearance, you must add `aria-pressed` passing a boolean for the on and off states. All EUI button types provide a helper prop for this called `isSelected`. @@ -837,45 +819,43 @@ Do not add `aria-pressed` or `isSelected` if you also change the readable text. ::: - - ```tsx - import React, { useState } from 'react'; - import { EuiButton, EuiButtonIcon } from '@elastic/eui'; +```tsx interactive +import React, { useState } from 'react'; +import { EuiButton, EuiButtonIcon } from '@elastic/eui'; - export default () => { - const [toggle2On, setToggle2On] = useState(true); - const [toggle3On, setToggle3On] = useState(false); +export default () => { + const [toggle2On, setToggle2On] = useState(true); + const [toggle3On, setToggle3On] = useState(false); - return ( - <> - { - setToggle2On((isOn) => !isOn); - }} - > - Toggle me - -   - { - setToggle3On((isOn) => !isOn); - }} - /> - - ); - }; - ``` - + return ( + <> + { + setToggle2On((isOn) => !isOn); + }} + > + Toggle me + +   + { + setToggle3On((isOn) => !isOn); + }} + /> + + ); +}; +``` ## Button groups @@ -889,245 +869,241 @@ This is only for accessibility, however, so it will be visibly hidden. ::: - - ```tsx - import React, { useState, Fragment } from 'react'; - import { - EuiButtonGroup, - EuiSpacer, - EuiTitle, - useGeneratedHtmlId, - } from '@elastic/eui'; - - export default () => { - const basicButtonGroupPrefix = useGeneratedHtmlId({ - prefix: 'basicButtonGroup', - }); - const multiSelectButtonGroupPrefix = useGeneratedHtmlId({ - prefix: 'multiSelectButtonGroup', - }); - const disabledButtonGroupPrefix = useGeneratedHtmlId({ - prefix: 'disabledButtonGroup', - }); - - const toggleButtons = [ - { - id: `${basicButtonGroupPrefix}__0`, - label: 'Option one', - }, - { - id: `${basicButtonGroupPrefix}__1`, - label: 'Option two is selected by default', - }, - { - id: `${basicButtonGroupPrefix}__2`, - label: 'Option three', - }, - ]; +```tsx interactive +import React, { useState, Fragment } from 'react'; +import { + EuiButtonGroup, + EuiSpacer, + EuiTitle, + useGeneratedHtmlId, +} from '@elastic/eui'; - const toggleButtonsDisabled = [ - { - id: `${disabledButtonGroupPrefix}__0`, - label: 'Option one', - }, - { - id: `${disabledButtonGroupPrefix}__1`, - label: 'Option two is selected by default', - }, - { - id: `${disabledButtonGroupPrefix}__2`, - label: 'Option three', - }, - ]; +export default () => { + const basicButtonGroupPrefix = useGeneratedHtmlId({ + prefix: 'basicButtonGroup', + }); + const multiSelectButtonGroupPrefix = useGeneratedHtmlId({ + prefix: 'multiSelectButtonGroup', + }); + const disabledButtonGroupPrefix = useGeneratedHtmlId({ + prefix: 'disabledButtonGroup', + }); + + const toggleButtons = [ + { + id: `${basicButtonGroupPrefix}__0`, + label: 'Option one', + }, + { + id: `${basicButtonGroupPrefix}__1`, + label: 'Option two is selected by default', + }, + { + id: `${basicButtonGroupPrefix}__2`, + label: 'Option three', + }, + ]; - const toggleButtonsMulti = [ - { - id: `${multiSelectButtonGroupPrefix}__0`, - label: 'Option 1', - }, - { - id: `${multiSelectButtonGroupPrefix}__1`, - label: 'Option 2 is selected by default', - }, - { - id: `${multiSelectButtonGroupPrefix}__2`, - label: 'Option 3', - }, - ]; - - const [toggleIdSelected, setToggleIdSelected] = useState( - `${basicButtonGroupPrefix}__1` - ); - const [toggleIdDisabled, setToggleIdDisabled] = useState( - `${disabledButtonGroupPrefix}__1` - ); - const [toggleIdToSelectedMap, setToggleIdToSelectedMap] = useState({ - [`${multiSelectButtonGroupPrefix}__1`]: true, - }); - - const onChange = (optionId) => { - setToggleIdSelected(optionId); - }; + const toggleButtonsDisabled = [ + { + id: `${disabledButtonGroupPrefix}__0`, + label: 'Option one', + }, + { + id: `${disabledButtonGroupPrefix}__1`, + label: 'Option two is selected by default', + }, + { + id: `${disabledButtonGroupPrefix}__2`, + label: 'Option three', + }, + ]; - const onChangeDisabled = (optionId) => { - setToggleIdDisabled(optionId); - }; + const toggleButtonsMulti = [ + { + id: `${multiSelectButtonGroupPrefix}__0`, + label: 'Option 1', + }, + { + id: `${multiSelectButtonGroupPrefix}__1`, + label: 'Option 2 is selected by default', + }, + { + id: `${multiSelectButtonGroupPrefix}__2`, + label: 'Option 3', + }, + ]; - const onChangeMulti = (optionId) => { - const newToggleIdToSelectedMap = { - ...toggleIdToSelectedMap, - ...{ - [optionId]: !toggleIdToSelectedMap[optionId], - }, - }; - setToggleIdToSelectedMap(newToggleIdToSelectedMap); - }; + const [toggleIdSelected, setToggleIdSelected] = useState( + `${basicButtonGroupPrefix}__1` + ); + const [toggleIdDisabled, setToggleIdDisabled] = useState( + `${disabledButtonGroupPrefix}__1` + ); + const [toggleIdToSelectedMap, setToggleIdToSelectedMap] = useState({ + [`${multiSelectButtonGroupPrefix}__1`]: true, + }); - return ( - - onChange(id)} - /> - - -

Primary & multi select

-
- - onChangeMulti(id)} - color="primary" - type="multi" - /> - - -

Disabled & full width

-
- - onChangeDisabled(id)} - buttonSize="m" - isDisabled - isFullWidth - /> -
- ); + const onChange = (optionId) => { + setToggleIdSelected(optionId); }; - ``` -
-### Icon only button groups + const onChangeDisabled = (optionId) => { + setToggleIdDisabled(optionId); + }; -If you're just displaying a group of icons, add the prop `isIconOnly`. + const onChangeMulti = (optionId) => { + const newToggleIdToSelectedMap = { + ...toggleIdToSelectedMap, + ...{ + [optionId]: !toggleIdToSelectedMap[optionId], + }, + }; + setToggleIdToSelectedMap(newToggleIdToSelectedMap); + }; + + return ( + + onChange(id)} + /> + + +

Primary & multi select

+
+ + onChangeMulti(id)} + color="primary" + type="multi" + /> + + +

Disabled & full width

+
+ + onChangeDisabled(id)} + buttonSize="m" + isDisabled + isFullWidth + /> +
+ ); +}; +``` - - ```tsx - import React, { useState, Fragment } from 'react'; - import { EuiButtonGroup, htmlIdGenerator } from '@elastic/eui'; +### Icon only button groups - const idPrefix3 = htmlIdGenerator()(); +If you're just displaying a group of icons, add the prop `isIconOnly`. - export default () => { - const toggleButtonsIcons = [ - { - id: `${idPrefix3}0`, - label: 'Align left', - iconType: 'editorAlignLeft', - }, - { - id: `${idPrefix3}1`, - label: 'Align center', - iconType: 'editorAlignCenter', - }, - { - id: `${idPrefix3}2`, - label: 'Align right', - iconType: 'editorAlignRight', - isDisabled: true, - }, - ]; - - const toggleButtonsIconsMulti = [ - { - id: `${idPrefix3}3`, - label: 'Bold', - name: 'bold', - iconType: 'editorBold', - }, - { - id: `${idPrefix3}4`, - label: 'Italic', - name: 'italic', - iconType: 'editorItalic', - isDisabled: true, - }, - { - id: `${idPrefix3}5`, - label: 'Underline', - name: 'underline', - iconType: 'editorUnderline', - }, - { - id: `${idPrefix3}6`, - label: 'Strikethrough', - name: 'strikethrough', - iconType: 'editorStrike', - }, - ]; +```tsx interactive +import React, { useState, Fragment } from 'react'; +import { EuiButtonGroup, htmlIdGenerator } from '@elastic/eui'; + +const idPrefix3 = htmlIdGenerator()(); + +export default () => { + const toggleButtonsIcons = [ + { + id: `${idPrefix3}0`, + label: 'Align left', + iconType: 'editorAlignLeft', + }, + { + id: `${idPrefix3}1`, + label: 'Align center', + iconType: 'editorAlignCenter', + }, + { + id: `${idPrefix3}2`, + label: 'Align right', + iconType: 'editorAlignRight', + isDisabled: true, + }, + ]; - const [toggleIconIdSelected, setToggleIconIdSelected] = useState( - `${idPrefix3}1` - ); - const [toggleIconIdToSelectedMap, setToggleIconIdToSelectedMap] = useState( - {} - ); + const toggleButtonsIconsMulti = [ + { + id: `${idPrefix3}3`, + label: 'Bold', + name: 'bold', + iconType: 'editorBold', + }, + { + id: `${idPrefix3}4`, + label: 'Italic', + name: 'italic', + iconType: 'editorItalic', + isDisabled: true, + }, + { + id: `${idPrefix3}5`, + label: 'Underline', + name: 'underline', + iconType: 'editorUnderline', + }, + { + id: `${idPrefix3}6`, + label: 'Strikethrough', + name: 'strikethrough', + iconType: 'editorStrike', + }, + ]; - const onChangeIcons = (optionId) => { - setToggleIconIdSelected(optionId); - }; + const [toggleIconIdSelected, setToggleIconIdSelected] = useState( + `${idPrefix3}1` + ); + const [toggleIconIdToSelectedMap, setToggleIconIdToSelectedMap] = useState( + {} + ); - const onChangeIconsMulti = (optionId) => { - const newToggleIconIdToSelectedMap = { - ...toggleIconIdToSelectedMap, - ...{ - [optionId]: !toggleIconIdToSelectedMap[optionId], - }, - }; + const onChangeIcons = (optionId) => { + setToggleIconIdSelected(optionId); + }; - setToggleIconIdToSelectedMap(newToggleIconIdToSelectedMap); + const onChangeIconsMulti = (optionId) => { + const newToggleIconIdToSelectedMap = { + ...toggleIconIdToSelectedMap, + ...{ + [optionId]: !toggleIconIdToSelectedMap[optionId], + }, }; - return ( - - onChangeIcons(id)} - isIconOnly - /> -    - onChangeIconsMulti(id)} - type="multi" - isIconOnly - /> - - ); + setToggleIconIdToSelectedMap(newToggleIconIdToSelectedMap); }; - ``` - + + return ( + + onChangeIcons(id)} + isIconOnly + /> +    + onChangeIconsMulti(id)} + type="multi" + isIconOnly + /> + + ); +}; +``` ### Button groups in forms @@ -1137,112 +1113,110 @@ Compressed groups should always be `fullWidth` so they line up nicely in their s For a more detailed example of how to integrate with forms, see the ["Complex example"](#/forms/compressed-forms#complex-example) on the compressed forms page. - - ```tsx - import React, { useState } from 'react'; - import { - EuiButtonGroup, - EuiSpacer, - EuiPanel, - useGeneratedHtmlId, - } from '@elastic/eui'; - - export default () => { - const compressedToggleButtonGroupPrefix = useGeneratedHtmlId({ - prefix: 'compressedToggleButtonGroup', - }); - const multiSelectButtonGroupPrefix = useGeneratedHtmlId({ - prefix: 'multiSelectButtonGroup', - }); - - const toggleButtonsCompressed = [ - { - id: `${compressedToggleButtonGroupPrefix}__0`, - label: 'fine', - }, - { - id: `${compressedToggleButtonGroupPrefix}__1`, - label: 'rough', - }, - { - id: `${compressedToggleButtonGroupPrefix}__2`, - label: 'coarse', - }, - ]; - - const toggleButtonsIconsMulti = [ - { - id: `${multiSelectButtonGroupPrefix}__0`, - label: 'Bold', - name: 'bold', - iconType: 'editorBold', - }, - { - id: `${multiSelectButtonGroupPrefix}__1`, - label: 'Italic', - name: 'italic', - iconType: 'editorItalic', - isDisabled: true, - }, - { - id: `${multiSelectButtonGroupPrefix}__2`, - label: 'Underline', - name: 'underline', - iconType: 'editorUnderline', - }, - { - id: `${multiSelectButtonGroupPrefix}__3`, - label: 'Strikethrough', - name: 'strikethrough', - iconType: 'editorStrike', - }, - ]; +```tsx interactive +import React, { useState } from 'react'; +import { + EuiButtonGroup, + EuiSpacer, + EuiPanel, + useGeneratedHtmlId, +} from '@elastic/eui'; - const [toggleIconIdToSelectedMapIcon, setToggleIconIdToSelectedMapIcon] = - useState({}); - const [toggleCompressedIdSelected, setToggleCompressedIdSelected] = useState( - `${compressedToggleButtonGroupPrefix}__1` - ); +export default () => { + const compressedToggleButtonGroupPrefix = useGeneratedHtmlId({ + prefix: 'compressedToggleButtonGroup', + }); + const multiSelectButtonGroupPrefix = useGeneratedHtmlId({ + prefix: 'multiSelectButtonGroup', + }); + + const toggleButtonsCompressed = [ + { + id: `${compressedToggleButtonGroupPrefix}__0`, + label: 'fine', + }, + { + id: `${compressedToggleButtonGroupPrefix}__1`, + label: 'rough', + }, + { + id: `${compressedToggleButtonGroupPrefix}__2`, + label: 'coarse', + }, + ]; - const onChangeCompressed = (optionId) => { - setToggleCompressedIdSelected(optionId); - }; + const toggleButtonsIconsMulti = [ + { + id: `${multiSelectButtonGroupPrefix}__0`, + label: 'Bold', + name: 'bold', + iconType: 'editorBold', + }, + { + id: `${multiSelectButtonGroupPrefix}__1`, + label: 'Italic', + name: 'italic', + iconType: 'editorItalic', + isDisabled: true, + }, + { + id: `${multiSelectButtonGroupPrefix}__2`, + label: 'Underline', + name: 'underline', + iconType: 'editorUnderline', + }, + { + id: `${multiSelectButtonGroupPrefix}__3`, + label: 'Strikethrough', + name: 'strikethrough', + iconType: 'editorStrike', + }, + ]; - const onChangeIconsMultiIcons = (optionId) => { - const newToggleIconIdToSelectedMapIcon = { - ...toggleIconIdToSelectedMapIcon, - ...{ - [optionId]: !toggleIconIdToSelectedMapIcon[optionId], - }, - }; + const [toggleIconIdToSelectedMapIcon, setToggleIconIdToSelectedMapIcon] = + useState({}); + const [toggleCompressedIdSelected, setToggleCompressedIdSelected] = useState( + `${compressedToggleButtonGroupPrefix}__1` + ); + + const onChangeCompressed = (optionId) => { + setToggleCompressedIdSelected(optionId); + }; - setToggleIconIdToSelectedMapIcon(newToggleIconIdToSelectedMapIcon); + const onChangeIconsMultiIcons = (optionId) => { + const newToggleIconIdToSelectedMapIcon = { + ...toggleIconIdToSelectedMapIcon, + ...{ + [optionId]: !toggleIconIdToSelectedMapIcon[optionId], + }, }; - return ( - - onChangeCompressed(id)} - buttonSize="compressed" - isFullWidth - /> - - onChangeIconsMultiIcons(id)} - type="multi" - buttonSize="compressed" - isIconOnly - /> - - ); + setToggleIconIdToSelectedMapIcon(newToggleIconIdToSelectedMapIcon); }; - ``` - + + return ( + + onChangeCompressed(id)} + buttonSize="compressed" + isFullWidth + /> + + onChangeIconsMultiIcons(id)} + type="multi" + buttonSize="compressed" + isIconOnly + /> + + ); +}; +``` From 740cbe5a2e8a987e46bbd0beb19d9e828b023654 Mon Sep 17 00:00:00 2001 From: Tomasz Kajtoch Date: Fri, 26 Jul 2024 16:04:47 +0200 Subject: [PATCH 09/10] chore(docusaurus-theme): update jsdoc for `clientSideRequire` --- packages/docusaurus-theme/src/components/demo/scope.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docusaurus-theme/src/components/demo/scope.ts b/packages/docusaurus-theme/src/components/demo/scope.ts index ecaa993a7b2..8c8ab52fd75 100644 --- a/packages/docusaurus-theme/src/components/demo/scope.ts +++ b/packages/docusaurus-theme/src/components/demo/scope.ts @@ -4,7 +4,7 @@ import * as EmotionReact from '@emotion/react'; /** * A custom client-side require() alternative to inform users it's not available - * and + * in our demo environment */ const clientSideRequire = () => { throw new Error('require() is not accessible in the interactive demo environment! All EUI and React exports are available in the global scope for you to use without the need to import them.'); From 1d4b1e7f961ce3fb7eccaa028aa071359186adb3 Mon Sep 17 00:00:00 2001 From: Tomasz Kajtoch Date: Fri, 26 Jul 2024 16:08:16 +0200 Subject: [PATCH 10/10] feat(docusaurus-theme): pass className to `EuiCode` --- packages/docusaurus-theme/src/theme/MDXComponents/Code.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus-theme/src/theme/MDXComponents/Code.tsx b/packages/docusaurus-theme/src/theme/MDXComponents/Code.tsx index 0fe77bd753a..84b74232e5f 100644 --- a/packages/docusaurus-theme/src/theme/MDXComponents/Code.tsx +++ b/packages/docusaurus-theme/src/theme/MDXComponents/Code.tsx @@ -31,7 +31,12 @@ const Code = ({ children, className, ...rest }: Props): JSX.Element => { if (isInlineCode) { return ( - + {children} );