From 415971dc415109a8dc08c503cb0703dfcd893ae2 Mon Sep 17 00:00:00 2001 From: Cee Chen <549407+cee-chen@users.noreply.github.com> Date: Thu, 7 Mar 2024 08:38:37 -0800 Subject: [PATCH] [EuiBreadcrumb] Allow popover content to close the breadcrumb popover (#7555) --- changelogs/upcoming/7555.md | 1 + .../views/breadcrumbs/breadcrumbs_example.js | 8 +++ .../src/views/breadcrumbs/popover_content.tsx | 59 +++++++++---------- .../__snapshots__/breadcrumb.test.tsx.snap | 2 +- .../breadcrumbs/breadcrumb.test.tsx | 57 +++++++++++++----- src/components/breadcrumbs/breadcrumb.tsx | 13 ++-- 6 files changed, 89 insertions(+), 51 deletions(-) create mode 100644 changelogs/upcoming/7555.md diff --git a/changelogs/upcoming/7555.md b/changelogs/upcoming/7555.md new file mode 100644 index 00000000000..b827da815c6 --- /dev/null +++ b/changelogs/upcoming/7555.md @@ -0,0 +1 @@ +- `EuiBreadcrumbs`'s `popoverContent` API now accepts a render function that will be passed a `closePopover` callback, allowing consumers to close the breadcrumb popover from their popover content diff --git a/src-docs/src/views/breadcrumbs/breadcrumbs_example.js b/src-docs/src/views/breadcrumbs/breadcrumbs_example.js index 9d3ec472d66..53fe2dd0d9e 100644 --- a/src-docs/src/views/breadcrumbs/breadcrumbs_example.js +++ b/src-docs/src/views/breadcrumbs/breadcrumbs_example.js @@ -294,6 +294,14 @@ export const BreadcrumbsExample = { accepted as they are controlled automatically by{' '} EuiBreadcrumbs.

+

+ If you need the ability to close the breadcrumb popover from within + your popover content, popoverContent accepts a + render function that will be passed a{' '} + closePopover callback, which you can invoke to + close the popover. See the Deployment breadcrumb below for example + usage. +

{ const breadcrumbs: EuiBreadcrumb[] = [ { text: 'My deployment', - popoverContent: ( - <> - Select a deployment - e.preventDefault()} - > - Go to Deployment A - , - e.preventDefault()} - > - Go to Deployment B - , - e.preventDefault()} - > - Go to all deployments - , - ]} - /> - - ), + // Passing a render function allows closing the breadcrumb popover from within your content + popoverContent: (closePopover) => { + const onClick = (e: React.MouseEvent) => { + e.preventDefault(); + closePopover(); + }; + return ( + <> + + Select a deployment + + + Go to Deployment A + , + + Go to Deployment B + , + + Go to all deployments + , + ]} + /> + + ); + }, popoverProps: { panelPaddingSize: 'none' }, }, { diff --git a/src/components/breadcrumbs/__snapshots__/breadcrumb.test.tsx.snap b/src/components/breadcrumbs/__snapshots__/breadcrumb.test.tsx.snap index 5a803bb40ce..116e054b27e 100644 --- a/src/components/breadcrumbs/__snapshots__/breadcrumb.test.tsx.snap +++ b/src/components/breadcrumbs/__snapshots__/breadcrumb.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`EuiBreadcrumbContent renders breadcrumbs with \`popoverContent\` with popovers 1`] = ` +exports[`EuiBreadcrumbContent breadcrumbs with popovers renders with \`popoverContent\` 1`] = `
{ expect(container).toMatchSnapshot(); }); - it('renders breadcrumbs with `popoverContent` with popovers', async () => { - const { baseElement, getByTestSubject } = render( - - ); - fireEvent.click(getByTestSubject('popoverToggle')); - await waitForEuiPopoverOpen(); + describe('breadcrumbs with popovers', () => { + it('renders with `popoverContent`', async () => { + const { baseElement, getByTestSubject } = render( + + ); + fireEvent.click(getByTestSubject('popoverToggle')); + await waitForEuiPopoverOpen(); - expect(getByTestSubject('popover')).toBeInTheDocument(); - expect(baseElement).toMatchSnapshot(); + expect(getByTestSubject('popover')).toBeInTheDocument(); + expect(baseElement).toMatchSnapshot(); + }); + + it('passes a popover close callback to `popoverContent` render functions', async () => { + const { getByTestSubject } = render( + ( + + )} + /> + ); + + fireEvent.click(getByTestSubject('popoverToggle')); + await waitForEuiPopoverOpen(); + + fireEvent.click(getByTestSubject('popoverClose')); + await waitForEuiPopoverClose(); + }); }); describe('highlightLastBreadcrumb', () => { diff --git a/src/components/breadcrumbs/breadcrumb.tsx b/src/components/breadcrumbs/breadcrumb.tsx index 5730e219dc3..13daeef593e 100644 --- a/src/components/breadcrumbs/breadcrumb.tsx +++ b/src/components/breadcrumbs/breadcrumb.tsx @@ -56,12 +56,14 @@ export type EuiBreadcrumbProps = Omit< */ 'aria-current'?: AriaAttributes['aria-current']; /** - * Creates a breadcrumb that toggles a popover dialog + * Creates a breadcrumb that toggles a popover dialog. Takes any rendered node(s), + * or a render function that will pass callback allowing you to close the + * breadcrumb popover from within your popover content. * * If passed, both `href` and `onClick` will be ignored - the breadcrumb's * click behavior should only trigger a popover. */ - popoverContent?: ReactNode; + popoverContent?: ReactNode | ((closePopover: () => void) => ReactNode); /** * Allows customizing the popover if necessary. Accepts any props that * [EuiPopover](/#/layout/popover) accepts, except for props that control state. @@ -166,11 +168,12 @@ export const EuiBreadcrumbContent: FunctionComponent< const styleProps = { className: classes, css: cssStyles }; if (isPopoverBreadcrumb) { + const closePopover = () => setIsPopoverOpen(false); return ( setIsPopoverOpen(false)} + closePopover={closePopover} css={!isLastBreadcrumb && styles.euiBreadcrumb__popoverWrapper} button={ } > - {popoverContent} + {typeof popoverContent === 'function' + ? popoverContent(closePopover) + : popoverContent} ); } else if (isInteractiveBreadcrumb) {