docs(ui): update Header docs with tags, description, and metadata props

Add new props to the Header API reference and examples on ui.backstage.io.
Also adds deprecated badge support to the shared PropsTable component so
the breadcrumbs prop is visually marked as deprecated.

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
Made-with: Cursor
This commit is contained in:
Charles de Dreuille
2026-04-19 09:54:19 +02:00
parent c96e2b3445
commit 33ea7fb301
8 changed files with 166 additions and 9 deletions
@@ -29,10 +29,25 @@ const breadcrumbs = [
},
];
const tags = [
{ label: 'TypeScript' },
{ label: 'Platform', href: '/platform' },
{ label: 'Gold' },
];
const metadata = [
{ label: 'Owner', value: 'platform-team' },
{ label: 'Type', value: 'website' },
{ label: 'Tier', value: 'gold' },
];
export const WithEverything = () => (
<MemoryRouter initialEntries={['/overview']}>
<Header
title="Page Title"
tags={tags}
description="A short description of this page. Supports [inline links](https://backstage.io) and **bold text**."
metadata={metadata}
tabs={tabs.slice(0, 2)}
breadcrumbs={breadcrumbs.slice(0, 2)}
customActions={
@@ -45,6 +60,27 @@ export const WithEverything = () => (
</MemoryRouter>
);
export const WithTags = () => (
<MemoryRouter>
<Header title="Page Title" tags={tags} />
</MemoryRouter>
);
export const WithDescription = () => (
<MemoryRouter>
<Header
title="Page Title"
description="A short description of this page. Supports [inline links](https://backstage.io) and **bold text**."
/>
</MemoryRouter>
);
export const WithMetadata = () => (
<MemoryRouter>
<Header title="Page Title" metadata={metadata} />
</MemoryRouter>
);
export const WithLongBreadcrumbs = () => (
<MemoryRouter>
<Header title="Page Title" breadcrumbs={breadcrumbs.slice(0, 2)} />
+28 -4
View File
@@ -5,6 +5,9 @@ import {
WithEverything,
WithLongBreadcrumbs,
WithTabs,
WithTags,
WithDescription,
WithMetadata,
WithCustomActions,
WithMenu,
} from './components';
@@ -13,6 +16,9 @@ import {
usage,
defaultSnippet,
withTabs,
withTags,
withDescription,
withMetadata,
withBreadcrumbs,
withCustomActions,
withMenu,
@@ -24,7 +30,7 @@ import { ChangelogComponent } from '@/components/ChangelogComponent';
<PageTitle
title="Header"
description="A secondary header with title, breadcrumbs, tabs, and actions."
description="A secondary header with title, tags, description, metadata, tabs, and actions."
/>
<Snippet py={4} preview={<WithEverything />} code={defaultSnippet} />
@@ -39,11 +45,23 @@ import { ChangelogComponent } from '@/components/ChangelogComponent';
## Examples
### Breadcrumbs
### Tags
Labels are truncated at 240px.
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.
<Snippet open preview={<WithLongBreadcrumbs />} code={withBreadcrumbs} />
<Snippet open preview={<WithTags />} code={withTags} />
### Description
The description accepts a markdown string. Only inline elements are supported — links, bold, and italic.
<Snippet open preview={<WithDescription />} code={withDescription} />
### Metadata
Key-value pairs displayed below the description.
<Snippet open preview={<WithMetadata />} code={withMetadata} />
### Tabs
@@ -61,6 +79,12 @@ Use `customActions` to add a dropdown menu.
<Snippet open preview={<WithMenu />} code={withMenu} />
### Breadcrumbs (deprecated)
The `breadcrumbs` prop is deprecated and will be removed in a future release. Labels are truncated at 240px.
<Snippet open preview={<WithLongBreadcrumbs />} code={withBreadcrumbs} />
<Theming definition={HeaderDefinition} />
<ChangelogComponent component={['header', 'header-page']} />
@@ -5,6 +5,50 @@ export const headerPagePropDefs: Record<string, PropDef> = {
type: 'string',
description: 'Page heading displayed in the header.',
},
tags: {
type: 'complex',
description:
'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.',
complexType: {
name: 'HeaderTag[]',
properties: {
label: {
type: 'string',
required: true,
description: 'Display text for the tag.',
},
href: {
type: 'string',
required: false,
description: 'URL to navigate to when the tag is clicked.',
},
},
},
},
description: {
type: 'string',
description:
'Markdown string rendered below the title. Only inline elements are supported: links, bold, and italic. Block-level markdown such as headings or lists is not rendered.',
},
metadata: {
type: 'complex',
description: 'Key-value pairs displayed below the description.',
complexType: {
name: 'HeaderMetadataItem[]',
properties: {
label: {
type: 'string',
required: true,
description: 'The key label, displayed in bold.',
},
value: {
type: 'ReactNode',
required: true,
description: 'The value to display alongside the label.',
},
},
},
},
customActions: {
type: 'enum',
values: ['ReactNode'],
@@ -49,6 +93,7 @@ export const headerPagePropDefs: Record<string, PropDef> = {
},
breadcrumbs: {
type: 'complex',
deprecated: true,
description: 'Breadcrumb trail displayed above the title.',
complexType: {
name: 'HeaderBreadcrumb[]',
+33 -3
View File
@@ -4,9 +4,16 @@ export const usage = `import { Header } from '@backstage/ui';
export const defaultSnippet = `<Header
title="Page Title"
breadcrumbs={[
{ label: 'Home', href: '/' },
{ label: 'Dashboard', href: '/dashboard' },
tags={[
{ label: 'TypeScript' },
{ label: 'Platform', href: '/platform' },
{ label: 'Gold' },
]}
description="A short description. Supports [inline links](https://backstage.io) and **bold text**."
metadata={[
{ label: 'Owner', value: 'platform-team' },
{ label: 'Type', value: 'website' },
{ label: 'Tier', value: 'gold' },
]}
tabs={[
{ id: 'overview', label: 'Overview', href: '/overview' },
@@ -54,3 +61,26 @@ export const withMenu = `<Header
</MenuTrigger>
}
/>`;
export const withTags = `<Header
title="Page Title"
tags={[
{ label: 'TypeScript' },
{ label: 'Platform', href: '/platform' },
{ label: 'Gold' },
]}
/>`;
export const withDescription = `<Header
title="Page Title"
description="A short description. Supports [inline links](https://backstage.io) and **bold text**."
/>`;
export const withMetadata = `<Header
title="Page Title"
metadata={[
{ label: 'Owner', value: 'platform-team' },
{ label: 'Type', value: 'website' },
{ label: 'Tier', value: 'gold' },
]}
/>`;
+7 -1
View File
@@ -4,12 +4,18 @@ import styles from './styles.module.css';
export const Chip = ({
children,
head = false,
deprecated = false,
}: {
children: ReactNode;
head?: boolean;
deprecated?: boolean;
}) => {
return (
<span className={`${styles.chip} ${head ? styles.head : ''}`}>
<span
className={`${styles.chip} ${head ? styles.head : ''} ${
deprecated ? styles.deprecated : ''
}`}
>
{children}
</span>
);
@@ -14,6 +14,11 @@
color: #2563eb;
}
.deprecated {
background-color: #fff4e5;
color: #b45309;
}
[data-theme-mode='dark'] .chip {
background-color: #2c2c2c;
color: #fff;
@@ -22,3 +27,8 @@
[data-theme-mode='dark'] .chip.head {
background-color: #33405b;
}
[data-theme-mode='dark'] .chip.deprecated {
background-color: #3d2a10;
color: #fbbf24;
}
@@ -52,7 +52,12 @@ export const PropsTable = <T extends Record<string, PropData>>({
switch (column) {
case 'prop':
return <Chip head>{propName}</Chip>;
return (
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.375rem' }}>
<Chip head>{propName}</Chip>
{propData.deprecated && <Chip deprecated>deprecated</Chip>}
</div>
);
case 'type':
return (
+1
View File
@@ -44,6 +44,7 @@ export type PropDef = {
required?: boolean;
responsive?: boolean;
description?: ReactNode;
deprecated?: boolean;
};
export { breakpoints };