From eb570531cba27c8a67c07eaa6f30e74ddb781ce2 Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Wed, 6 Mar 2024 08:20:43 -0800 Subject: [PATCH 1/4] Allow `popoverContent` to be a render function that is passed the `closePopover` callback --- src/components/breadcrumbs/breadcrumb.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) 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) { From 755b375ec422863a557a7f05997db2433c95ee9f Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Wed, 6 Mar 2024 08:20:53 -0800 Subject: [PATCH 2/4] Add tests --- .../__snapshots__/breadcrumb.test.tsx.snap | 2 +- .../breadcrumbs/breadcrumb.test.tsx | 57 ++++++++++++++----- 2 files changed, 43 insertions(+), 16 deletions(-) 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', () => { From 52d2dc6fc84391ade5b0ed5d77d37f91ea0f626d Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Wed, 6 Mar 2024 08:31:55 -0800 Subject: [PATCH 3/4] Update docs/example --- .../views/breadcrumbs/breadcrumbs_example.js | 8 +++ .../src/views/breadcrumbs/popover_content.tsx | 59 +++++++++---------- 2 files changed, 36 insertions(+), 31 deletions(-) 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' }, }, { From a76827263531bb530b6d8473292bd9ed790a8afb Mon Sep 17 00:00:00 2001 From: Cee Chen Date: Wed, 6 Mar 2024 08:37:57 -0800 Subject: [PATCH 4/4] changelog --- changelogs/upcoming/7555.md | 1 + 1 file changed, 1 insertion(+) 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