Skip to content

[App Menu Standardization] New way to register app menu#245938

Merged
kowalczyk-krzysztof merged 50 commits intoelastic:mainfrom
kowalczyk-krzysztof:feat/new-app-menu-api
Jan 7, 2026
Merged

[App Menu Standardization] New way to register app menu#245938
kowalczyk-krzysztof merged 50 commits intoelastic:mainfrom
kowalczyk-krzysztof:feat/new-app-menu-api

Conversation

@kowalczyk-krzysztof
Copy link
Copy Markdown
Member

@kowalczyk-krzysztof kowalczyk-krzysztof commented Dec 11, 2025

Summary

This PR adds a new way to add app menu to applications.

Usage:

  • Declarative (preferred):
import React, { useEffect } from 'react';
import { AppMenu } from '@kbn/core-chrome-app-menu';
import type { AppMenuConfig } from '@kbn/core-chrome-app-menu-components';
import type { CoreStart } from '@kbn/core/public';

interface Props {
  config: AppMenuConfig;
  core: CoreStart
}

const Example = ({ config, core }: Props) => {
  const { chrome } = core;

  return <AppMenu config={config} setAppMenu={chrome.setAppMenu} />;
};
  • Imperative:
import React, { useEffect } from 'react';
import type { AppMenuConfig } from '@kbn/core-chrome-app-menu-components';
import type { CoreStart } from '@kbn/core/public';

interface Props {
  config: AppMenuConfig;
  core: CoreStart
}

const Example = ({ config, core }: Props) => {
  const { chrome } = core;

  useEffect(() => {
    chrome.setAppMenu(config);
  }, [chrome.setAppMenu, config]);

  return <div>Hello world!</div>;
};
  • As a standalone component:
import React, { useEffect } from 'react';
import { AppMenuComponent, type AppMenuConfig } from '@kbn/core-chrome-app-menu-components';

interface Props {
  config: AppMenuConfig;
}

const Example = ({ config }: Props) => {
  return <AppMenuComponent config={config} />;
};

Closes: https://github.com/elastic/kibana-team/issues/2408

@kowalczyk-krzysztof kowalczyk-krzysztof self-assigned this Dec 11, 2025
@kowalczyk-krzysztof kowalczyk-krzysztof force-pushed the feat/new-app-menu-api branch 2 times, most recently from 52a5c62 to b955131 Compare December 11, 2025 21:37
Copy link
Copy Markdown
Contributor

@davismcphee davismcphee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Discover changes are looking good! Left a couple of comments.

@kowalczyk-krzysztof
Copy link
Copy Markdown
Member Author

kowalczyk-krzysztof commented Dec 12, 2025

The Discover changes are looking good! Left a couple of comments.

Thanks for checking this out @davismcphee

I will probably open separate PRs for both discover and dashboards later as this one includes those changes, mostly to see if this approach would work.

EDIT: Moved to: #246156

@kowalczyk-krzysztof kowalczyk-krzysztof added Team:SharedUX Platform AppEx-SharedUX (formerly Global Experience) t// release_note:skip Skip the PR/issue when compiling release notes backport:skip This PR does not require backporting labels Dec 17, 2025
};

const discoverConfig: TopNavMenuConfigBeta = {
const discoverConfig: AppMenuConfig = {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved Storybook directly to SharedUX Stories as in current state, integrating the component with unified tabs would cause circular dependencies if the Storybook file was kept within the app menu package. Once the integration with discover tabs is complete, it will be safe to delete the discover story and move the file back to app menu package.

@kowalczyk-krzysztof kowalczyk-krzysztof marked this pull request as ready for review December 17, 2025 16:36
@kowalczyk-krzysztof kowalczyk-krzysztof requested a review from a team as a code owner December 17, 2025 16:36
@elasticmachine
Copy link
Copy Markdown
Contributor

Pinging @elastic/appex-sharedux (Team:SharedUX)

Comment thread src/core/packages/chrome/browser-internal/src/chrome_service.tsx
Comment thread src/core/packages/chrome/browser-internal/src/ui/project/app_menu.tsx Outdated
Comment thread src/core/packages/chrome/browser-internal/src/ui/header/header_app_menu.tsx Outdated
Comment thread src/core/packages/chrome/browser-internal/src/ui/header/header_app_menu.tsx Outdated
Comment thread src/core/packages/chrome/browser-internal/src/ui/header/header.tsx Outdated
@kowalczyk-krzysztof kowalczyk-krzysztof enabled auto-merge (squash) December 19, 2025 18:46
@elasticmachine
Copy link
Copy Markdown
Contributor

💛 Build succeeded, but was flaky

Failed CI Steps

Test Failures

  • [job] [logs] Scout: [ observability / observability_onboarding ] plugin / Navigates correctly within Kubernetes Host flow using the keyboard only
  • [job] [logs] Scout: [ observability / observability_onboarding ] plugin / stateful - Onboarding UI Validation - Navigates correctly within Kubernetes Host flow using the keyboard only

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
core 523 539 +16
navigation 25 17 -8
total +8

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
@kbn/core-chrome-app-menu - 3 +3
@kbn/core-chrome-app-menu-components - 42 +42
@kbn/core-chrome-browser 87 88 +1
total +46

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
core 115.1KB 126.4KB +11.3KB
navigation 8.9KB 0.0B -8.9KB
total +2.4KB

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
@kbn/core 919 928 +9
navigation 6 5 -1
total +8

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
core 497.9KB 498.9KB +1.1KB
navigation 13.9KB 11.0KB -2.9KB
total -1.8KB
Unknown metric groups

API count

id before after diff
@kbn/core-chrome-app-menu - 6 +6
@kbn/core-chrome-app-menu-components - 57 +57
@kbn/core-chrome-browser 191 194 +3
total +66

async chunk count

id before after diff
core 3 4 +1
navigation 1 0 -1
total -0

ESLint disabled line counts

id before after diff
@kbn/core-chrome-app-menu-components - 1 +1

Total ESLint disabled count

id before after diff
@kbn/core-chrome-app-menu-components - 1 +1

History

cc @kowalczyk-krzysztof

@kowalczyk-krzysztof kowalczyk-krzysztof merged commit 00023f5 into elastic:main Jan 7, 2026
16 checks passed
@kowalczyk-krzysztof kowalczyk-krzysztof deleted the feat/new-app-menu-api branch January 9, 2026 11:17
devamanv pushed a commit to devamanv/kibana that referenced this pull request Jan 12, 2026
## Summary

This PR adds a new way to add app menu to applications.

### Usage:

- Declarative (preferred):
```tsx
import React, { useEffect } from 'react';
import { AppMenu } from '@kbn/core-chrome-app-menu';
import type { AppMenuConfig } from '@kbn/core-chrome-app-menu-components';
import { useKibana } from '@kbn/kibana-react-plugin/public';

interface Props {
  config: AppMenuConfig;
}

const Example = ({ config }: Props) => {
  const { chrome } = useKibana().services;

  return <AppMenu config={config} setAppMenu={chrome.setAppMenu} />;
};
```
- Imperative:
```tsx
import React, { useEffect } from 'react';
import type { AppMenuConfig } from '@kbn/core-chrome-app-menu-components';
import { useKibana } from '@kbn/kibana-react-plugin/public';

interface Props {
  config: AppMenuConfig;
}

const Example = ({ config }: Props) => {
  const { chrome } = useKibana().services;

  useEffect(() => {
    chrome.setAppMenu(config);
  }, [chrome.setAppMenu, config]);

  return <div>Hello world!</div>;
};
```

- As a standalone component:
```tsx
import React, { useEffect } from 'react';
import { AppMenuComponent, type AppMenuConfig } from '@kbn/core-chrome-app-menu-components';

interface Props {
  config: AppMenuConfig;
}

const Example = ({ config }: Props) => {
  return <AppMenuComponent config={config} />;
};
```

Closes: elastic/kibana-team#2408

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:skip This PR does not require backporting release_note:skip Skip the PR/issue when compiling release notes Team:SharedUX Platform AppEx-SharedUX (formerly Global Experience) t// v9.4.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants