app: migrate to new navItems API

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2026-02-16 10:36:11 +01:00
parent cc3c035267
commit 98fe69ae6a
2 changed files with 64 additions and 46 deletions
+46 -29
View File
@@ -29,7 +29,7 @@ import SearchIcon from '@material-ui/icons/Search';
import MenuIcon from '@material-ui/icons/Menu';
import BuildIcon from '@material-ui/icons/Build';
import { createFrontendModule } from '@backstage/frontend-plugin-api';
import { NavContentBlueprint } from '@backstage/plugin-app-react';
import { NavContentBlueprint, NavItem } from '@backstage/plugin-app-react';
import { SidebarSearchModal } from '@backstage/plugin-search';
import { NotificationsSidebarItem } from '@backstage/plugin-notifications';
import {
@@ -98,39 +98,56 @@ const SidebarLogo = () => {
);
};
function item(props?: NavItem) {
if (!props) {
return null;
}
return (
<SidebarItem icon={() => props.icon} to={props.href} text={props.title} />
);
}
export const appModuleNav = createFrontendModule({
pluginId: 'app',
extensions: [
NavContentBlueprint.make({
params: {
component: ({ items }) => (
<Sidebar>
<SidebarLogo />
<SidebarGroup label="Search" icon={<SearchIcon />} to="/search">
<SidebarSearchModal />
</SidebarGroup>
<SidebarDivider />
<SidebarGroup label="Menu" icon={<MenuIcon />}>
<SidebarScrollWrapper>
{items.map((item, index) => (
<SidebarItem {...item} key={index} />
))}
</SidebarScrollWrapper>
</SidebarGroup>
<SidebarDivider />
<SidebarSpace />
<SidebarDivider />
<SidebarGroup
label="Settings"
icon={<UserSettingsSignInAvatar />}
to="/settings"
>
<NotificationsSidebarItem />
<SidebarItem icon={BuildIcon} to="devtools" text="DevTools" />
<Settings />
</SidebarGroup>
</Sidebar>
),
component: ({ navItems }) => {
navItems.take('page:home'); // Skip home
return (
<Sidebar>
<SidebarLogo />
<SidebarGroup label="Search" icon={<SearchIcon />} to="/search">
<SidebarSearchModal />
</SidebarGroup>
<SidebarDivider />
<SidebarGroup label="Menu" icon={<MenuIcon />}>
{item(navItems.take('page:home'))}
{item(navItems.take('page:catalog'))}
{item(navItems.take('page:scaffolder'))}
<SidebarDivider />
<SidebarScrollWrapper>
{navItems
.rest()
.sort((a, b) => a.title.localeCompare(b.title))
.map(item)}
</SidebarScrollWrapper>
</SidebarGroup>
<SidebarDivider />
<SidebarSpace />
<SidebarDivider />
<SidebarGroup
label="Settings"
icon={<UserSettingsSignInAvatar />}
to="/settings"
>
<NotificationsSidebarItem />
<SidebarItem icon={BuildIcon} to="devtools" text="DevTools" />
<Settings />
</SidebarGroup>
</Sidebar>
);
},
},
}),
],
@@ -1,4 +1,5 @@
import {
Sidebar,
SidebarDivider,
SidebarGroup,
SidebarItem,
@@ -6,20 +7,26 @@ import {
SidebarSpace,
} from '@backstage/core-components';
import { compatWrapper } from '@backstage/core-compat-api';
import { Sidebar } from '@backstage/core-components';
import { NavContentBlueprint } from '@backstage/plugin-app-react';
import { NavContentBlueprint, NavItem } from '@backstage/plugin-app-react';
import { SidebarLogo } from './SidebarLogo';
import CreateComponentIcon from '@material-ui/icons/AddCircleOutline';
import HomeIcon from '@material-ui/icons/Home';
import MenuIcon from '@material-ui/icons/Menu';
import SearchIcon from '@material-ui/icons/Search';
import { SidebarSearchModal } from '@backstage/plugin-search';
import { UserSettingsSignInAvatar, Settings as SidebarSettings } from '@backstage/plugin-user-settings';
import { NotificationsSidebarItem } from '@backstage/plugin-notifications';
function item(props?: NavItem) {
if (!props) {
return null;
}
return (
<SidebarItem icon={() => props.icon} to={props.href} text={props.title} />
);
}
export const SidebarContent = NavContentBlueprint.make({
params: {
component: ({ items }) =>
component: ({ navItems }) =>
compatWrapper(
<Sidebar>
<SidebarLogo />
@@ -28,20 +35,14 @@ export const SidebarContent = NavContentBlueprint.make({
</SidebarGroup>
<SidebarDivider />
<SidebarGroup label="Menu" icon={<MenuIcon />}>
{/* Global nav, not org-specific */}
<SidebarItem icon={HomeIcon} to="catalog" text="Home" />
<SidebarItem
icon={CreateComponentIcon}
to="create"
text="Create..."
/>
{/* End global nav */}
{item(navItems.take('page:catalog'))}
{item(navItems.take('page:scaffolder'))}
<SidebarDivider />
<SidebarScrollWrapper>
{/* Items in this group will be scrollable if they run out of space */}
{items.map((item, index) => (
<SidebarItem {...item} key={index} />
))}
{navItems
.rest()
.sort((a, b) => a.title.localeCompare(b.title))
.map(item)}
</SidebarScrollWrapper>
</SidebarGroup>
<SidebarSpace />