diff --git a/dev_docs/nav-kibana-dev.docnav.json b/dev_docs/nav-kibana-dev.docnav.json index dc8a4373f5450..08c0fef042d34 100644 --- a/dev_docs/nav-kibana-dev.docnav.json +++ b/dev_docs/nav-kibana-dev.docnav.json @@ -222,7 +222,7 @@ "id": "ktCustomServerlessImage" }, { - "id": "kibDevTutorialsServerlessProjectNavigation" + "id": "kibDevTutorialsSolutionNavigation" } ] }, @@ -240,8 +240,8 @@ "pageId": "kibDevDocsSharedUxOverview", "items": [ { - "label": "Serverless Project Navigation", - "id": "kibDevTutorialsServerlessProjectNavigation" + "label": "Solution Navigation (stateful solution nav and serverless navigation", + "id": "kibDevTutorialsSolutionNavigation" }, { "id": "kibDevTutorialFileService", diff --git a/packages/shared-ux/chrome/serverless_project_navigation.mdx b/packages/shared-ux/chrome/solution_navigation.mdx similarity index 77% rename from packages/shared-ux/chrome/serverless_project_navigation.mdx rename to packages/shared-ux/chrome/solution_navigation.mdx index 786c0052c654d..c4d0743c59800 100644 --- a/packages/shared-ux/chrome/serverless_project_navigation.mdx +++ b/packages/shared-ux/chrome/solution_navigation.mdx @@ -1,17 +1,17 @@ --- -id: kibDevTutorialsServerlessProjectNavigation -slug: /kibana-dev-docs/serverless-project-navigation -title: Serverless project navigation -description: Project navigation replaces the default Kibana navigation in serverless mode, providing a more tailored experience for each project. Learn how to build a custom navigation for your project. +id: kibDevTutorialsSolutionNavigation +slug: /kibana-dev-docs/solution-navigation +title: Solution navigation +description: Solution navigation replaces the default Kibana navigation in serverless mode or in stateful mode when a space solution is set, providing a more tailored experience for each solution. Learn how to build a custom navigation for your space solution or serverless project. date: 2023-07-26 -tags: ['kibana', 'serverless', 'navigation'] +tags: ['kibana', 'serverless', 'solution', 'navigation'] --- ## Introduction -Welcome to the serverless project navigation documentation. Our tools help teams build customizable and flexible navigation for their serverless projects. Project navigation replaces the default Kibana navigation in serverless mode, providing a more tailored experience for each project. +Welcome to the solution navigation documentation. Our tools help teams build customizable and flexible navigation for their solution (in stateful) or serverless projects. Solution navigation replaces the classic Kibana navigation in serverless mode or in stateful mode when a "space solution" is set, providing a more tailored experience for each solution. -- [Serverless project navigation](#serverless-project-navigation) +- [Solution navigation](#solution-navigation) - [Left Side Navigation](#left-side-navigation) - [Navigation Tree Definition](#navigation-tree-definition) - [Example](#example) @@ -31,12 +31,12 @@ Welcome to the serverless project navigation documentation. Our tools help teams ### Building Blocks -The project navigation is composed of several key building blocks that work together to form a comprehensive navigation system. These building blocks include: +The solution navigation is composed of several key building blocks that work together to form a comprehensive navigation system. These building blocks include: -1. **Left Side Navigation**: Allow users to navigate through different sections of the project. +1. **Left Side Navigation**: Allow users to navigate through different sections of the solution. 2. **Breadcrumbs**: A visual representation of the user's current location within the navigation hierarchy. 3. **Header action menu**: A customizable toolbar that provides quick access to important actions and features. -4. **Global Search**: A navigational search input that enables users to quickly access specific content within the project. +4. **Global Search**: A navigational search input that enables users to quickly access specific content within the solution. In the following sections, we will explore each of these building blocks in detail. @@ -46,7 +46,7 @@ In the following sections, we will explore each of these building blocks in deta > Left Side Navigation is available in shared_ux storybook under the `Chrome/Navigation` section. You can explore the components and their properties there. > `yarn storybook shared_ux` -The left side navigation is a primary way for users to navigate through different sections of the project. It consists of a tree of navigation items that can be expanded/collapsed or opened in a side panel. Apart from the navigation tree it also supports special pre-built blocks like recently accessed items. The main part of the navigation tree is project's navigation: this is fully configured and supported by the project teams (e.g. Observability). We also provide pre-configured platform sections as presets that solutions can use as part of their navigation (e.g. `ml`, `analytics`). Solutions can customize those sections to their needs. +The left side navigation is a primary way for users to navigate through different sections of the solution. It consists of a tree of navigation items that can be expanded/collapsed or opened in a side panel. Apart from the navigation tree it also supports special pre-built blocks like recently accessed items. The main part of the navigation tree is solution's navigation: this is fully configured and supported by the solution teams (e.g. Observability). We also provide pre-configured platform sections as presets that solutions can use as part of their navigation (e.g. `ml`, `analytics`). Solutions can customize those sections to their needs. ### Navigation Tree Definition @@ -63,8 +63,8 @@ const navigationTree: NavigationTreeDefinition = { body: [ { type: 'recentlyAccessed' }, // Add the recently accessed items { - type: 'navGroup', // A top level group for the project's navigation the main part of the navigation tree - id: 'search_project_nav', + type: 'navGroup', // A top level group for the solution's navigation the main part of the navigation tree + id: 'search_nav', title: 'Elasticsearch', icon: 'logoElasticsearch', defaultIsCollapsed: false, // ensures this section is automatically expanded when users first load the page @@ -113,7 +113,7 @@ const navigationTree: NavigationTreeDefinition = { footer: [ { type: 'navGroup', - id: 'project_settings_project_nav', + id: 'project_settings_nav', title: 'Project settings', icon: 'gear', breadcrumbStatus: 'hidden', @@ -145,9 +145,12 @@ const navigationTree: NavigationTreeDefinition = { Once the navigation tree is defined we need to 1. Convert it to an `Observable` -2. Initiate the navigation in the `serverless` plugin +2. (a) Initiate the navigation in the `serverless` plugin (Serverless Kibana) + (b) or Initiate the navigation in the `navigation` plugin (Stateful Kibana) ```tsx +// Serverless Kibana + import { of } from 'rxjs'; // plugin.ts (public) "start()" @@ -159,6 +162,23 @@ serverless.initNavigation(navigationTree$, /* optional */ { }); ``` +```tsx +// Stateful Kibana + +import { of } from 'rxjs'; + +// plugin.ts (public) "start()" +const navigationTree$ = of(navigationTree); + +navigation.addSolutionNavigation({ + id: 'oblt', + title, + icon: 'logoObservability', + navigationTree$, + dataTestSubj: 'myNavigation', +}); +``` + #### Navigation tree API > **Warning** @@ -294,10 +314,17 @@ const panelContentProvider: PanelContentProvider = (id: string) => { // All other nodes content ids that haven't match will be auto-generated }; -// 2. Provide it when initiating the navigation -// ----------------------------------------- - +// 2a. Provide it when initiating the navigation (serverless) +// ---------------------------------------------------------- serverless.initNavigation(navigationTree$, { panelContentProvider }); + +// 2b. Provide it when initiating the navigation (stateful) +// -------------------------------------------------------- +navigation.addSolutionNavigation({ + ... + navigationTree$, + panelContentProvider +}); ``` ### Important Concepts @@ -306,7 +333,7 @@ serverless.initNavigation(navigationTree$, { panelContentProvider }); [Deep links](https://github.com/elastic/kibana/blob/f5034e60a501e7b61a3e1bff34e64c9b94c71344/packages/core/application/core-application-browser/src/application.ts#L281-L314) are a Kibana core's mechanism for registering sub-pages within an app. In "classic" Kibana they are used for the default side navigation, navigation APIs and the global search. Teams can register the deep links when they register their app. They can also update their registered deep links, or unregister deep links dynamically. -The serverless navigation API uses the same deep links mechanism to configure the navigation tree. The `link` property of the `NodeDefinition` interface refers to the deep links registered by apps. The `link` property can be either can be either the ID of an app, or a deep link ID. +The solution navigation API uses the same deep links mechanism to configure the navigation tree. The `link` property of the `NodeDefinition` interface refers to the deep links registered by apps. The `link` property can be either can be either the ID of an app, or a deep link ID. There are multiple benefits of using deep links instead of the hardcoded URLs when configuring the navigation tree: @@ -389,30 +416,30 @@ Technically, multiple paths can be active simultaneously and multiple nodes can ## Breadcrumbs -Breadcrumbs is a list of links that represent the current navigation path. Project navigation breadcrumbs are automatically generated based on the navigation tree set for the [side navigation](#left-side-navigation) and the currently active navigation path. +Breadcrumbs is a list of links that represent the current navigation path. Solution navigation breadcrumbs are automatically generated based on the navigation tree set for the [side navigation](#left-side-navigation) and the currently active navigation path. -Project breadcrumbs are built from 3 sections: +Solution breadcrumbs are built from 3 sections: -1. **Project name** -2. **Project navigation:** automatically set based on the project's navigation tree and the currently active navigation path +1. **Project name / Deployment** +2. **Solution navigation:** automatically set based on the solution's navigation tree and the currently active navigation path 3. **Deeper context:** manually set by currently active application -### Project breadcrumbs sections +### Solution breadcrumbs sections -#### Project name breadcrumb +#### Project name/Deployment breadcrumb -Project name breadcrumb is always displayed as the first breadcrumb. It displays the project name and opens a popup with links to manage the project and view all projects. +Project name / Deployment breadcrumb is always displayed as the first breadcrumb. It displays either the project name (in serverless) or the deployment and opens a popup with either (a) links to manage the project and view all projects (serverless) or (b) the deployment and view all deployments (stateful). -#### Project navigation breadcrumbs +#### Solution navigation breadcrumbs -Project navigation breadcrumbs are automatically generated based on the project's navigation tree set for the [side navigation](#left-side-navigation) and the currently active navigation path. +Solution navigation breadcrumbs are automatically generated based on the solution's navigation tree set for the [side navigation](#left-side-navigation) and the currently active navigation path. > **Note** > If you have static pages that are accessible from an app and should display breadcrumbs but shouldn't be visible in the sidenav, you can add such pages to the navigation tree with `sideNavStatus: 'hidden'`. #### Deeper context breadcrumbs -Most of the applications are already setting the complete breadcrumb path for stateful Kibana navigation using the `chrome.setBreadcrumbs` API. It is possible to reuse the existing breadcrumbs for deeper context breadcrumbs in the serverless project navigation. For this, apps need to add a deepLinkId to the breadcrumb object. This `deepLinkId` will be used to match and merge the project navigation breadcrumbs with the deeper context breadcrumbs set in `chrome.setBreadcrumbs`. +Most of the applications are already setting the complete breadcrumb path for stateful Kibana navigation using the `chrome.setBreadcrumbs` API. It is possible to reuse the existing breadcrumbs for deeper context breadcrumbs in the solution navigation. For this, apps need to add a deepLinkId to the breadcrumb object. This `deepLinkId` will be used to match and merge the solution navigation breadcrumbs with the deeper context breadcrumbs set in `chrome.setBreadcrumbs`. For example, consider the navigation tree: @@ -434,7 +461,7 @@ const navigationTree: NavigationTreeDefinition = { }; ``` -When on `ml:anomalyexplorer` page, the project navigation breadcrumbs will be: +When on `ml:anomalyexplorer` page, the solution navigation breadcrumbs will be: ```ts [ @@ -471,11 +498,11 @@ chrome.setBreadcrumbs([ ]) ``` -The resulting project breadcrumbs list will be: +The resulting breadcrumbs list will be: ```ts [ - {}, // project name breadcrumb + {}, // project name/deployment breadcrumb { text: 'AI Ops' }, @@ -489,7 +516,7 @@ The resulting project breadcrumbs list will be: ] ``` -Alternatively, the deeper context breadcrumbs can be manually set using the `serverless.setBreadcrumbs` API. +Alternatively, the deeper context breadcrumbs can be manually (only in Serverless) set using the `serverless.setBreadcrumbs` API. ```ts serverless.setBreadcrumbs([ @@ -502,9 +529,9 @@ serverless.setBreadcrumbs([ These breadcrumbs are removed when the active navigation path changes. -### Overriding breadcrumbs +### Overriding breadcrumbs (serverless) -Apps can override navigation breadcrumbs. This will override navigation breadcrumbs keeping the root "project name" breadcrumb: +In serverless, apps can override navigation breadcrumbs. This will override navigation breadcrumbs keeping the root "project name/deployment" breadcrumb: ```ts pluginsStart.serverless.setBreadcrumbs([b1, b2, b3], { absolute: true }); @@ -514,43 +541,50 @@ The override is automatically reset when the active navigation path changes. ## Header Action Menu -The Header Action Menu, aka application toolbar, is a horizontal bar that is **conditionally** displayed at the top of the page below the header where apps can put their custom actions. Like the header, the toolbar has fixed position. Unlike the header however, this bar only appears when an application has registered content to show. Another UI difference, is the toolbar could be covered by flyouts or full-page overlays on the page. There might be other slight styling and positioning changes comparing to the toolbar in the default Kibana navigation. -There is no serverless specific API or behavior change for the toolbar. To set custom content in this area, use the same API as in the default Kibana `setHeaderActionMenu` [source](https://github.com/elastic/kibana/blob/188009f9376d5976b5db37e04c52a2b5bdaf9771/packages/core/application/core-application-browser/src/app_mount.ts#L176-L205). To unset content, call `setHeaderActionMenu` with `undefined`. +The Header Action Menu, aka application toolbar, is a horizontal bar that is **conditionally** displayed at the top of the page below the header where apps can put their custom actions. Like the header, the toolbar has fixed position. Unlike the header however, this bar only appears when an application has registered content to show. Another UI difference, is the toolbar could be covered by flyouts or full-page overlays on the page. There might be other slight styling and positioning changes comparing to the toolbar in the classic Kibana navigation. +There is no specific API or behavior change for the toolbar. To set custom content in this area, use the same API as in the classic Kibana `setHeaderActionMenu` [source](https://github.com/elastic/kibana/blob/188009f9376d5976b5db37e04c52a2b5bdaf9771/packages/core/application/core-application-browser/src/app_mount.ts#L176-L205). To unset content, call `setHeaderActionMenu` with `undefined`. > **Note** -> The display of the toolbar container is conditional, based on whether there is toolbar content to show. Make sure to pass `undefined` to `setHeaderActionMenu` if there is no application content to show. In classic layout, passing an empty `span` or `div` element suffices to "clear" the toolbar, but in serverless projects it will cause a large empty container to show below the header. +> The display of the toolbar container is conditional, based on whether there is toolbar content to show. Make sure to pass `undefined` to `setHeaderActionMenu` if there is no application content to show. In classic layout, passing an empty `span` or `div` element suffices to "clear" the toolbar, but in the solution navigation it will cause a large empty container to show below the header. ## Global Search -The global search (navigational search) is a search bar that can be opened from the header. It allows users to search for apps, pages, and other resources. Unlike the classic layout, the user must click a magnifying glass icon to reveal the search text input, but everything else in the serverless project layout is the same. -There is no serverless specific API or behavior changes for this: refer to [the global search plugin](https://github.com/elastic/kibana/blob/bd778221dcf8b934f2947d6be3173f8a2796ef74/x-pack/plugins/global_search/README.md) to learn about the API. +The global search (navigational search) is a search bar that can be opened from the header. It allows users to search for apps, pages, and other resources. Unlike the classic layout, the user must click a magnifying glass icon to reveal the search text input, but everything else in the solution navigation layout is the same. +There is no specific API or behavior changes for this: refer to [the global search plugin](https://github.com/elastic/kibana/blob/bd778221dcf8b934f2947d6be3173f8a2796ef74/x-pack/plugins/global_search/README.md) to learn about the API. # Testing > **Note** > For the general guidance on functional testing serverless projects refer to [the doc](https://docs.google.com/document/d/1tiax7xoDYwFXYZjRTgVKkVMjN-SQzBWk4yn1JY6Z5UY/edit#heading=h.t3qzojfbvfj4) -To test project navigation in functional tests use `svlCommonNavigation` page object: +To test solution navigation in functional tests use `solutionNavigation` page object: ```ts -const svlCommonNavigation = getPageObject('svlCommonNavigation'); +const solutionNavigation = getPageObject('solutionNavigation'); ``` The page object exposes helpers for using links in the sidenav and breadcrumbs, as well as using page-level components such as global search, recent items, the Elastic logo icon. There are also utilities to check that no page reload happened during the navigation. Find the full list of helpers in [the source](https://github.com/elastic/kibana/blob/621401ed6a435d4c9beaa03ac1f61ace9716217a/x-pack/test_serverless/functional/page_objects/svl_common_navigation.ts#L44-L206). The most notable are: -- `svlCommonNavigation.expectExists()` checks that serverless project navigation is displayed and not the statefull one -- `svlCommonNavigation.sideNav.expectLinkExists({ deepLinkId: 'discover'})` checks that the link is visible. Can check by deepLinkId, text or navId -- `svlCommonNavigation.sideNav.clickLink({ deepLinkId: 'discover'})` clicks the link. Use to navigate using the sidenav as the users would. Can be used with deepLinkId, text or navId -- `svlCommonNavigation.sideNav.openSection(sectionId)` opens navigation section. -- `svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({deepLinkId: 'discover'})` check that breadcrumbs is in the list using deepLinkId or text +- `solutionNavigation.expectExists()` checks that solution navigation is displayed and not the classic one +- `solutionNavigation.sideNav.expectLinkExists({ deepLinkId: 'discover'})` checks that the link is visible. Can check by deepLinkId, text or navId +- `solutionNavigation.sideNav.clickLink({ deepLinkId: 'discover'})` clicks the link. Use to navigate using the sidenav as the users would. Can be used with deepLinkId, text or navId +- `solutionNavigation.sideNav.openSection(sectionId)` opens navigation section. +- `solutionNavigation.sideNav.openPanel(sectionId)` opens navigation side panel. +- `solutionNavigation.breadcrumbs.expectBreadcrumbExists({deepLinkId: 'discover'})` check that breadcrumbs is in the list using deepLinkId or text -For each project there is a navigation test suite that does a shared navigation smoke check and can be used as an example of using the shared navigation page object. +For each serverless project there is a navigation test suite that does a shared navigation smoke check and can be used as an example of using the shared navigation page object. - x-pack/test_serverless/functional/test_suites/ - search/navigation - observability/navigation - security/navigation -We recommend solution teams to improve these basic navigation smoke tests to cover more project specific functionality. +Similarily for stateful you will find smoe tests with setup examples in the following directories: + +- x-pack/test/functional_solution_sidenav/tests + - observability_sidenav.ts + - search_sidenav.ts + - security_sidenav.ts +