-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[SharedUx] Chrome/Navigation package (#152510)
**The API for the link definition is subject to change.** This PR provides linking functionality and structure that will give solution devs a starting point for side nav in their projects. The API uses simple hrefs for now, because it's the easiest thing to start with. Planning forward, we are thinking of a different navigation model that separates nav structure from presentation of each nav item - this will allow reuse of the structure without reusing the presentation. ## Isolated dependencies In order for this component to be usable in `main`, a bit further work is currently required in the ChromeStart service and the Serverless plugin. These links are examples of a usable implementation that link to a POC branch: * Light mode for the side nav container: tsullivan@0a32333cdf0 * Extensions to Serverless plugin and the ChromeStart service: tsullivan@16b0aad610f ## Summary Introduces a component to host the side navigation in Kibana. Solution teams can insert their own content, and have other small options to customize the presentation: see the storybook demos for more. Closes #154479 Closes #154484 Closes #154485 ~~Closes #154489 Closes #154481 Closes #154480 Closes #154486 Closes #154487 <img width="1462" alt="image" src="https://user-images.githubusercontent.com/908371/233739506-7b88646e-3c19-44f0-afbf-ca1a23d32c57.png"> ## Developer documentation See the Storybook demos: * run: `yarn storybook shared_ux` * Find the `Chrome > Navigation` section in the Storybook app ### Checklist Delete any items that are not applicable to this PR. - [x] Home icon links to Project's "home" - or the customer user setting - [x] Home icon shows loading indicator - [x] All the Platform links navigate to the correct place - ~~Platform links are not shown if the underlying plugin is disabled~~ - [x] Nav items define their links using `href` only - [x] All href links work - [x] Nav menu item to link to Cloud deployment - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --------- Co-authored-by: kibanamachine <[email protected]>
- Loading branch information
1 parent
11a80ce
commit 604a02f
Showing
31 changed files
with
1,637 additions
and
0 deletions.
There are no files selected for viewing
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--- | ||
id: sharedUX/Chrome/Navigation | ||
slug: /shared-ux/chrome/navigation | ||
title: Kibana Chrome Navigation | ||
description: Navigation container to render items for cross-app linking | ||
tags: ['shared-ux', 'component', 'chrome', 'navigation'] | ||
date: 2023-02-28 | ||
--- | ||
|
||
## Description | ||
|
||
Empty package generated by @kbn/generate | ||
@kbn/shared-ux-chrome-navigation | ||
Navigation container to render items for cross-app linking | ||
|
||
## API | ||
|
||
| Export | Description | | ||
|---|---| | ||
| `NavigationProvider` | Provides contextual services to `Navigation`. | | ||
| `NavigationKibanaProvider` | Maps Kibana dependencies to provide contextual services to `Navigation`. | | ||
| `Navigation` | Uses a `Provider` to access contextual services and render the component. | | ||
|
||
## EUI Promotion Status | ||
|
||
This component is not currently considered for promotion to EUI. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/* | ||
* 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 { NavigationKibanaProvider, NavigationProvider } from './src/services'; | ||
export { Navigation } from './src/ui/navigation'; | ||
export type { NavigationProps, NavigationServices, NavItemProps } from './types'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
module.exports = { | ||
preset: '@kbn/test', | ||
rootDir: '../../../..', | ||
roots: ['<rootDir>/packages/shared-ux/chrome/navigation'], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"type": "shared-common", | ||
"id": "@kbn/shared-ux-chrome-navigation", | ||
"owner": "@elastic/appex-sharedux" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/* | ||
* 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 { | ||
getServicesMock as getNavigationServicesMock, | ||
getSolutionPropertiesMock, | ||
} from './src/jest'; | ||
export { StorybookMock as NavigationStorybookMock } from './src/storybook'; | ||
export type { Params as NavigationStorybookParams } from './src/storybook'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
* 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 { NavigationServices, SolutionProperties } from '../../types'; | ||
|
||
export const getServicesMock = (): NavigationServices => { | ||
const navigateToUrl = jest.fn().mockResolvedValue(undefined); | ||
const basePath = { prepend: jest.fn((path: string) => `/base${path}`) }; | ||
const loadingCount = 0; | ||
|
||
return { | ||
basePath, | ||
loadingCount, | ||
navIsOpen: true, | ||
navigateToUrl, | ||
}; | ||
}; | ||
|
||
export const getSolutionPropertiesMock = (): SolutionProperties => ({ | ||
id: 'example_project', | ||
icon: 'logoObservability', | ||
name: 'Example project', | ||
items: [ | ||
{ | ||
id: 'root', | ||
name: '', | ||
items: [ | ||
{ | ||
id: 'get_started', | ||
name: 'Get started', | ||
href: '/app/example_project/get_started', | ||
}, | ||
{ | ||
id: 'alerts', | ||
name: 'Alerts', | ||
href: '/app/example_project/alerts', | ||
}, | ||
{ | ||
id: 'cases', | ||
name: 'Cases', | ||
href: '/app/example_project/cases', | ||
}, | ||
], | ||
}, | ||
{ | ||
id: 'example_settings', | ||
name: 'Settings', | ||
items: [ | ||
{ | ||
id: 'logs', | ||
name: 'Logs', | ||
href: '/app/management/logs', | ||
}, | ||
{ | ||
id: 'signals', | ||
name: 'Signals', | ||
href: '/app/management/signals', | ||
}, | ||
{ | ||
id: 'tracing', | ||
name: 'Tracing', | ||
href: '/app/management/tracing', | ||
}, | ||
], | ||
}, | ||
], | ||
}); |
59 changes: 59 additions & 0 deletions
59
packages/shared-ux/chrome/navigation/mocks/src/storybook.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* 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 { AbstractStorybookMock } from '@kbn/shared-ux-storybook-mock'; | ||
import { action } from '@storybook/addon-actions'; | ||
import { NavigationProps, NavigationServices } from '../../types'; | ||
|
||
type Arguments = NavigationProps & NavigationServices; | ||
export type Params = Pick< | ||
Arguments, | ||
'activeNavItemId' | 'loadingCount' | 'navIsOpen' | 'platformConfig' | 'solutions' | ||
>; | ||
|
||
export class StorybookMock extends AbstractStorybookMock<NavigationProps, NavigationServices> { | ||
propArguments = {}; | ||
|
||
serviceArguments = { | ||
navIsOpen: { | ||
control: 'boolean', | ||
defaultValue: true, | ||
}, | ||
loadingCount: { | ||
control: 'number', | ||
defaultValue: 0, | ||
}, | ||
}; | ||
|
||
dependencies = []; | ||
|
||
getServices(params: Params): NavigationServices { | ||
const { navIsOpen } = params; | ||
|
||
const navAction = action('Navigate to'); | ||
const navigateToUrl = (url: string) => { | ||
navAction(url); | ||
return Promise.resolve(); | ||
}; | ||
|
||
return { | ||
...params, | ||
basePath: { prepend: (suffix: string) => `/basepath${suffix}` }, | ||
navigateToUrl, | ||
navIsOpen, | ||
}; | ||
} | ||
|
||
getProps(params: Params): NavigationProps { | ||
return { | ||
...params, | ||
homeHref: '#', | ||
linkToCloud: 'projects', | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"name": "@kbn/shared-ux-chrome-navigation", | ||
"private": true, | ||
"version": "1.0.0", | ||
"license": "SSPL-1.0 OR Elastic License 2.0" | ||
} |
77 changes: 77 additions & 0 deletions
77
packages/shared-ux/chrome/navigation/src/model/create_side_nav.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* | ||
* 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 type { EuiSideNavItemType } from '@elastic/eui'; | ||
import type { NavigationModelDeps } from '.'; | ||
import type { NavItemProps, PlatformSectionConfig } from '../../types'; | ||
|
||
type MyEuiSideNavItem = EuiSideNavItemType<unknown>; | ||
type OnClickFn = MyEuiSideNavItem['onClick']; | ||
|
||
/** | ||
* Factory function to return a function that processes modeled nav items into EuiSideNavItemType | ||
* The factory puts memoized function arguments in scope for iterations of the recursive item processing. | ||
*/ | ||
export const createSideNavDataFactory = ( | ||
deps: NavigationModelDeps, | ||
activeNavItemId: string | undefined | ||
) => { | ||
const { basePath, navigateToUrl } = deps; | ||
const createSideNavData = ( | ||
parentIds: string | number = '', | ||
navItems: NavItemProps[], | ||
platformSectionConfig?: PlatformSectionConfig | ||
): Array<EuiSideNavItemType<unknown>> => | ||
navItems.reduce<MyEuiSideNavItem[]>((accum, item) => { | ||
const { id, name, items: subNav, href } = item; | ||
const config = platformSectionConfig?.properties?.[id]; | ||
if (config?.enabled === false) { | ||
// return accumulated set without the item that is not enabled | ||
return accum; | ||
} | ||
|
||
let onClick: OnClickFn | undefined; | ||
|
||
const fullId = [parentIds, id].filter(Boolean).join('.'); | ||
|
||
if (href) { | ||
onClick = (event: React.MouseEvent) => { | ||
event.preventDefault(); | ||
navigateToUrl(basePath.prepend(href)); | ||
}; | ||
} | ||
|
||
let filteredSubNav: MyEuiSideNavItem[] | undefined; | ||
if (subNav) { | ||
// recursion | ||
const nextConfig = platformSectionConfig?.properties?.[id]; | ||
filteredSubNav = createSideNavData(fullId, subNav, nextConfig); | ||
} | ||
|
||
let isSelected: boolean = false; | ||
let subjId = fullId; | ||
if (!subNav && fullId === activeNavItemId) { | ||
// if there are no subnav items and ID is current, mark the item as selected | ||
isSelected = true; | ||
subjId += '-selected'; | ||
} | ||
|
||
const next: MyEuiSideNavItem = { | ||
id: fullId, | ||
name, | ||
isSelected, | ||
onClick, | ||
href, | ||
items: filteredSubNav, | ||
['data-test-subj']: `nav-item-${subjId}`, | ||
}; | ||
return [...accum, next]; | ||
}, []); | ||
|
||
return createSideNavData; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* 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 { BasePathService, NavigateToUrlFn } from '../../types/internal'; | ||
import { analyticsItemSet } from './platform_nav/analytics'; | ||
import { devtoolsItemSet } from './platform_nav/devtools'; | ||
import { mlItemSet } from './platform_nav/machine_learning'; | ||
import { managementItemSet } from './platform_nav/management'; | ||
|
||
export interface NavigationModelDeps { | ||
basePath: BasePathService; | ||
navigateToUrl: NavigateToUrlFn; | ||
} | ||
|
||
/** | ||
* @public | ||
*/ | ||
export enum Platform { | ||
Recents = 'recents', | ||
Analytics = 'analytics', | ||
MachineLearning = 'ml', | ||
DevTools = 'devTools', | ||
Management = 'management', | ||
} | ||
|
||
/** | ||
* @public | ||
*/ | ||
export const navItemSet = { | ||
[Platform.Analytics]: analyticsItemSet, | ||
[Platform.MachineLearning]: mlItemSet, | ||
[Platform.DevTools]: devtoolsItemSet, | ||
[Platform.Management]: managementItemSet, | ||
}; | ||
|
||
export { NavigationModel } from './model'; |
Oops, something went wrong.