A secondary header with title, tags, description, metadata, tabs, and actions.
import { Header } from '@backstage/ui';
<Header title="Page Title" />| Prop | Type | Default | Description |
|---|---|---|---|
title | string | - | Page heading displayed in the header. |
tags | - | Items displayed above the title. Each tag renders as a link when href is provided, or as plain text otherwise. Tags are separated by a small circle divider. | |
description | string | - | Markdown string rendered below the title. Only inline links are supported. Bold, italic, and block-level markdown are not rendered. |
metadata | - | Key-value pairs displayed below the description. | |
customActions | ReactNode | - | Custom elements rendered in the actions area. |
tabs | - | Navigation items displayed below the title. | |
activeTabId | stringnull | - | ID of the currently active tab. Omit to auto-detect from the current route. Set to null for no active tab. |
breadcrumbsdeprecated | - | Breadcrumb trail displayed above the title. | |
className | string | - | Additional CSS class name for custom styling. |
Tags are rendered above the title. Each tag with an href renders as a link; tags without href render as plain text. Tags are separated by a small circle divider.
<Header
title="Page Title"
tags={[
{ label: 'TypeScript' },
{ label: 'Platform', href: '/platform' },
{ label: 'Gold' },
]}
/>The description accepts a markdown string with support for inline links. Bold, italic, and block-level markdown are not rendered.
<Header
title="Page Title"
description="A short description. Supports [inline links](https://backstage.io)."
/>Key-value pairs displayed below the description.
<Header
title="Page Title"
metadata={[
{ label: 'Owner', value: 'platform-team' },
{ label: 'Type', value: 'website' },
]}
/>Use HeaderMetadataUsers as the metadata value to display users as avatars. A single user shows the avatar with their name beside it. Multiple users show a row of avatars — hover to reveal each name via tooltip. When a user has an href, the avatar and name become links.
import { Header, HeaderMetadataUsers } from '@backstage/ui';
<Header
title="Page Title"
metadata={[
{ label: 'Type', value: 'website' },
{
label: 'Owner',
value: <HeaderMetadataUsers users={[{ name: 'Giles Peyton-Nicoll', src: '...', href: '/users/giles' }]} />,
},
{
label: 'Contributors',
value: (
<HeaderMetadataUsers
users={[
{ name: 'Alice Johnson', src: '...', href: '/users/alice' },
{ name: 'Bob Smith', src: '...', href: '/users/bob' },
{ name: 'Carol Williams', src: '...', href: '/users/carol' },
]}
/>
),
},
]}
/>| Prop | Type | Default | Description |
|---|---|---|---|
users | - | List of users to display. A single user shows the avatar with their name beside it. Multiple users show a row of avatars with names revealed on hover via tooltip. |
Use HeaderMetadataStatus as the metadata value to display a status indicator. The dot colour is driven by the color prop which maps to BUI status tokens. Pass an href to make the label a link.
import { Header, HeaderMetadataStatus } from '@backstage/ui';
<Header
title="Page Title"
metadata={[
{
label: 'Status',
value: <HeaderMetadataStatus label="Passing" color="success" />,
},
{
label: 'Build',
value: <HeaderMetadataStatus label="Failed" color="danger" href="/builds/123" />,
},
{
label: 'Coverage',
value: <HeaderMetadataStatus label="Warning" color="warning" />,
},
]}
/>Tabs auto-detect the active tab from the current route when activeTabId is omitted. Pass an explicit activeTabId to override, or null for no active tab.
<Header
title="Page Title"
tabs={[
{ id: 'overview', label: 'Overview', href: '/overview' },
{ id: 'checks', label: 'Checks', href: '/checks' },
{ id: 'tracks', label: 'Tracks', href: '/tracks' },
]}
/>Use customActions to add a dropdown menu.
<Header
title="Page Title"
customActions={
<MenuTrigger>
<ButtonIcon variant="tertiary" icon={<RiMore2Line />} />
<Menu placement="bottom end">
<MenuItem href="/settings">Settings</MenuItem>
<MenuItem onAction={() => {}}>Logout</MenuItem>
</Menu>
</MenuTrigger>
}
/>Our theming system is based on a mix between CSS classes, CSS variables and data attributes. If you want to customise this component, you can use one of these class names below.
bui-HeaderTopbui-HeaderStickySentinelbui-HeaderContentbui-HeaderBottombui-HeaderBreadcrumbsbui-HeaderBreadcrumbsSmallbui-HeaderBreadcrumbLinkbui-HeaderBreadcrumbLinkSmallbui-HeaderBreadcrumbSeparatorbui-HeaderTitleStackbui-HeaderTitlebui-HeaderTitleSmallbui-HeaderTabsWrapperbui-HeaderControlsbui-HeaderTagsbui-HeaderTagbui-HeaderDescriptionbui-HeaderMetaRowbui-HeaderMetaItemHeader Breaking The Header component's tabs prop now uses HeaderNavTabItem[] instead of HeaderTab[]. Tabs render as a <nav> element with links and optional dropdown menus instead of role="tablist". A new activeTabId prop controls which tab is highlighted. #33527
Migration Guide:
- import { Header, type HeaderTab } from '@backstage/ui';
+ import { Header, type HeaderNavTabItem } from '@backstage/ui';
// Tabs no longer support matchStrategy — active state is controlled via activeTabId
- const tabs: HeaderTab[] = [
- { id: 'overview', label: 'Overview', href: '/overview', matchStrategy: 'prefix' },
+ const tabs: HeaderNavTabItem[] = [
+ { id: 'overview', label: 'Overview', href: '/overview' },
];
- <Header title="My Page" tabs={tabs} />
+ <Header title="My Page" tabs={tabs} activeTabId="overview" />
Header Breaking Tab href values in the Header component are now resolved through the router context instead of being passed raw to the <a> tag. This means relative href values (e.g. sub3, ./sub4, ../catalog) are now resolved against the current route, and absolute href values may be affected by the router's basename configuration. #33783
Migration Guide:
Tab navigation should work the same for absolute href values in most setups. If you use relative href values in tabs, verify they resolve as expected. If your app configures a router basename, check that absolute tab href values still navigate correctly.
Header Added automatic active tab detection to the Header component. When activeTabId is omitted, the active tab is now auto-detected from the current route using matchRoutes. Pass an explicit activeTabId to override, or null for no active tab. #33783
Header Fixed HeaderNav hover indicator covering tab text when theme uses opaque background colors. Also fixed an incorrect CSS variable reference (--bui-font-family → --bui-font-regular). #33696
Header Breaking Renamed internal CSS classes to match the Header component name.
Migration: If you are targeting these classes directly in your styles, update the following:
bui-HeaderPage → bui-Headerbui-HeaderPageContent → bui-HeaderContentbui-HeaderPageBreadcrumbs → bui-HeaderBreadcrumbsbui-HeaderPageTabsWrapper → bui-HeaderTabsWrapperbui-HeaderPageControls → bui-HeaderControls #33354HeaderPage Migrated all components from useStyles to useDefinition hook. Exported OwnProps types for each component, enabling better type composition for consumers. #33050
Header Fixed incorrect bottom spacing caused by Container using padding-bottom for its default bottom spacing. Changed to margin-bottom and prevented it from applying when Container is used as the Header root element. #33354
Header Breaking Changed className prop behavior to augment default styles instead of being ignored or overriding them.
If you were passing custom className values to any of these components that relied on the previous behavior, you may need to adjust your styles to account for the default classes now being applied alongside your custom classes. #31496