Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
5e4cb43
Add setAppActionMenuBeta
kowalczyk-krzysztof Dec 10, 2025
f00816d
Add to discover
kowalczyk-krzysztof Dec 10, 2025
c42431a
Move TopNavMenuBeta to a package
kowalczyk-krzysztof Dec 11, 2025
35266c5
Make it work with discover and dashboards
kowalczyk-krzysztof Dec 11, 2025
5020df7
Fix for solution view
kowalczyk-krzysztof Dec 11, 2025
3da6f65
Changes from node scripts/lint_ts_projects --fix
kibanamachine Dec 11, 2025
4528a44
Changes from node scripts/generate codeowners
kibanamachine Dec 11, 2025
fbdb35f
Changes from node scripts/regenerate_moon_projects.js --update
kibanamachine Dec 11, 2025
66adbf2
Move Storybook to avoid circular dependencies
kowalczyk-krzysztof Dec 11, 2025
a9b6bcb
Changes from node scripts/lint_packages --fix
kibanamachine Dec 11, 2025
a4b1314
More type fixes
kowalczyk-krzysztof Dec 11, 2025
22c8376
Merge branch 'main' into feat/new-app-menu-api
kowalczyk-krzysztof Dec 11, 2025
6bf36af
Quick check fix
kowalczyk-krzysztof Dec 11, 2025
b4273cf
Changes from node scripts/regenerate_moon_projects.js --update
kibanamachine Dec 12, 2025
f3efd69
Move story
kowalczyk-krzysztof Dec 12, 2025
6d63c80
Changes from node scripts/lint_ts_projects --fix
kibanamachine Dec 12, 2025
ecbd108
Changes from node scripts/regenerate_moon_projects.js --update
kibanamachine Dec 12, 2025
62f4b2a
Merge branch 'main' into feat/new-app-menu-api
kowalczyk-krzysztof Dec 12, 2025
c8e1614
Remove temporary dashboard implementation
kowalczyk-krzysztof Dec 12, 2025
58ea482
Remove discover temporary implementation
kowalczyk-krzysztof Dec 12, 2025
1df7de2
Fix tests
kowalczyk-krzysztof Dec 12, 2025
5164a28
Merge branch 'main' into feat/new-app-menu-api
kowalczyk-krzysztof Dec 12, 2025
f4df82b
Changes from node scripts/lint_ts_projects --fix
kibanamachine Dec 12, 2025
287d538
Changes from node scripts/regenerate_moon_projects.js --update
kibanamachine Dec 12, 2025
4d2b692
Rename to AppMenu
kowalczyk-krzysztof Dec 12, 2025
fa4aae3
Merge branch 'main' into feat/new-app-menu-api
kowalczyk-krzysztof Dec 13, 2025
f90ea52
Rename packages
kowalczyk-krzysztof Dec 16, 2025
495b8c6
Merge branch 'main' into feat/new-app-menu-api
kowalczyk-krzysztof Dec 16, 2025
925996a
Chores
kowalczyk-krzysztof Dec 16, 2025
4b5d7d3
Changes from node scripts/lint_ts_projects --fix
kibanamachine Dec 16, 2025
622e8bb
Changes from node scripts/generate codeowners
kibanamachine Dec 16, 2025
6315c23
Changes from node scripts/regenerate_moon_projects.js --update
kibanamachine Dec 16, 2025
6e154ba
Lazy load app menu
kowalczyk-krzysztof Dec 16, 2025
02e95d8
Use chrome
kowalczyk-krzysztof Dec 16, 2025
04eb356
Changes from node scripts/regenerate_moon_projects.js --update
kibanamachine Dec 16, 2025
d92e50c
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Dec 16, 2025
857b958
Chores fix
kowalczyk-krzysztof Dec 17, 2025
cdd55e4
Add declarative component
kowalczyk-krzysztof Dec 17, 2025
7ea1b0d
Merge branch 'main' into feat/new-app-menu-api
kowalczyk-krzysztof Dec 17, 2025
75cc7c8
Changes from node scripts/regenerate_moon_projects.js --update
kibanamachine Dec 17, 2025
eac3549
Fix observable conditional
kowalczyk-krzysztof Dec 17, 2025
0df8b17
Cleanup
kowalczyk-krzysztof Dec 17, 2025
246286a
CR changes
kowalczyk-krzysztof Dec 19, 2025
28affbc
Merge branch 'main' into feat/new-app-menu-api
kowalczyk-krzysztof Dec 19, 2025
9bab8eb
Update README
kowalczyk-krzysztof Dec 19, 2025
335291f
Fix types
kowalczyk-krzysztof Dec 19, 2025
a0b16dc
Merge branch 'main' into feat/new-app-menu-api
kowalczyk-krzysztof Dec 20, 2025
5bdf15e
Merge branch 'main' into feat/new-app-menu-api
kowalczyk-krzysztof Dec 27, 2025
786d2e1
Merge branch 'main' into feat/new-app-menu-api
kowalczyk-krzysztof Jan 3, 2026
02a4051
Merge branch 'main' into feat/new-app-menu-api
kowalczyk-krzysztof Jan 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ src/core/packages/capabilities/common @elastic/kibana-core
src/core/packages/capabilities/server @elastic/kibana-core
src/core/packages/capabilities/server-internal @elastic/kibana-core
src/core/packages/capabilities/server-mocks @elastic/kibana-core
src/core/packages/chrome/app-menu/core-chrome-app-menu @elastic/appex-sharedux
src/core/packages/chrome/app-menu/core-chrome-app-menu-components @elastic/appex-sharedux
src/core/packages/chrome/browser @elastic/appex-sharedux
src/core/packages/chrome/browser-internal @elastic/appex-sharedux
src/core/packages/chrome/browser-mocks @elastic/appex-sharedux
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@
"@kbn/core-capabilities-common": "link:src/core/packages/capabilities/common",
"@kbn/core-capabilities-server": "link:src/core/packages/capabilities/server",
"@kbn/core-capabilities-server-internal": "link:src/core/packages/capabilities/server-internal",
"@kbn/core-chrome-app-menu": "link:src/core/packages/chrome/app-menu/core-chrome-app-menu",
"@kbn/core-chrome-app-menu-components": "link:src/core/packages/chrome/app-menu/core-chrome-app-menu-components",
"@kbn/core-chrome-browser": "link:src/core/packages/chrome/browser",
"@kbn/core-chrome-browser-internal": "link:src/core/packages/chrome/browser-internal",
"@kbn/core-chrome-layout": "link:src/core/packages/chrome/layout/core-chrome-layout",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# AppMenuComponent

`AppMenuComponent` is the standalone component used in chrome app menu.

## Usage

```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} />;
};
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* 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".
*/

export { AppMenuComponent } from './src';
export { AppMenuItem } from './src';
export { AppMenuActionButton } from './src';
export { AppMenuOverflowButton } from './src';
export { AppMenuPopover } from './src';
export { AppMenuPopoverActionButtons } from './src';

export type {
AppMenuConfig,
AppMenuItemType,
AppMenuSecondaryActionItem,
AppMenuPrimaryActionItem,
AppMenuPopoverItem,
AppMenuSplitButtonProps,
} from './src';

export {
APP_MENU_ITEM_LIMIT,
APP_MENU_NOTIFICATION_INDICATOR_LEFT,
APP_MENU_NOTIFICATION_INDICATOR_TOP,
} from './src';

export {
getDisplayedItemsAllowedAmount,
getShouldOverflow,
isDisabled,
getTooltip,
mapAppMenuItemToPanelItem,
getAppMenuItems,
getPopoverPanels,
getPopoverActionItems,
getIsSelectedColor,
} from './src';
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", 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".
*/

module.exports = {
preset: '@kbn/test',
rootDir: '../../../../../..',
roots: ['<rootDir>/src/core/packages/chrome/app-menu/core-chrome-app-menu-components'],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "shared-browser",
"id": "@kbn/core-chrome-app-menu-components",
"owner": "@elastic/appex-sharedux",
"group": "platform",
"visibility": "shared"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# This file is generated by the @kbn/moon package. Any manual edits will be erased!
# To extend this, write your extensions/overrides to 'moon.extend.yml'
# then regenerate this file with: 'node scripts/regenerate_moon_projects.js --update --filter @kbn/core-chrome-app-menu-components'

$schema: https://moonrepo.dev/schemas/project.json
id: '@kbn/core-chrome-app-menu-components'
type: unknown
owners:
defaultOwner: '@elastic/appex-sharedux'
toolchain:
default: node
language: typescript
project:
name: '@kbn/core-chrome-app-menu-components'
description: Moon project for @kbn/core-chrome-app-menu-components
channel: ''
owner: '@elastic/appex-sharedux'
metadata:
sourceRoot: src/core/packages/chrome/app-menu/core-chrome-app-menu-components
dependsOn:
- '@kbn/split-button'
- '@kbn/i18n'
tags:
- shared-browser
- package
- prod
- group-platform
- shared
- jest-unit-tests
fileGroups:
src:
- '**/*.ts'
- '**/*.tsx'
- '!target/**/*'
tasks:
jest:
args:
- '--config'
- $projectRoot/jest.config.js
inputs:
- '@group(src)'
jestCI:
args:
- '--config'
- $projectRoot/jest.config.js
inputs:
- '@group(src)'
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "@kbn/core-chrome-app-menu-components",
"private": true,
"version": "1.0.0",
"license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0",
"sideEffects": false
}
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", 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".
*/

// eslint-disable-next-line import/no-extraneous-dependencies
import '@testing-library/jest-dom';
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

import React from 'react';
import { render, screen } from '@testing-library/react';
import { TopNavMenuBeta } from './top_nav_menu_beta';
import type { TopNavMenuConfigBeta } from './types';
import { AppMenuComponent } from './app_menu';
import type { AppMenuConfig } from '../types';

// Mock useIsWithinBreakpoints to control responsive behavior
const mockUseIsWithinBreakpoints = jest.fn();
Expand All @@ -22,13 +22,13 @@ jest.mock('@elastic/eui', () => {
};
});

describe('TopNavMenuBeta', () => {
describe('AppMenu', () => {
const defaultItems = [
{ id: 'item1', label: 'Item 1', run: jest.fn(), iconType: 'gear', order: 1 },
{ id: 'item2', label: 'Item 2', run: jest.fn(), iconType: 'search', order: 2 },
];

const defaultConfig: TopNavMenuConfigBeta = {
const defaultConfig: AppMenuConfig = {
items: defaultItems,
};

Expand All @@ -43,31 +43,31 @@ describe('TopNavMenuBeta', () => {

describe('rendering', () => {
it('should return null when config is undefined', () => {
const { container } = render(<TopNavMenuBeta config={undefined} />);
const { container } = render(<AppMenuComponent config={undefined} />);

expect(container).toBeEmptyDOMElement();
});

it('should return null when config has no items', () => {
const { container } = render(<TopNavMenuBeta config={{}} />);
const { container } = render(<AppMenuComponent config={{}} />);

expect(container).toBeEmptyDOMElement();
});

it('should return null when visible is false', () => {
const { container } = render(<TopNavMenuBeta config={defaultConfig} visible={false} />);
const { container } = render(<AppMenuComponent config={defaultConfig} visible={false} />);

expect(container).toBeEmptyDOMElement();
});

it('should render the top nav menu when config has items', () => {
render(<TopNavMenuBeta config={defaultConfig} />);
render(<AppMenuComponent config={defaultConfig} />);

expect(screen.getByTestId('top-nav')).toBeInTheDocument();
});

it('should render menu items at xl breakpoint', () => {
render(<TopNavMenuBeta config={defaultConfig} />);
render(<AppMenuComponent config={defaultConfig} />);

expect(screen.getByText('Item 1')).toBeInTheDocument();
expect(screen.getByText('Item 2')).toBeInTheDocument();
Expand All @@ -76,7 +76,7 @@ describe('TopNavMenuBeta', () => {

describe('action items', () => {
it('should render primary action item', () => {
const configWithPrimary: TopNavMenuConfigBeta = {
const configWithPrimary: AppMenuConfig = {
primaryActionItem: {
id: 'save',
label: 'Save',
Expand All @@ -85,13 +85,13 @@ describe('TopNavMenuBeta', () => {
},
};

render(<TopNavMenuBeta config={configWithPrimary} />);
render(<AppMenuComponent config={configWithPrimary} />);

expect(screen.getByText('Save')).toBeInTheDocument();
});

it('should render secondary action item', () => {
const configWithSecondary: TopNavMenuConfigBeta = {
const configWithSecondary: AppMenuConfig = {
secondaryActionItem: {
id: 'cancel',
label: 'Cancel',
Expand All @@ -100,13 +100,13 @@ describe('TopNavMenuBeta', () => {
},
};

render(<TopNavMenuBeta config={configWithSecondary} />);
render(<AppMenuComponent config={configWithSecondary} />);

expect(screen.getByText('Cancel')).toBeInTheDocument();
});

it('should render both primary and secondary action items', () => {
const configWithBoth: TopNavMenuConfigBeta = {
const configWithBoth: AppMenuConfig = {
primaryActionItem: {
id: 'save',
label: 'Save',
Expand All @@ -121,7 +121,7 @@ describe('TopNavMenuBeta', () => {
},
};

render(<TopNavMenuBeta config={configWithBoth} />);
render(<AppMenuComponent config={configWithBoth} />);

expect(screen.getByText('Save')).toBeInTheDocument();
expect(screen.getByText('Cancel')).toBeInTheDocument();
Expand All @@ -135,15 +135,15 @@ describe('TopNavMenuBeta', () => {
return false;
});

render(<TopNavMenuBeta config={defaultConfig} />);
render(<AppMenuComponent config={defaultConfig} />);

expect(screen.getByTestId('top-nav-menu-overflow-button')).toBeInTheDocument();
});

it('should render overflow button with all items at small breakpoint', () => {
mockUseIsWithinBreakpoints.mockReturnValue(false);

render(<TopNavMenuBeta config={defaultConfig} />);
render(<AppMenuComponent config={defaultConfig} />);

expect(screen.getByTestId('top-nav-menu-overflow-button')).toBeInTheDocument();
});
Expand All @@ -154,7 +154,7 @@ describe('TopNavMenuBeta', () => {
return false;
});

render(<TopNavMenuBeta config={defaultConfig} />);
render(<AppMenuComponent config={defaultConfig} />);

expect(screen.getByText('Item 1')).toBeInTheDocument();
expect(screen.getByText('Item 2')).toBeInTheDocument();
Expand Down
Loading