diff --git a/.changeset/rename-header-to-plugin-header.md b/.changeset/rename-header-to-plugin-header.md
new file mode 100644
index 0000000000..5e4bfcbb02
--- /dev/null
+++ b/.changeset/rename-header-to-plugin-header.md
@@ -0,0 +1,27 @@
+---
+'@backstage/ui': minor
+---
+
+**BREAKING**: Renamed the `Header` component to `PluginHeader` for clarity.
+
+The following exports have been renamed:
+
+- `Header` → `PluginHeader`
+- `HeaderProps` → `PluginHeaderProps`
+- `HeaderDefinition` → `PluginHeaderDefinition`
+
+The `HeaderTab` type is unchanged as it is shared with `HeaderPage`.
+
+CSS class names have been updated from `bui-Header*` to `bui-PluginHeader*`.
+
+**Migration:**
+
+```diff
+-import { Header, HeaderDefinition } from '@backstage/ui';
++import { PluginHeader, PluginHeaderDefinition } from '@backstage/ui';
+
+-
++
+```
+
+**Affected components:** plugin-header
diff --git a/docs-ui/src/app/components/header/components.tsx b/docs-ui/src/app/components/plugin-header/components.tsx
similarity index 90%
rename from docs-ui/src/app/components/header/components.tsx
rename to docs-ui/src/app/components/plugin-header/components.tsx
index 80a4d1dd6e..b3d831e718 100644
--- a/docs-ui/src/app/components/header/components.tsx
+++ b/docs-ui/src/app/components/plugin-header/components.tsx
@@ -1,6 +1,6 @@
'use client';
-import { Header } from '../../../../../packages/ui/src/components/Header/Header';
+import { PluginHeader } from '../../../../../packages/ui/src/components/PluginHeader/PluginHeader';
import { HeaderPage } from '../../../../../packages/ui/src/components/HeaderPage/HeaderPage';
import { ButtonIcon } from '../../../../../packages/ui/src/components/ButtonIcon/ButtonIcon';
import { Button } from '../../../../../packages/ui/src/components/Button/Button';
@@ -27,7 +27,7 @@ const tabs2 = [
export const WithAllOptionsAndTabs = () => (
- (
export const WithAllOptions = () => (
- (
export const WithHeaderPage = () => (
<>
-
+
@@ -36,22 +36,22 @@ import { ChangelogComponent } from '@/components/ChangelogComponent';
## Examples
-### Simple header
+### Simple plugin header
} code={simple} open />
-### Header with tabs
+### Plugin header with tabs
Tabs use React Router and highlight automatically based on the current route.
} code={withTabs} open />
-### Header with HeaderPage
+### Plugin header with HeaderPage
Combine with [HeaderPage](/components/header-page) for multi-level navigation.
} code={withHeaderPage} open />
-
+
-
+
diff --git a/docs-ui/src/app/components/header/props-definition.tsx b/docs-ui/src/app/components/plugin-header/props-definition.tsx
similarity index 100%
rename from docs-ui/src/app/components/header/props-definition.tsx
rename to docs-ui/src/app/components/plugin-header/props-definition.tsx
diff --git a/docs-ui/src/app/components/header/snippets.ts b/docs-ui/src/app/components/plugin-header/snippets.ts
similarity index 84%
rename from docs-ui/src/app/components/header/snippets.ts
rename to docs-ui/src/app/components/plugin-header/snippets.ts
index b83f1b68b2..4e9518af73 100644
--- a/docs-ui/src/app/components/header/snippets.ts
+++ b/docs-ui/src/app/components/plugin-header/snippets.ts
@@ -1,8 +1,8 @@
-export const usage = `import { Header } from '@backstage/ui';
+export const usage = `import { PluginHeader } from '@backstage/ui';
-`;
+`;
-export const defaultSnippet = ``;
-export const simple = ``;
-export const withTabs = ``;
-export const withHeaderPage = ` JSX_2.Element;
-
-// @public
-export const HeaderDefinition: {
- readonly classNames: {
- readonly root: 'bui-Header';
- readonly toolbar: 'bui-HeaderToolbar';
- readonly toolbarWrapper: 'bui-HeaderToolbarWrapper';
- readonly toolbarContent: 'bui-HeaderToolbarContent';
- readonly toolbarControls: 'bui-HeaderToolbarControls';
- readonly toolbarIcon: 'bui-HeaderToolbarIcon';
- readonly toolbarName: 'bui-HeaderToolbarName';
- readonly tabsWrapper: 'bui-HeaderTabsWrapper';
- };
-};
-
// @public
export const HeaderPage: (props: HeaderPageProps) => JSX_2.Element;
@@ -1206,24 +1189,6 @@ export interface HeaderPageProps {
title?: string;
}
-// @public
-export interface HeaderProps {
- // (undocumented)
- className?: string;
- // (undocumented)
- customActions?: React.ReactNode;
- // (undocumented)
- icon?: React.ReactNode;
- // (undocumented)
- onTabSelectionChange?: TabsProps_2['onSelectionChange'];
- // (undocumented)
- tabs?: HeaderTab[];
- // (undocumented)
- title?: string;
- // (undocumented)
- titleLink?: string;
-}
-
// @public
export interface HeaderTab {
// (undocumented)
@@ -1574,6 +1539,41 @@ export interface PasswordFieldProps
size?: 'small' | 'medium' | Partial>;
}
+// @public
+export const PluginHeader: (props: PluginHeaderProps) => JSX_2.Element;
+
+// @public
+export const PluginHeaderDefinition: {
+ readonly classNames: {
+ readonly root: 'bui-PluginHeader';
+ readonly toolbar: 'bui-PluginHeaderToolbar';
+ readonly toolbarWrapper: 'bui-PluginHeaderToolbarWrapper';
+ readonly toolbarContent: 'bui-PluginHeaderToolbarContent';
+ readonly toolbarControls: 'bui-PluginHeaderToolbarControls';
+ readonly toolbarIcon: 'bui-PluginHeaderToolbarIcon';
+ readonly toolbarName: 'bui-PluginHeaderToolbarName';
+ readonly tabsWrapper: 'bui-PluginHeaderTabsWrapper';
+ };
+};
+
+// @public
+export interface PluginHeaderProps {
+ // (undocumented)
+ className?: string;
+ // (undocumented)
+ customActions?: React.ReactNode;
+ // (undocumented)
+ icon?: React.ReactNode;
+ // (undocumented)
+ onTabSelectionChange?: TabsProps_2['onSelectionChange'];
+ // (undocumented)
+ tabs?: HeaderTab[];
+ // (undocumented)
+ title?: string;
+ // (undocumented)
+ titleLink?: string;
+}
+
// @public
export const Popover: ForwardRefExoticComponent<
PopoverProps & RefAttributes
diff --git a/packages/ui/src/components/FullPage/FullPage.stories.tsx b/packages/ui/src/components/FullPage/FullPage.stories.tsx
index 8ac1b731e9..05169ca8ea 100644
--- a/packages/ui/src/components/FullPage/FullPage.stories.tsx
+++ b/packages/ui/src/components/FullPage/FullPage.stories.tsx
@@ -17,10 +17,10 @@
import preview from '../../../../../.storybook/preview';
import type { StoryFn } from '@storybook/react-vite';
import { FullPage } from './FullPage';
-import { Header } from '../Header';
+import { PluginHeader } from '../PluginHeader';
import { Container } from '../Container';
import { Text } from '../Text';
-import type { HeaderTab } from '../Header/types';
+import type { HeaderTab } from '../PluginHeader/types';
import { MemoryRouter } from 'react-router-dom';
const meta = preview.meta({
@@ -57,7 +57,7 @@ export const Default = meta.story({
decorators: [withRouter],
render: () => (
<>
-
+
@@ -73,7 +73,7 @@ export const WithScrollableContent = meta.story({
decorators: [withRouter],
render: () => (
<>
-
+
@@ -94,7 +94,7 @@ export const WithTabs = meta.story({
decorators: [withRouter],
render: () => (
<>
-
+
diff --git a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx
index 8242b5cd6a..0c027477e3 100644
--- a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx
+++ b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx
@@ -17,7 +17,7 @@
import preview from '../../../../../.storybook/preview';
import type { StoryFn } from '@storybook/react-vite';
import { HeaderPage } from './HeaderPage';
-import type { HeaderTab } from '../Header/types';
+import type { HeaderTab } from '../PluginHeader/types';
import { MemoryRouter } from 'react-router-dom';
import {
Button,
diff --git a/packages/ui/src/components/HeaderPage/types.ts b/packages/ui/src/components/HeaderPage/types.ts
index 1271461989..72d365968e 100644
--- a/packages/ui/src/components/HeaderPage/types.ts
+++ b/packages/ui/src/components/HeaderPage/types.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import type { HeaderTab } from '../Header/types';
+import type { HeaderTab } from '../PluginHeader/types';
/**
* Props for the main HeaderPage component.
diff --git a/packages/ui/src/components/Header/Header.module.css b/packages/ui/src/components/PluginHeader/PluginHeader.module.css
similarity index 88%
rename from packages/ui/src/components/Header/Header.module.css
rename to packages/ui/src/components/PluginHeader/PluginHeader.module.css
index f945b70bf0..037fd00722 100644
--- a/packages/ui/src/components/Header/Header.module.css
+++ b/packages/ui/src/components/PluginHeader/PluginHeader.module.css
@@ -17,11 +17,11 @@
@layer tokens, base, components, utilities;
@layer components {
- .bui-Header {
+ .bui-PluginHeader {
display: block;
}
- .bui-HeaderToolbar {
+ .bui-PluginHeaderToolbar {
&::before {
content: '';
position: absolute;
@@ -34,7 +34,7 @@
}
}
- .bui-HeaderToolbarWrapper {
+ .bui-PluginHeaderToolbarWrapper {
position: relative;
z-index: 1;
display: flex;
@@ -48,14 +48,14 @@
height: 52px;
}
- .bui-HeaderToolbarContent {
+ .bui-PluginHeaderToolbarContent {
display: flex;
flex-direction: row;
align-items: center;
gap: var(--bui-space-2);
}
- .bui-HeaderToolbarName {
+ .bui-PluginHeaderToolbarName {
display: flex;
flex-direction: row;
align-items: center;
@@ -65,7 +65,7 @@
flex-shrink: 0;
}
- .bui-HeaderToolbarIcon {
+ .bui-PluginHeaderToolbarIcon {
width: 16px;
height: 16px;
color: var(--bui-fg-primary);
@@ -76,7 +76,7 @@
}
}
- .bui-HeaderToolbarControls {
+ .bui-PluginHeaderToolbarControls {
position: absolute;
right: var(--bui-space-5);
top: 50%;
@@ -87,7 +87,7 @@
gap: var(--bui-space-2);
}
- .bui-HeaderTabsWrapper {
+ .bui-PluginHeaderTabsWrapper {
padding-inline: var(--bui-space-3);
border-bottom: 1px solid var(--bui-border-1);
background-color: var(--bui-bg-neutral-1);
diff --git a/packages/ui/src/components/Header/Header.stories.tsx b/packages/ui/src/components/PluginHeader/PluginHeader.stories.tsx
similarity index 96%
rename from packages/ui/src/components/Header/Header.stories.tsx
rename to packages/ui/src/components/PluginHeader/PluginHeader.stories.tsx
index d48c1a7ceb..91cb69b2a8 100644
--- a/packages/ui/src/components/Header/Header.stories.tsx
+++ b/packages/ui/src/components/PluginHeader/PluginHeader.stories.tsx
@@ -16,7 +16,7 @@
import preview from '../../../../../.storybook/preview';
import type { StoryFn } from '@storybook/react-vite';
-import { Header } from './Header';
+import { PluginHeader } from './PluginHeader';
import type { HeaderTab } from './types';
import {
Button,
@@ -38,8 +38,8 @@ import {
import { HeaderPageBreadcrumb } from '../HeaderPage/types';
const meta = preview.meta({
- title: 'Backstage UI/Header',
- component: Header,
+ title: 'Backstage UI/PluginHeader',
+ component: PluginHeader,
parameters: {
layout: 'fullscreen',
},
@@ -213,7 +213,7 @@ export const WithCustomActions = meta.story({
args: {},
decorators: [withRouter],
render: args => (
-
@@ -253,7 +253,7 @@ export const WithHeaderPage = meta.story({
decorators: [withRouter],
render: args => (
<>
-
@@ -277,7 +277,7 @@ export const WithLayout = meta.story({
decorators: layoutDecorator,
render: args => (
<>
-
+
(
<>
-
+
>
),
@@ -306,7 +306,7 @@ export const WithEverything = meta.story({
decorators: layoutDecorator,
render: args => (
<>
-
@@ -336,7 +336,7 @@ export const WithMockedURLCampaigns = meta.story({
},
render: args => (
-
+
Current URL is mocked to be: /campaigns
@@ -356,7 +356,7 @@ export const WithMockedURLIntegrations = meta.story({
},
render: args => (
-
+
Current URL is mocked to be: /integrations
@@ -376,7 +376,7 @@ export const WithMockedURLNoMatch = meta.story({
},
render: args => (
-
+
Current URL is mocked to be: /some-other-page
@@ -424,7 +424,7 @@ export const WithTabsMatchingStrategies = meta.story({
},
render: args => (
-
+
Current URL: /mentorship/events
@@ -477,7 +477,7 @@ export const WithTabsExactMatching = meta.story({
},
render: args => (
-
+
Current URL: /mentorship/events
@@ -519,7 +519,7 @@ export const WithTabsPrefixMatchingDeep = meta.story({
},
render: args => (
-
+
Current URL: /catalog/users/john/details
diff --git a/packages/ui/src/components/Header/Header.tsx b/packages/ui/src/components/PluginHeader/PluginHeader.tsx
similarity index 86%
rename from packages/ui/src/components/Header/Header.tsx
rename to packages/ui/src/components/PluginHeader/PluginHeader.tsx
index 09f29b95c5..2ed663d61c 100644
--- a/packages/ui/src/components/Header/Header.tsx
+++ b/packages/ui/src/components/PluginHeader/PluginHeader.tsx
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-import type { HeaderProps } from './types';
-import { HeaderToolbar } from './HeaderToolbar';
+import type { PluginHeaderProps } from './types';
+import { PluginHeaderToolbar } from './PluginHeaderToolbar';
import { Tabs, TabList, Tab } from '../Tabs';
import { useStyles } from '../../hooks/useStyles';
-import { HeaderDefinition } from './definition';
+import { PluginHeaderDefinition } from './definition';
import { type NavigateOptions } from 'react-router-dom';
import { useRef } from 'react';
import { useIsomorphicLayoutEffect } from '../../hooks/useIsomorphicLayoutEffect';
-import styles from './Header.module.css';
+import styles from './PluginHeader.module.css';
import clsx from 'clsx';
declare module 'react-aria-components' {
@@ -32,12 +32,13 @@ declare module 'react-aria-components' {
}
/**
- * A component that renders a toolbar.
+ * A component that renders a plugin header with icon, title, custom actions,
+ * and navigation tabs.
*
* @public
*/
-export const Header = (props: HeaderProps) => {
- const { classNames, cleanedProps } = useStyles(HeaderDefinition, props);
+export const PluginHeader = (props: PluginHeaderProps) => {
+ const { classNames, cleanedProps } = useStyles(PluginHeaderDefinition, props);
const {
className,
tabs,
@@ -88,7 +89,7 @@ export const Header = (props: HeaderProps) => {
ref={headerRef}
className={clsx(classNames.root, styles[classNames.root], className)}
>
- {
- const { classNames, cleanedProps } = useStyles(HeaderDefinition, props);
+export const PluginHeaderToolbar = (props: PluginHeaderToolbarProps) => {
+ const { classNames, cleanedProps } = useStyles(PluginHeaderDefinition, props);
const { className, icon, title, titleLink, customActions, hasTabs } =
cleanedProps;
diff --git a/packages/ui/src/components/Header/definition.ts b/packages/ui/src/components/PluginHeader/definition.ts
similarity index 61%
rename from packages/ui/src/components/Header/definition.ts
rename to packages/ui/src/components/PluginHeader/definition.ts
index 6937bc5347..39de7a0443 100644
--- a/packages/ui/src/components/Header/definition.ts
+++ b/packages/ui/src/components/PluginHeader/definition.ts
@@ -17,18 +17,18 @@
import type { ComponentDefinition } from '../../types';
/**
- * Component definition for Header
+ * Component definition for PluginHeader
* @public
*/
-export const HeaderDefinition = {
+export const PluginHeaderDefinition = {
classNames: {
- root: 'bui-Header',
- toolbar: 'bui-HeaderToolbar',
- toolbarWrapper: 'bui-HeaderToolbarWrapper',
- toolbarContent: 'bui-HeaderToolbarContent',
- toolbarControls: 'bui-HeaderToolbarControls',
- toolbarIcon: 'bui-HeaderToolbarIcon',
- toolbarName: 'bui-HeaderToolbarName',
- tabsWrapper: 'bui-HeaderTabsWrapper',
+ root: 'bui-PluginHeader',
+ toolbar: 'bui-PluginHeaderToolbar',
+ toolbarWrapper: 'bui-PluginHeaderToolbarWrapper',
+ toolbarContent: 'bui-PluginHeaderToolbarContent',
+ toolbarControls: 'bui-PluginHeaderToolbarControls',
+ toolbarIcon: 'bui-PluginHeaderToolbarIcon',
+ toolbarName: 'bui-PluginHeaderToolbarName',
+ tabsWrapper: 'bui-PluginHeaderTabsWrapper',
},
} as const satisfies ComponentDefinition;
diff --git a/packages/ui/src/components/Header/index.tsx b/packages/ui/src/components/PluginHeader/index.tsx
similarity index 78%
rename from packages/ui/src/components/Header/index.tsx
rename to packages/ui/src/components/PluginHeader/index.tsx
index 60685cfaa6..306910f516 100644
--- a/packages/ui/src/components/Header/index.tsx
+++ b/packages/ui/src/components/PluginHeader/index.tsx
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-export { Header } from './Header';
-export { HeaderDefinition } from './definition';
-export type { HeaderProps, HeaderTab } from './types';
+export { PluginHeader } from './PluginHeader';
+export { PluginHeaderDefinition } from './definition';
+export type { PluginHeaderProps, HeaderTab } from './types';
diff --git a/packages/ui/src/components/Header/types.ts b/packages/ui/src/components/PluginHeader/types.ts
similarity index 80%
rename from packages/ui/src/components/Header/types.ts
rename to packages/ui/src/components/PluginHeader/types.ts
index 57dd1088f5..21021cdbaf 100644
--- a/packages/ui/src/components/Header/types.ts
+++ b/packages/ui/src/components/PluginHeader/types.ts
@@ -18,11 +18,11 @@ import { TabsProps } from 'react-aria-components';
import { TabMatchStrategy } from '../Tabs';
/**
- * Props for the main Header component.
+ * Props for the {@link PluginHeader} component.
*
* @public
*/
-export interface HeaderProps {
+export interface PluginHeaderProps {
icon?: React.ReactNode;
title?: string;
titleLink?: string;
@@ -50,15 +50,15 @@ export interface HeaderTab {
}
/**
- * Props for the HeaderToolbar component.
+ * Props for the PluginHeaderToolbar component.
*
* @internal
*/
-export interface HeaderToolbarProps {
- icon?: HeaderProps['icon'];
- title?: HeaderProps['title'];
- titleLink?: HeaderProps['titleLink'];
- customActions?: HeaderProps['customActions'];
+export interface PluginHeaderToolbarProps {
+ icon?: PluginHeaderProps['icon'];
+ title?: PluginHeaderProps['title'];
+ titleLink?: PluginHeaderProps['titleLink'];
+ customActions?: PluginHeaderProps['customActions'];
hasTabs?: boolean;
className?: string;
}
diff --git a/packages/ui/src/components/SearchField/SearchField.stories.tsx b/packages/ui/src/components/SearchField/SearchField.stories.tsx
index 2e07e742ad..7b75cfd24a 100644
--- a/packages/ui/src/components/SearchField/SearchField.stories.tsx
+++ b/packages/ui/src/components/SearchField/SearchField.stories.tsx
@@ -23,7 +23,7 @@ import { FieldLabel } from '../FieldLabel';
import { ButtonIcon } from '../ButtonIcon';
import { RiCactusLine, RiEBike2Line } from '@remixicon/react';
import { Button } from '../Button';
-import { Header } from '../Header';
+import { PluginHeader } from '../PluginHeader';
import { MemoryRouter } from 'react-router-dom';
const meta = preview.meta({
@@ -192,7 +192,7 @@ export const InHeader = meta.story({
],
render: args => (
<>
-
@@ -229,7 +229,7 @@ export const StartCollapsedInHeader = meta.story({
],
render: args => (
<>
-
diff --git a/packages/ui/src/definitions.ts b/packages/ui/src/definitions.ts
index 030584fbb3..59003e8070 100644
--- a/packages/ui/src/definitions.ts
+++ b/packages/ui/src/definitions.ts
@@ -42,7 +42,7 @@ export {
GridDefinition,
GridItemDefinition,
} from './components/Grid/definition';
-export { HeaderDefinition } from './components/Header/definition';
+export { PluginHeaderDefinition } from './components/PluginHeader/definition';
export { HeaderPageDefinition } from './components/HeaderPage/definition';
export { LinkDefinition } from './components/Link/definition';
export { MenuDefinition } from './components/Menu/definition';
diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts
index 40f37aba41..c70aa9d325 100644
--- a/packages/ui/src/index.ts
+++ b/packages/ui/src/index.ts
@@ -35,7 +35,7 @@ export * from './components/Button';
export * from './components/Card';
export * from './components/Dialog';
export * from './components/FieldLabel';
-export * from './components/Header';
+export * from './components/PluginHeader';
export * from './components/HeaderPage';
export * from './components/ButtonIcon';
export * from './components/ButtonLink';