mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[chrome] Improve breadcrumb extension (#209765)
## Summary fix https://github.com/elastic/kibana/issues/208728 This PR improves breadcrumb extension point for adding starring next to a dashboard breadcrumb https://github.com/elastic/kibana/issues/200315: - Fix breadcrumb extension didn't render in solution nav - Support multiple extensions (search sessions are deprecated and need to be enabled with kibana.yml flag, but we still need to support both UI elements) - Improve DX to unmount the extension To test: - Add `data.search.sessions.enabled: true` and see that search session UI appears in solution nav. - To test multiple, add more extensions by using `chrome.setBreadcrumbsAppendExtension`, e.g. in `src/platform/plugins/shared/data/public/search/search_service.ts` . This actually gonna be used in https://github.com/elastic/kibana/issues/200315 
This commit is contained in:
parent
e21e7482e7
commit
02a88d13c2
14 changed files with 191 additions and 77 deletions
|
@ -138,7 +138,8 @@ export const chromeStyles = (euiTheme: UseEuiTheme['euiTheme']) => css`
|
|||
|
||||
.header__breadcrumbsWithExtensionContainer {
|
||||
overflow: hidden; // enables text-ellipsis in the last breadcrumb
|
||||
.euiHeaderBreadcrumbs {
|
||||
.euiHeaderBreadcrumbs,
|
||||
.euiBreadcrumbs {
|
||||
// stop breadcrumbs from growing.
|
||||
// this makes the extension appear right next to the last breadcrumb
|
||||
flex-grow: 0;
|
||||
|
@ -147,7 +148,7 @@ export const chromeStyles = (euiTheme: UseEuiTheme['euiTheme']) => css`
|
|||
overflow: hidden; // enables text-ellipsis in the last breadcrumb
|
||||
}
|
||||
}
|
||||
.header__breadcrumbsAppendExtension {
|
||||
.header__breadcrumbsAppendExtension--last {
|
||||
flex-grow: 1;
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -492,21 +492,70 @@ describe('start', () => {
|
|||
describe('breadcrumbsAppendExtension$', () => {
|
||||
it('updates the breadcrumbsAppendExtension$', async () => {
|
||||
const { chrome, service } = await start();
|
||||
const promise = chrome.getBreadcrumbsAppendExtension$().pipe(toArray()).toPromise();
|
||||
const promise = chrome.getBreadcrumbsAppendExtensions$().pipe(toArray()).toPromise();
|
||||
|
||||
chrome.setBreadcrumbsAppendExtension({
|
||||
const ext1 = chrome.setBreadcrumbsAppendExtension({
|
||||
content: () => () => {},
|
||||
});
|
||||
chrome.setBreadcrumbsAppendExtension({
|
||||
order: 0,
|
||||
content: () => () => {},
|
||||
});
|
||||
const ext3 = chrome.setBreadcrumbsAppendExtension({
|
||||
order: 100,
|
||||
content: () => () => {},
|
||||
});
|
||||
ext3();
|
||||
ext1();
|
||||
service.stop();
|
||||
|
||||
await expect(promise).resolves.toMatchInlineSnapshot(`
|
||||
Array [
|
||||
undefined,
|
||||
Object {
|
||||
"content": [Function],
|
||||
},
|
||||
]
|
||||
`);
|
||||
Array [
|
||||
Array [],
|
||||
Array [
|
||||
Object {
|
||||
"content": [Function],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"content": [Function],
|
||||
"order": 0,
|
||||
},
|
||||
Object {
|
||||
"content": [Function],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"content": [Function],
|
||||
"order": 0,
|
||||
},
|
||||
Object {
|
||||
"content": [Function],
|
||||
},
|
||||
Object {
|
||||
"content": [Function],
|
||||
"order": 100,
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"content": [Function],
|
||||
"order": 0,
|
||||
},
|
||||
Object {
|
||||
"content": [Function],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"content": [Function],
|
||||
"order": 0,
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -270,9 +270,9 @@ export class ChromeService {
|
|||
);
|
||||
const helpExtension$ = new BehaviorSubject<ChromeHelpExtension | undefined>(undefined);
|
||||
const breadcrumbs$ = new BehaviorSubject<ChromeBreadcrumb[]>([]);
|
||||
const breadcrumbsAppendExtension$ = new BehaviorSubject<
|
||||
ChromeBreadcrumbsAppendExtension | undefined
|
||||
>(undefined);
|
||||
const breadcrumbsAppendExtensions$ = new BehaviorSubject<ChromeBreadcrumbsAppendExtension[]>(
|
||||
[]
|
||||
);
|
||||
const badge$ = new BehaviorSubject<ChromeBadge | undefined>(undefined);
|
||||
const customNavLink$ = new BehaviorSubject<ChromeNavLink | undefined>(undefined);
|
||||
const helpSupportUrl$ = new BehaviorSubject<string>(docLinks.links.kibana.askElastic);
|
||||
|
@ -467,6 +467,9 @@ export class ChromeService {
|
|||
globalHelpExtensionMenuLinks$={globalHelpExtensionMenuLinks$}
|
||||
actionMenu$={application.currentActionMenu$}
|
||||
breadcrumbs$={currentProjectBreadcrumbs$}
|
||||
breadcrumbsAppendExtensions$={breadcrumbsAppendExtensions$.pipe(
|
||||
takeUntil(this.stop$)
|
||||
)}
|
||||
customBranding$={customBranding$}
|
||||
helpExtension$={helpExtension$.pipe(takeUntil(this.stop$))}
|
||||
helpSupportUrl$={helpSupportUrl$.pipe(takeUntil(this.stop$))}
|
||||
|
@ -500,7 +503,7 @@ export class ChromeService {
|
|||
badge$={badge$.pipe(takeUntil(this.stop$))}
|
||||
basePath={http.basePath}
|
||||
breadcrumbs$={breadcrumbs$.pipe(takeUntil(this.stop$))}
|
||||
breadcrumbsAppendExtension$={breadcrumbsAppendExtension$.pipe(takeUntil(this.stop$))}
|
||||
breadcrumbsAppendExtensions$={breadcrumbsAppendExtensions$.pipe(takeUntil(this.stop$))}
|
||||
customNavLink$={customNavLink$.pipe(takeUntil(this.stop$))}
|
||||
kibanaDocLink={docLinks.links.kibana.guide}
|
||||
docLinks={docLinks}
|
||||
|
@ -548,12 +551,24 @@ export class ChromeService {
|
|||
|
||||
setBreadcrumbs: setClassicBreadcrumbs,
|
||||
|
||||
getBreadcrumbsAppendExtension$: () => breadcrumbsAppendExtension$.pipe(takeUntil(this.stop$)),
|
||||
getBreadcrumbsAppendExtensions$: () =>
|
||||
breadcrumbsAppendExtensions$.pipe(takeUntil(this.stop$)),
|
||||
|
||||
setBreadcrumbsAppendExtension: (
|
||||
breadcrumbsAppendExtension?: ChromeBreadcrumbsAppendExtension
|
||||
breadcrumbsAppendExtension: ChromeBreadcrumbsAppendExtension
|
||||
) => {
|
||||
breadcrumbsAppendExtension$.next(breadcrumbsAppendExtension);
|
||||
breadcrumbsAppendExtensions$.next(
|
||||
[...breadcrumbsAppendExtensions$.getValue(), breadcrumbsAppendExtension].sort(
|
||||
({ order: orderA = 50 }, { order: orderB = 50 }) => orderA - orderB
|
||||
)
|
||||
);
|
||||
return () => {
|
||||
breadcrumbsAppendExtensions$.next(
|
||||
breadcrumbsAppendExtensions$
|
||||
.getValue()
|
||||
.filter((ext) => ext !== breadcrumbsAppendExtension)
|
||||
);
|
||||
};
|
||||
},
|
||||
|
||||
getGlobalHelpExtensionMenuLinks$: () => globalHelpExtensionMenuLinks$.asObservable(),
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { Observable } from 'rxjs';
|
||||
import type { ChromeBreadcrumbsAppendExtension } from '@kbn/core-chrome-browser';
|
||||
import useObservable from 'react-use/lib/useObservable';
|
||||
import { EuiFlexGroup } from '@elastic/eui';
|
||||
import classnames from 'classnames';
|
||||
import { HeaderExtension } from './header_extension';
|
||||
|
||||
export interface Props {
|
||||
breadcrumbsAppendExtensions$: Observable<ChromeBreadcrumbsAppendExtension[]>;
|
||||
}
|
||||
|
||||
export const BreadcrumbsWithExtensionsWrapper = ({
|
||||
breadcrumbsAppendExtensions$,
|
||||
children,
|
||||
}: PropsWithChildren<Props>) => {
|
||||
const breadcrumbsAppendExtensions = useObservable(breadcrumbsAppendExtensions$, []);
|
||||
|
||||
return breadcrumbsAppendExtensions.length === 0 ? (
|
||||
<>{children}</>
|
||||
) : (
|
||||
<EuiFlexGroup
|
||||
responsive={false}
|
||||
wrap={false}
|
||||
alignItems={'center'}
|
||||
className={'header__breadcrumbsWithExtensionContainer'}
|
||||
gutterSize={'none'}
|
||||
>
|
||||
{children}
|
||||
{breadcrumbsAppendExtensions.map((breadcrumbsAppendExtension, index) => {
|
||||
const isLast = breadcrumbsAppendExtensions.length - 1 === index;
|
||||
return (
|
||||
<HeaderExtension
|
||||
key={index}
|
||||
extension={breadcrumbsAppendExtension.content}
|
||||
containerClassName={classnames({
|
||||
'header__breadcrumbsAppendExtension--last': isLast,
|
||||
})}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
|
@ -82,9 +82,9 @@ describe('Header', () => {
|
|||
const recentlyAccessed$ = new BehaviorSubject([
|
||||
{ link: '', label: 'dashboard', id: 'dashboard' },
|
||||
]);
|
||||
const breadcrumbsAppendExtension$ = new BehaviorSubject<
|
||||
undefined | ChromeBreadcrumbsAppendExtension
|
||||
>(undefined);
|
||||
const breadcrumbsAppendExtensions$ = new BehaviorSubject<ChromeBreadcrumbsAppendExtension[]>(
|
||||
[]
|
||||
);
|
||||
const component = mountWithIntl(
|
||||
<Header
|
||||
{...mockProps()}
|
||||
|
@ -93,7 +93,7 @@ describe('Header', () => {
|
|||
recentlyAccessed$={recentlyAccessed$}
|
||||
isLocked$={isLocked$}
|
||||
customNavLink$={customNavLink$}
|
||||
breadcrumbsAppendExtension$={breadcrumbsAppendExtension$}
|
||||
breadcrumbsAppendExtensions$={breadcrumbsAppendExtensions$}
|
||||
headerBanner$={headerBanner$}
|
||||
helpMenuLinks$={of([])}
|
||||
isServerless={false}
|
||||
|
@ -108,17 +108,28 @@ describe('Header', () => {
|
|||
expect(component.render()).toMatchSnapshot();
|
||||
|
||||
act(() =>
|
||||
breadcrumbsAppendExtension$.next({
|
||||
content: (root: HTMLDivElement) => {
|
||||
root.innerHTML = '<div class="my-extension">__render__</div>';
|
||||
return () => (root.innerHTML = '');
|
||||
breadcrumbsAppendExtensions$.next([
|
||||
{
|
||||
content: (root: HTMLDivElement) => {
|
||||
root.innerHTML = '<div class="my-extension1">__render__</div>';
|
||||
return () => (root.innerHTML = '');
|
||||
},
|
||||
},
|
||||
})
|
||||
{
|
||||
content: (root: HTMLDivElement) => {
|
||||
root.innerHTML = '<div class="my-extension2">__render__</div>';
|
||||
return () => (root.innerHTML = '');
|
||||
},
|
||||
},
|
||||
])
|
||||
);
|
||||
component.update();
|
||||
expect(component.find('HeaderExtension').exists()).toBeTruthy();
|
||||
expect(component.find('HeaderExtension').length).toBe(2);
|
||||
expect(
|
||||
component.find('HeaderExtension').getDOMNode().querySelector('.my-extension')
|
||||
component.find('HeaderExtension').at(0).getDOMNode().querySelector('.my-extension1')
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
component.find('HeaderExtension').at(1).getDOMNode().querySelector('.my-extension2')
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
EuiHeader,
|
||||
EuiHeaderSection,
|
||||
EuiHeaderSectionItem,
|
||||
|
@ -19,7 +18,6 @@ import {
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import classnames from 'classnames';
|
||||
import React, { createRef, useState } from 'react';
|
||||
import useObservable from 'react-use/lib/useObservable';
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { HttpStart } from '@kbn/core-http-browser';
|
||||
import type { InternalApplicationStart } from '@kbn/core-application-browser-internal';
|
||||
|
@ -45,7 +43,7 @@ import { HeaderHelpMenu } from './header_help_menu';
|
|||
import { HeaderLogo } from './header_logo';
|
||||
import { HeaderNavControls } from './header_nav_controls';
|
||||
import { HeaderActionMenu, useHeaderActionMenuMounter } from './header_action_menu';
|
||||
import { HeaderExtension } from './header_extension';
|
||||
import { BreadcrumbsWithExtensionsWrapper } from './breadcrumbs_with_extensions';
|
||||
import { HeaderTopBanner } from './header_top_banner';
|
||||
import { HeaderMenuButton } from './header_menu_button';
|
||||
import { ScreenReaderRouteAnnouncements, SkipToMainContent } from './screen_reader_a11y';
|
||||
|
@ -56,7 +54,7 @@ export interface HeaderProps {
|
|||
headerBanner$: Observable<ChromeUserBanner | undefined>;
|
||||
badge$: Observable<ChromeBadge | undefined>;
|
||||
breadcrumbs$: Observable<ChromeBreadcrumb[]>;
|
||||
breadcrumbsAppendExtension$: Observable<ChromeBreadcrumbsAppendExtension | undefined>;
|
||||
breadcrumbsAppendExtensions$: Observable<ChromeBreadcrumbsAppendExtension[]>;
|
||||
customNavLink$: Observable<ChromeNavLink | undefined>;
|
||||
homeHref: string;
|
||||
kibanaDocLink: string;
|
||||
|
@ -88,7 +86,7 @@ export function Header({
|
|||
basePath,
|
||||
onIsLockedUpdate,
|
||||
homeHref,
|
||||
breadcrumbsAppendExtension$,
|
||||
breadcrumbsAppendExtensions$,
|
||||
globalHelpExtensionMenuLinks$,
|
||||
customBranding$,
|
||||
isServerless,
|
||||
|
@ -96,7 +94,6 @@ export function Header({
|
|||
}: HeaderProps) {
|
||||
const [isNavOpen, setIsNavOpen] = useState(false);
|
||||
const [navId] = useState(htmlIdGenerator()());
|
||||
const breadcrumbsAppendExtension = useObservable(breadcrumbsAppendExtension$);
|
||||
const headerActionMenuMounter = useHeaderActionMenuMounter(application.currentActionMenu$);
|
||||
|
||||
const toggleCollapsibleNavRef = createRef<HTMLButtonElement & { euiAnimate: () => void }>();
|
||||
|
@ -206,24 +203,11 @@ export function Header({
|
|||
|
||||
<HeaderNavControls side="left" navControls$={observables.navControlsLeft$} />
|
||||
</EuiHeaderSection>
|
||||
|
||||
{!breadcrumbsAppendExtension ? (
|
||||
Breadcrumbs
|
||||
) : (
|
||||
<EuiFlexGroup
|
||||
responsive={false}
|
||||
wrap={false}
|
||||
alignItems={'center'}
|
||||
className={'header__breadcrumbsWithExtensionContainer'}
|
||||
gutterSize={'none'}
|
||||
>
|
||||
{Breadcrumbs}
|
||||
<HeaderExtension
|
||||
extension={breadcrumbsAppendExtension.content}
|
||||
containerClassName={'header__breadcrumbsAppendExtension'}
|
||||
/>
|
||||
</EuiFlexGroup>
|
||||
)}
|
||||
<BreadcrumbsWithExtensionsWrapper
|
||||
breadcrumbsAppendExtensions$={breadcrumbsAppendExtensions$}
|
||||
>
|
||||
{Breadcrumbs}
|
||||
</BreadcrumbsWithExtensionsWrapper>
|
||||
|
||||
<HeaderBadge badge$={observables.badge$} />
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ describe('Header', () => {
|
|||
const mockProps: Omit<ProjectHeaderProps, 'children'> = {
|
||||
application: mockApplication,
|
||||
breadcrumbs$: Rx.of([]),
|
||||
breadcrumbsAppendExtensions$: Rx.of([]),
|
||||
actionMenu$: Rx.of(undefined),
|
||||
docLinks: docLinksServiceMock.createStartContract(),
|
||||
globalHelpExtensionMenuLinks$: Rx.of([]),
|
||||
|
|
|
@ -12,15 +12,16 @@ import {
|
|||
EuiHeaderLogo,
|
||||
EuiHeaderSection,
|
||||
EuiHeaderSectionItem,
|
||||
EuiLoadingSpinner,
|
||||
useEuiTheme,
|
||||
EuiThemeComputed,
|
||||
EuiImage,
|
||||
EuiLoadingSpinner,
|
||||
EuiThemeComputed,
|
||||
useEuiTheme,
|
||||
} from '@elastic/eui';
|
||||
import { css } from '@emotion/react';
|
||||
import type { InternalApplicationStart } from '@kbn/core-application-browser-internal';
|
||||
import {
|
||||
ChromeBreadcrumb,
|
||||
type ChromeBreadcrumbsAppendExtension,
|
||||
ChromeGlobalHelpExtensionMenuLink,
|
||||
ChromeHelpExtension,
|
||||
ChromeHelpMenuLink,
|
||||
|
@ -33,7 +34,7 @@ import { MountPoint } from '@kbn/core-mount-utils-browser';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
|
||||
import { Router } from '@kbn/shared-ux-router';
|
||||
import React, { useCallback, type ComponentProps } from 'react';
|
||||
import React, { type ComponentProps, useCallback } from 'react';
|
||||
import useObservable from 'react-use/lib/useObservable';
|
||||
import { debounceTime, Observable } from 'rxjs';
|
||||
import type { CustomBranding } from '@kbn/core-custom-branding-common';
|
||||
|
@ -46,6 +47,7 @@ import { HeaderTopBanner } from '../header/header_top_banner';
|
|||
import { ScreenReaderRouteAnnouncements, SkipToMainContent } from '../header/screen_reader_a11y';
|
||||
import { AppMenuBar } from './app_menu';
|
||||
import { ProjectNavigation } from './navigation';
|
||||
import { BreadcrumbsWithExtensionsWrapper } from '../header/breadcrumbs_with_extensions';
|
||||
|
||||
const getHeaderCss = ({ size, colors }: EuiThemeComputed) => ({
|
||||
logo: {
|
||||
|
@ -114,6 +116,7 @@ const headerStrings = {
|
|||
export interface Props extends Pick<ComponentProps<typeof HeaderHelpMenu>, 'isServerless'> {
|
||||
headerBanner$: Observable<ChromeUserBanner | undefined>;
|
||||
breadcrumbs$: Observable<ChromeBreadcrumb[]>;
|
||||
breadcrumbsAppendExtensions$: Observable<ChromeBreadcrumbsAppendExtension[]>;
|
||||
actionMenu$: Observable<MountPoint | undefined>;
|
||||
docLinks: DocLinksStart;
|
||||
children: React.ReactNode;
|
||||
|
@ -228,6 +231,7 @@ export const ProjectHeader = ({
|
|||
toggleSideNav,
|
||||
customBranding$,
|
||||
isServerless,
|
||||
breadcrumbsAppendExtensions$,
|
||||
...observables
|
||||
}: Props) => {
|
||||
const headerActionMenuMounter = useHeaderActionMenuMounter(observables.actionMenu$);
|
||||
|
@ -282,7 +286,11 @@ export const ProjectHeader = ({
|
|||
coreStart={{ application }}
|
||||
css={headerCss.redirectAppLinksContainer}
|
||||
>
|
||||
<Breadcrumbs breadcrumbs$={observables.breadcrumbs$} />
|
||||
<BreadcrumbsWithExtensionsWrapper
|
||||
breadcrumbsAppendExtensions$={breadcrumbsAppendExtensions$}
|
||||
>
|
||||
<Breadcrumbs breadcrumbs$={observables.breadcrumbs$} />
|
||||
</BreadcrumbsWithExtensionsWrapper>
|
||||
</RedirectAppLinks>
|
||||
</EuiHeaderSectionItem>
|
||||
</EuiHeaderSection>
|
||||
|
|
|
@ -59,7 +59,7 @@ const createStartContractMock = () => {
|
|||
getIsFeedbackBtnVisible$: jest.fn(),
|
||||
setIsFeedbackBtnVisible: jest.fn(),
|
||||
},
|
||||
getBreadcrumbsAppendExtension$: jest.fn(),
|
||||
getBreadcrumbsAppendExtensions$: jest.fn(),
|
||||
setBreadcrumbsAppendExtension: jest.fn(),
|
||||
getGlobalHelpExtensionMenuLinks$: jest.fn(),
|
||||
registerGlobalHelpExtensionMenuLink: jest.fn(),
|
||||
|
@ -95,7 +95,7 @@ const createStartContractMock = () => {
|
|||
startContract.getIsVisible$.mockReturnValue(new BehaviorSubject(false));
|
||||
startContract.getBadge$.mockReturnValue(new BehaviorSubject({} as ChromeBadge));
|
||||
startContract.getBreadcrumbs$.mockReturnValue(new BehaviorSubject([{} as ChromeBreadcrumb]));
|
||||
startContract.getBreadcrumbsAppendExtension$.mockReturnValue(new BehaviorSubject(undefined));
|
||||
startContract.getBreadcrumbsAppendExtensions$.mockReturnValue(new BehaviorSubject([]));
|
||||
startContract.getCustomNavLink$.mockReturnValue(new BehaviorSubject(undefined));
|
||||
startContract.getGlobalHelpExtensionMenuLinks$.mockReturnValue(new BehaviorSubject([]));
|
||||
startContract.getHelpExtension$.mockReturnValue(new BehaviorSubject(undefined));
|
||||
|
|
|
@ -23,6 +23,8 @@ export interface ChromeBreadcrumb extends EuiBreadcrumb {
|
|||
/** @public */
|
||||
export interface ChromeBreadcrumbsAppendExtension {
|
||||
content: MountPoint<HTMLDivElement>;
|
||||
/** The order in which the extension should be appended to the breadcrumbs. Default is 50 */
|
||||
order?: number;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
|
|
|
@ -91,16 +91,16 @@ export interface ChromeStart {
|
|||
setBreadcrumbs(newBreadcrumbs: ChromeBreadcrumb[], params?: ChromeSetBreadcrumbsParams): void;
|
||||
|
||||
/**
|
||||
* Get an observable of the current extension appended to breadcrumbs
|
||||
* Get an observable of the current extensions appended to breadcrumbs
|
||||
*/
|
||||
getBreadcrumbsAppendExtension$(): Observable<ChromeBreadcrumbsAppendExtension | undefined>;
|
||||
getBreadcrumbsAppendExtensions$(): Observable<ChromeBreadcrumbsAppendExtension[]>;
|
||||
|
||||
/**
|
||||
* Mount an element next to the last breadcrumb
|
||||
*/
|
||||
setBreadcrumbsAppendExtension(
|
||||
breadcrumbsAppendExtension?: ChromeBreadcrumbsAppendExtension
|
||||
): void;
|
||||
breadcrumbsAppendExtension: ChromeBreadcrumbsAppendExtension
|
||||
): () => void;
|
||||
|
||||
/**
|
||||
* Get an observable of the current custom nav link
|
||||
|
|
|
@ -76,13 +76,8 @@ export const useBreadcrumbs = (
|
|||
|
||||
useEffect(() => {
|
||||
if (breadcrumbsAppendExtension) {
|
||||
setBreadcrumbsAppendExtension(breadcrumbsAppendExtension);
|
||||
return setBreadcrumbsAppendExtension(breadcrumbsAppendExtension);
|
||||
}
|
||||
return () => {
|
||||
if (breadcrumbsAppendExtension) {
|
||||
setBreadcrumbsAppendExtension(undefined);
|
||||
}
|
||||
};
|
||||
}, [breadcrumbsAppendExtension, setBreadcrumbsAppendExtension]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -66,7 +66,7 @@ export const DecorateWithKibanaContext: DecoratorFn = (story) => {
|
|||
},
|
||||
},
|
||||
setBreadcrumbs: () => {},
|
||||
setBreadcrumbsAppendExtension: () => {},
|
||||
setBreadcrumbsAppendExtension: () => () => {},
|
||||
},
|
||||
data: {
|
||||
search: {
|
||||
|
|
|
@ -116,13 +116,8 @@ export const useBreadcrumbs = (
|
|||
|
||||
useEffect(() => {
|
||||
if (breadcrumbsAppendExtension) {
|
||||
setBreadcrumbsAppendExtension(breadcrumbsAppendExtension);
|
||||
return setBreadcrumbsAppendExtension(breadcrumbsAppendExtension);
|
||||
}
|
||||
return () => {
|
||||
if (breadcrumbsAppendExtension) {
|
||||
setBreadcrumbsAppendExtension(undefined);
|
||||
}
|
||||
};
|
||||
}, [breadcrumbsAppendExtension, setBreadcrumbsAppendExtension]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue