diff --git a/packages/frontend-app-api/src/extensions/CoreNav.tsx b/packages/frontend-app-api/src/extensions/CoreNav.tsx index 50aa8fd408..9c829a348f 100644 --- a/packages/frontend-app-api/src/extensions/CoreNav.tsx +++ b/packages/frontend-app-api/src/extensions/CoreNav.tsx @@ -30,6 +30,7 @@ import { sidebarConfig, SidebarDivider, SidebarItem, + SidebarGroup, } from '@backstage/core-components'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import LogoIcon from '../../../app/src/components/Root/LogoIcon'; @@ -64,6 +65,18 @@ const SidebarLogo = () => { ); }; +const SidebarNavItem = (props: NavTarget) => { + const { icon: Icon, title, group, routeRef } = props; + const to = useRouteRef(routeRef)(); + return group ? ( + } label={title}> + {group} + + ) : ( + + ); +}; + export const CoreNav = createExtension({ id: 'core.nav', at: 'core.layout/nav', @@ -76,11 +89,6 @@ export const CoreNav = createExtension({ element: coreExtensionData.reactElement, }, factory({ bind, inputs }) { - const SidebarNavItem = (props: NavTarget) => { - const { icon, title, routeRef } = props; - const to = useRouteRef(routeRef)(); - return ; - }; bind({ element: ( diff --git a/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx b/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx index 8c55531866..723c9e9956 100644 --- a/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx +++ b/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx @@ -16,19 +16,33 @@ import { IconComponent, RouteRef } from '@backstage/core-plugin-api'; import { createSchemaFromZod } from '../schema/createSchemaFromZod'; -import { coreExtensionData, createExtension } from '../wiring'; +import { + AnyExtensionInputMap, + ExtensionInputValues, + coreExtensionData, + createExtension, +} from '../wiring'; +import { Expand } from '../wiring/createExtension'; +import { Suspense, lazy } from 'react'; +import React from 'react'; /** * Helper for creating extensions for a nav item. * @public */ -export function createNavItemExtension(options: { +export function createNavItemExtension< + TInputs extends AnyExtensionInputMap, +>(options: { id: string; routeRef: RouteRef; title: string; icon: IconComponent; + inputs?: TInputs; + group?: (options: { + inputs: Expand>; + }) => Promise; }) { - const { id, routeRef, title, icon } = options; + const { id, routeRef, title, icon, group } = options; return createExtension({ id, at: 'core.nav/items', @@ -37,15 +51,28 @@ export function createNavItemExtension(options: { title: z.string().default(title), }), ), + inputs: options.inputs, output: { navTarget: coreExtensionData.navTarget, }, - factory: ({ bind, config }) => { + factory: ({ bind, config, inputs }) => { + const Group = group + ? (lazy(() => + group({ inputs }).then(element => ({ + default: () => element, + })), + ) as unknown as () => JSX.Element) + : undefined; bind({ navTarget: { title: config.title, icon, routeRef, + group: Group ? ( + + + + ) : undefined, }, }); }, diff --git a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts index 079d5bcb18..d03513677d 100644 --- a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts +++ b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts @@ -27,6 +27,7 @@ export type NavTarget = { title: string; icon: IconComponent; routeRef: RouteRef<{}>; + group?: JSX.Element; }; /** @public */