From 49ffe8ae6b4ed5504b008c8d4b59a35e5ee4df97 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Sat, 21 Mar 2026 10:14:44 +0000 Subject: [PATCH 1/7] First pass improving the PluginHeader Signed-off-by: Charles de Dreuille --- .../plugin-header-remove-toolbar-wrapper.md | 9 + .storybook/themes/spotify.css | 54 +-- packages/ui/report.api.md | 1 - .../PluginHeader/PluginHeader.module.css | 20 +- .../PluginHeader/PluginHeader.stories.tsx | 197 +---------- .../components/PluginHeader/PluginHeader.tsx | 64 ++-- .../src/components/PluginHeader/definition.ts | 1 - .../recipes/PluginHeaderAndHeader.stories.tsx | 326 ++++++++++++++++++ 8 files changed, 418 insertions(+), 254 deletions(-) create mode 100644 .changeset/plugin-header-remove-toolbar-wrapper.md create mode 100644 packages/ui/src/recipes/PluginHeaderAndHeader.stories.tsx diff --git a/.changeset/plugin-header-remove-toolbar-wrapper.md b/.changeset/plugin-header-remove-toolbar-wrapper.md new file mode 100644 index 0000000000..084eab9b61 --- /dev/null +++ b/.changeset/plugin-header-remove-toolbar-wrapper.md @@ -0,0 +1,9 @@ +--- +'@backstage/ui': minor +--- + +**BREAKING**: Removed the `toolbarWrapper` element from `PluginHeader` and dropped `toolbarWrapper` from `PluginHeaderDefinition.classNames`. Toolbar layout styles now live on `toolbar` (`.bui-PluginHeaderToolbar`). Update custom CSS that targeted `.bui-PluginHeaderToolbarWrapper` to use `.bui-PluginHeaderToolbar` instead. + +**Affected components:** PluginHeader + +`PluginHeader` now establishes a neutral background provider (same rules as `Box` with `bg="neutral"`) so controls in the toolbar and tabs resolve `data-on-bg` correctly. diff --git a/.storybook/themes/spotify.css b/.storybook/themes/spotify.css index 3cad0fba10..47706497d8 100644 --- a/.storybook/themes/spotify.css +++ b/.storybook/themes/spotify.css @@ -183,21 +183,6 @@ font-weight: var(--bui-font-weight-regular); } - .bui-PluginHeaderToolbarWrapper { - padding: 0; - height: 32px; - border: none; - background: none; - } - - .bui-PluginHeaderTabsWrapper { - margin: 0; - padding: 0; - margin-left: -8px; - border: none; - background: none; - } - .bui-Input { border-radius: var(--bui-radius-3); } @@ -228,14 +213,6 @@ --bui-border-success: #53db83; --bui-ring: rgba(0, 0, 0, 0.2); - - .bui-HeaderToolbarWrapper { - border: 1px solid var(--bui-border-2); - } - - .bui-HeaderTabsWrapper { - border: 1px solid var(--bui-border-2); - } } [data-theme-mode='dark'][data-theme-name='spotify'] { @@ -266,3 +243,34 @@ --bui-ring: rgba(255, 255, 255, 0.2); } + +/* + * Plugin header (@backstage/ui) and story shell header — kept at the bottom of + * this file for easier scanning alongside other component overrides above. + */ +[data-theme-name='spotify'] { + .bui-PluginHeaderToolbar { + padding: 0; + height: 32px; + border: none; + background: none; + margin-bottom: var(--bui-space-2); + } + + .bui-PluginHeaderTabsWrapper { + margin: 0; + padding: 0; + border: none; + background: none; + } +} + +[data-theme-mode='light'][data-theme-name='spotify'] { + .bui-HeaderToolbarWrapper { + border: 1px solid var(--bui-border-2); + } + + .bui-HeaderTabsWrapper { + border: 1px solid var(--bui-border-2); + } +} diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md index 511074f8bb..fcfacb7412 100644 --- a/packages/ui/report.api.md +++ b/packages/ui/report.api.md @@ -1949,7 +1949,6 @@ 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'; diff --git a/packages/ui/src/components/PluginHeader/PluginHeader.module.css b/packages/ui/src/components/PluginHeader/PluginHeader.module.css index f016ef7674..3b8aa9a698 100644 --- a/packages/ui/src/components/PluginHeader/PluginHeader.module.css +++ b/packages/ui/src/components/PluginHeader/PluginHeader.module.css @@ -17,15 +17,16 @@ @layer tokens, base, components, utilities; @layer components { - .bui-PluginHeaderToolbarWrapper { + .bui-PluginHeaderToolbar { display: flex; flex-direction: row; align-items: center; justify-content: space-between; padding-inline: var(--bui-space-5); - border-bottom: 1px solid var(--bui-border-1); color: var(--bui-fg-primary); height: 52px; + background-color: var(--bui-bg-neutral-1); + border-bottom: 1px solid var(--bui-border-1); } .bui-PluginHeaderToolbarContent { @@ -46,13 +47,19 @@ } .bui-PluginHeaderToolbarIcon { - width: 16px; - height: 16px; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + width: 2rem; + height: 2rem; + border-radius: var(--bui-radius-2); + background-color: var(--bui-bg-neutral-2); color: var(--bui-fg-primary); & svg { - width: 100%; - height: 100%; + width: 1rem; + height: 1rem; } } @@ -66,5 +73,6 @@ .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/PluginHeader/PluginHeader.stories.tsx b/packages/ui/src/components/PluginHeader/PluginHeader.stories.tsx index d0d3475dbb..faadd4fc67 100644 --- a/packages/ui/src/components/PluginHeader/PluginHeader.stories.tsx +++ b/packages/ui/src/components/PluginHeader/PluginHeader.stories.tsx @@ -19,8 +19,6 @@ import type { StoryFn } from '@storybook/react-vite'; import { PluginHeader } from './PluginHeader'; import type { HeaderTab } from './types'; import { - Button, - Header, Container, Text, ButtonIcon, @@ -36,7 +34,6 @@ import { RiCloudy2Line, RiMore2Line, } from '@remixicon/react'; -import { HeaderBreadcrumb } from '../Header/types'; const meta = preview.meta({ title: 'Backstage UI/PluginHeader', @@ -82,24 +79,6 @@ const tabs: HeaderTab[] = [ }, ]; -const tabs2: HeaderTab[] = [ - { - id: 'Banana', - label: 'Banana', - href: '/banana', - }, - { - id: 'Apple', - label: 'Apple', - href: '/apple', - }, - { - id: 'Orange', - label: 'Orange', - href: '/orange', - }, -]; - const menuItems = [ { label: 'Settings', @@ -120,86 +99,6 @@ const menuItems = [ }, ]; -const breadcrumbs: HeaderBreadcrumb[] = [ - { - label: 'Home', - href: '/', - }, - { - label: 'Dashboard', - href: '/dashboard', - }, - { - label: 'Settings', - href: '/settings', - }, -]; - -// Extract layout decorator as a reusable constant -const layoutDecorator = [ - (Story: StoryFn) => ( - <> -
-
- - - - Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, - quos. - - - Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, - quos. - - - Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, - quos. - - - Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, - quos. - - - Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, - quos. - - - Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, - quos. - - - Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, - quos. - - - Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, - quos. - - -
- - ), - withRouter, -]; - export const Default = meta.story({ args: {}, decorators: [withRouter], @@ -249,90 +148,6 @@ export const WithAllOptionsAndTabs = WithCustomActions.extend({ }, }); -export const WithHeader = meta.story({ - args: { - ...WithAllOptionsAndTabs.input.args, - }, - decorators: [withRouter], - render: args => ( - <> - - } /> - } /> - } /> - - } - /> -
Custom action} - breadcrumbs={breadcrumbs} - /> - - ), -}); - -export const WithLayout = meta.story({ - decorators: layoutDecorator, - render: args => ( - <> - -
Custom action} - breadcrumbs={breadcrumbs} - /> - - ), -}); - -export const WithLayoutNoTabs = meta.story({ - decorators: layoutDecorator, - render: args => ( - <> - -
- - ), -}); - -export const WithEverything = meta.story({ - args: { - tabs, - titleLink: '/', - }, - decorators: layoutDecorator, - render: args => ( - <> - - } /> - } /> - } /> - - } - /> -
- - - - } - /> - - ), -}); - export const WithMockedURLCampaigns = meta.story({ args: { tabs, @@ -341,7 +156,7 @@ export const WithMockedURLCampaigns = meta.story({ - + Current URL is mocked to be: /campaigns @@ -363,7 +178,7 @@ export const WithMockedURLIntegrations = meta.story({ - + Current URL is mocked to be: /integrations @@ -385,7 +200,7 @@ export const WithMockedURLNoMatch = meta.story({ - + Current URL is mocked to be: /some-other-page @@ -435,7 +250,7 @@ export const WithTabsMatchingStrategies = meta.story({ - + Current URL: /mentorship/events @@ -490,7 +305,7 @@ export const WithTabsExactMatching = meta.story({ - + Current URL: /mentorship/events @@ -534,7 +349,7 @@ export const WithTabsPrefixMatchingDeep = meta.story({ - + Current URL: /catalog/users/john/details diff --git a/packages/ui/src/components/PluginHeader/PluginHeader.tsx b/packages/ui/src/components/PluginHeader/PluginHeader.tsx index 2414e22975..9cc3161ef7 100644 --- a/packages/ui/src/components/PluginHeader/PluginHeader.tsx +++ b/packages/ui/src/components/PluginHeader/PluginHeader.tsx @@ -17,12 +17,13 @@ import type { PluginHeaderProps } from './types'; import { Tabs, TabList, Tab } from '../Tabs'; import { useDefinition } from '../../hooks/useDefinition'; +import { useBgProvider, BgProvider } from '../../hooks/useBg'; import { PluginHeaderDefinition } from './definition'; import { type NavigateOptions } from 'react-router-dom'; import { Children, useMemo, useRef } from 'react'; import { useIsomorphicLayoutEffect } from '../../hooks/useIsomorphicLayoutEffect'; import { Box } from '../Box'; -import { Link } from 'react-aria-components'; +import { Link } from '../Link'; import { RiShapesLine } from '@remixicon/react'; import { Text } from '../Text'; @@ -33,8 +34,9 @@ declare module 'react-aria-components' { } /** - * A component that renders a plugin header with icon, title, custom actions, - * and navigation tabs. + * Renders a plugin header with icon, title, custom actions, and optional tabs. + * Always participates in the background context system so descendants (e.g. buttons) + * get the correct `data-on-bg` styling inside the toolbar and tabs. * * @public */ @@ -50,11 +52,9 @@ export const PluginHeader = (props: PluginHeaderProps) => { onTabSelectionChange, } = ownProps; + const providerBg = useBgProvider('neutral'); const hasTabs = tabs && tabs.length > 0; const headerRef = useRef(null); - const toolbarWrapperRef = useRef(null); - const toolbarContentRef = useRef(null); - const toolbarControlsRef = useRef(null); const animationFrameRef = useRef(undefined); const lastAppliedHeightRef = useRef(undefined); @@ -123,37 +123,29 @@ export const PluginHeader = (props: PluginHeaderProps) => { }; }, []); - const titleContent = ( - <> - - {title || 'Your plugin'} - - ); + const titleText = title || 'Your plugin'; - return ( -
+ const inner = ( + <>
-
-
- - {titleLink ? ( - - {titleContent} - - ) : ( -
{titleContent}
- )} -
-
-
- {actionChildren} -
+
+
{icon || }
+

+ {titleLink ? ( + + {titleText} + + ) : ( + + {titleText} + + )} +

+
{actionChildren}
{tabs && ( - + {tabs?.map(tab => ( @@ -170,6 +162,14 @@ export const PluginHeader = (props: PluginHeaderProps) => { )} + + ); + + const { bg: surfaceBg } = providerBg; + + return ( +
+ {surfaceBg ? {inner} : inner}
); }; diff --git a/packages/ui/src/components/PluginHeader/definition.ts b/packages/ui/src/components/PluginHeader/definition.ts index c9a35aa956..66414efbee 100644 --- a/packages/ui/src/components/PluginHeader/definition.ts +++ b/packages/ui/src/components/PluginHeader/definition.ts @@ -27,7 +27,6 @@ export const PluginHeaderDefinition = defineComponent()({ classNames: { root: 'bui-PluginHeader', toolbar: 'bui-PluginHeaderToolbar', - toolbarWrapper: 'bui-PluginHeaderToolbarWrapper', toolbarContent: 'bui-PluginHeaderToolbarContent', toolbarControls: 'bui-PluginHeaderToolbarControls', toolbarIcon: 'bui-PluginHeaderToolbarIcon', diff --git a/packages/ui/src/recipes/PluginHeaderAndHeader.stories.tsx b/packages/ui/src/recipes/PluginHeaderAndHeader.stories.tsx new file mode 100644 index 0000000000..b3fc2efc57 --- /dev/null +++ b/packages/ui/src/recipes/PluginHeaderAndHeader.stories.tsx @@ -0,0 +1,326 @@ +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import preview from '../../../../.storybook/preview'; +import type { StoryFn } from '@storybook/react-vite'; +import { MemoryRouter } from 'react-router-dom'; +import { BUIProvider } from '../provider'; +import { + PluginHeader, + Header, + Button, + ButtonIcon, + Card, + Container, + Flex, + MenuTrigger, + Menu, + MenuItem, +} from '..'; +import { + RiBookOpenLine, + RiBox3Line, + RiCodeSSlashLine, + RiDownloadLine, + RiEdit2Line, + RiGitBranchLine, + RiMore2Line, + RiPlayLine, + RiRefreshLine, + RiSettings4Line, + RiShieldCheckLine, + RiShareBoxLine, + RiTerminalLine, +} from '@remixicon/react'; + +// --------------------------------------------------------------------------- +// Shared page content placeholder +// --------------------------------------------------------------------------- + +const PageContent = () => ( + + + + + + + +); + +// --------------------------------------------------------------------------- +// Shared layout decorator +// --------------------------------------------------------------------------- + +const withLayout = (Story: StoryFn) => ( + + + + + +); + +// --------------------------------------------------------------------------- +// Meta +// --------------------------------------------------------------------------- + +const meta = preview.meta({ + title: 'Recipes/PluginHeader and Header', + parameters: { + layout: 'fullscreen', + }, +}); + +// --------------------------------------------------------------------------- +// Story: Catalog entity page +// --------------------------------------------------------------------------- + +export const CatalogEntityPage = meta.story({ + decorators: [withLayout], + render: () => ( + <> + } + title="Catalog" + titleLink="/" + tabs={[ + { id: 'catalog', label: 'Catalog', href: '/catalog' }, + { id: 'apis', label: 'APIs', href: '/apis' }, + { id: 'resources', label: 'Resources', href: '/resources' }, + { id: 'templates', label: 'Templates', href: '/templates' }, + { id: 'docs', label: 'Docs', href: '/docs' }, + ]} + customActions={ + <> + } + aria-label="Settings" + /> + + } + aria-label="More options" + /> + + Import component + Register existing + View documentation + + + + } + /> +
+ + + + } + /> + + + ), +}); + +// --------------------------------------------------------------------------- +// Story: CI/CD pipeline view +// --------------------------------------------------------------------------- + +export const CICDPipelineView = meta.story({ + decorators: [withLayout], + render: () => ( + <> + } + title="CI/CD" + titleLink="/" + tabs={[ + { id: 'builds', label: 'Builds', href: '/builds' }, + { id: 'pipelines', label: 'Pipelines', href: '/pipelines' }, + { id: 'deployments', label: 'Deployments', href: '/deployments' }, + { id: 'settings', label: 'Settings', href: '/settings' }, + ]} + customActions={ + <> + } + aria-label="Refresh" + /> + + } + /> +
+ + + + } + /> + + + ), +}); + +// --------------------------------------------------------------------------- +// Story: TechDocs page +// --------------------------------------------------------------------------- + +export const TechDocsPage = meta.story({ + decorators: [withLayout], + render: () => ( + <> + } + title="TechDocs" + titleLink="/" + tabs={[ + { id: 'explore', label: 'Explore', href: '/explore' }, + { id: 'owned', label: 'Owned by me', href: '/owned' }, + { id: 'starred', label: 'Starred', href: '/starred' }, + ]} + /> +
+ } + aria-label="More options" + /> + + } href="/share"> + Share link + + } href="/edit"> + Edit on GitHub + + + + } + /> + + + ), +}); + +// --------------------------------------------------------------------------- +// Story: Security / compliance audit page +// --------------------------------------------------------------------------- + +export const SecurityAuditPage = meta.story({ + decorators: [withLayout], + render: () => ( + <> + } + title="Security" + titleLink="/" + tabs={[ + { id: 'overview', label: 'Overview', href: '/overview' }, + { id: 'vulnerabilities', label: 'Vulnerabilities', href: '/vulns' }, + { id: 'policies', label: 'Policies', href: '/policies' }, + { id: 'audits', label: 'Audits', href: '/audits' }, + ]} + customActions={ + <> + } + aria-label="Refresh scan" + /> + + + } + /> +
+ + + } + /> + + + ), +}); + +// --------------------------------------------------------------------------- +// Story: Minimal — no tabs, no actions +// --------------------------------------------------------------------------- + +export const Minimal = meta.story({ + decorators: [withLayout], + render: () => ( + <> + } title="APIs" titleLink="/" /> +
+ + + ), +}); From bcf8042a2f98eb1228fa2107cfc8e1e8f90f7005 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Sat, 21 Mar 2026 17:52:36 +0000 Subject: [PATCH 2/7] Improve styles for Header Signed-off-by: Charles de Dreuille --- .storybook/themes/spotify.css | 11 +- .../src/components/Header/Header.stories.tsx | 40 ----- .../PluginHeader/PluginHeader.stories.tsx | 8 +- .../recipes/PluginHeaderAndHeader.stories.tsx | 164 +++++------------- 4 files changed, 54 insertions(+), 169 deletions(-) diff --git a/.storybook/themes/spotify.css b/.storybook/themes/spotify.css index 47706497d8..add82b87ab 100644 --- a/.storybook/themes/spotify.css +++ b/.storybook/themes/spotify.css @@ -258,19 +258,12 @@ } .bui-PluginHeaderTabsWrapper { - margin: 0; padding: 0; border: none; background: none; } -} -[data-theme-mode='light'][data-theme-name='spotify'] { - .bui-HeaderToolbarWrapper { - border: 1px solid var(--bui-border-2); - } - - .bui-HeaderTabsWrapper { - border: 1px solid var(--bui-border-2); + .bui-PluginHeaderTabsWrapper { + margin-left: -8px; } } diff --git a/packages/ui/src/components/Header/Header.stories.tsx b/packages/ui/src/components/Header/Header.stories.tsx index 0adfb43d55..82f0df7311 100644 --- a/packages/ui/src/components/Header/Header.stories.tsx +++ b/packages/ui/src/components/Header/Header.stories.tsx @@ -95,42 +95,6 @@ const withRouter = (Story: StoryFn) => ( ); -// Extract layout decorator as a reusable constant -const layoutDecorator = [ - (Story: StoryFn) => ( - <> -
-
- - - - Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, - quos. - - -
- - ), -]; - export const Default = meta.story({ args: { title: 'Page Title', @@ -208,10 +172,6 @@ export const WithEverything = meta.story({ ), }); -export const WithLayout = WithEverything.extend({ - decorators: [...layoutDecorator], -}); - export const WithTabsMatchingStrategies = meta.story({ args: { title: 'Route Matching Demo', diff --git a/packages/ui/src/components/PluginHeader/PluginHeader.stories.tsx b/packages/ui/src/components/PluginHeader/PluginHeader.stories.tsx index faadd4fc67..815fadf6e7 100644 --- a/packages/ui/src/components/PluginHeader/PluginHeader.stories.tsx +++ b/packages/ui/src/components/PluginHeader/PluginHeader.stories.tsx @@ -119,11 +119,11 @@ export const WithCustomActions = meta.story({ {...args} customActions={ <> - } /> - } /> - } /> + } /> + } /> + } /> - } /> + } /> {menuItems.map(option => ( ( + <> + } title="APIs" /> + + + ), +}); -export const CatalogEntityPage = meta.story({ +export const SimpleHeader = meta.story({ + decorators: [withLayout], + render: () => ( + <> + } title="APIs" /> +
+ + + ), +}); + +export const WithTabs = meta.story({ decorators: [withLayout], render: () => ( <> @@ -126,17 +143,6 @@ export const CatalogEntityPage = meta.story({ />
} />
+ } @@ -309,18 +256,3 @@ export const SecurityAuditPage = meta.story({ ), }); - -// --------------------------------------------------------------------------- -// Story: Minimal — no tabs, no actions -// --------------------------------------------------------------------------- - -export const Minimal = meta.story({ - decorators: [withLayout], - render: () => ( - <> - } title="APIs" titleLink="/" /> -
- - - ), -}); From 4d259c24d61b3faddaab435df0248360b3a19541 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Sat, 21 Mar 2026 18:09:22 +0000 Subject: [PATCH 3/7] Updates Signed-off-by: Charles de Dreuille --- .changeset/plugin-header-remove-toolbar-wrapper.md | 6 +++--- packages/ui/src/components/PluginHeader/PluginHeader.tsx | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.changeset/plugin-header-remove-toolbar-wrapper.md b/.changeset/plugin-header-remove-toolbar-wrapper.md index 084eab9b61..a68bb1dfdd 100644 --- a/.changeset/plugin-header-remove-toolbar-wrapper.md +++ b/.changeset/plugin-header-remove-toolbar-wrapper.md @@ -2,8 +2,8 @@ '@backstage/ui': minor --- -**BREAKING**: Removed the `toolbarWrapper` element from `PluginHeader` and dropped `toolbarWrapper` from `PluginHeaderDefinition.classNames`. Toolbar layout styles now live on `toolbar` (`.bui-PluginHeaderToolbar`). Update custom CSS that targeted `.bui-PluginHeaderToolbarWrapper` to use `.bui-PluginHeaderToolbar` instead. +**BREAKING**: Removed the `toolbarWrapper` element from `PluginHeader` and dropped `toolbarWrapper` from `PluginHeaderDefinition.classNames`. Toolbar layout styles now live on `toolbar` (`.bui-PluginHeaderToolbar`). + +**Migration:** Update custom CSS that targeted `.bui-PluginHeaderToolbarWrapper` to use `.bui-PluginHeaderToolbar` instead. **Affected components:** PluginHeader - -`PluginHeader` now establishes a neutral background provider (same rules as `Box` with `bg="neutral"`) so controls in the toolbar and tabs resolve `data-on-bg` correctly. diff --git a/packages/ui/src/components/PluginHeader/PluginHeader.tsx b/packages/ui/src/components/PluginHeader/PluginHeader.tsx index 9cc3161ef7..a7228503f1 100644 --- a/packages/ui/src/components/PluginHeader/PluginHeader.tsx +++ b/packages/ui/src/components/PluginHeader/PluginHeader.tsx @@ -129,7 +129,9 @@ export const PluginHeader = (props: PluginHeaderProps) => { <>
-
{icon || }
+

{titleLink ? ( From db7681b0912474265df8621f29b354d8a86129d3 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 23 Mar 2026 14:02:15 +0000 Subject: [PATCH 4/7] Bring back Box Signed-off-by: Charles de Dreuille --- .storybook/themes/spotify.css | 3 --- .../PluginHeader/PluginHeader.module.css | 1 - .../components/PluginHeader/PluginHeader.tsx | 18 ++++-------------- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/.storybook/themes/spotify.css b/.storybook/themes/spotify.css index add82b87ab..30aa0274d0 100644 --- a/.storybook/themes/spotify.css +++ b/.storybook/themes/spotify.css @@ -261,9 +261,6 @@ padding: 0; border: none; background: none; - } - - .bui-PluginHeaderTabsWrapper { margin-left: -8px; } } diff --git a/packages/ui/src/components/PluginHeader/PluginHeader.module.css b/packages/ui/src/components/PluginHeader/PluginHeader.module.css index 3b8aa9a698..703fd6e4cf 100644 --- a/packages/ui/src/components/PluginHeader/PluginHeader.module.css +++ b/packages/ui/src/components/PluginHeader/PluginHeader.module.css @@ -25,7 +25,6 @@ padding-inline: var(--bui-space-5); color: var(--bui-fg-primary); height: 52px; - background-color: var(--bui-bg-neutral-1); border-bottom: 1px solid var(--bui-border-1); } diff --git a/packages/ui/src/components/PluginHeader/PluginHeader.tsx b/packages/ui/src/components/PluginHeader/PluginHeader.tsx index a7228503f1..6dd7737d8f 100644 --- a/packages/ui/src/components/PluginHeader/PluginHeader.tsx +++ b/packages/ui/src/components/PluginHeader/PluginHeader.tsx @@ -17,7 +17,6 @@ import type { PluginHeaderProps } from './types'; import { Tabs, TabList, Tab } from '../Tabs'; import { useDefinition } from '../../hooks/useDefinition'; -import { useBgProvider, BgProvider } from '../../hooks/useBg'; import { PluginHeaderDefinition } from './definition'; import { type NavigateOptions } from 'react-router-dom'; import { Children, useMemo, useRef } from 'react'; @@ -52,7 +51,6 @@ export const PluginHeader = (props: PluginHeaderProps) => { onTabSelectionChange, } = ownProps; - const providerBg = useBgProvider('neutral'); const hasTabs = tabs && tabs.length > 0; const headerRef = useRef(null); const animationFrameRef = useRef(undefined); @@ -125,9 +123,9 @@ export const PluginHeader = (props: PluginHeaderProps) => { const titleText = title || 'Your plugin'; - const inner = ( - <> -
+ return ( +
+

{actionChildren}
-
+ {tabs && ( @@ -164,14 +162,6 @@ export const PluginHeader = (props: PluginHeaderProps) => { )} - - ); - - const { bg: surfaceBg } = providerBg; - - return ( -
- {surfaceBg ? {inner} : inner}
); }; From 9361eb3f941b7a8a08d567000fe50b1b768aa1a4 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 23 Mar 2026 14:26:30 +0000 Subject: [PATCH 5/7] Update PluginHeader.tsx Signed-off-by: Charles de Dreuille --- .../components/PluginHeader/PluginHeader.tsx | 77 ++++++++++--------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/packages/ui/src/components/PluginHeader/PluginHeader.tsx b/packages/ui/src/components/PluginHeader/PluginHeader.tsx index 6dd7737d8f..e7f76d6a5b 100644 --- a/packages/ui/src/components/PluginHeader/PluginHeader.tsx +++ b/packages/ui/src/components/PluginHeader/PluginHeader.tsx @@ -25,6 +25,7 @@ import { Box } from '../Box'; import { Link } from '../Link'; import { RiShapesLine } from '@remixicon/react'; import { Text } from '../Text'; +import { BgReset } from '../../hooks/useBg'; declare module 'react-aria-components' { interface RouterConfig { @@ -124,44 +125,46 @@ export const PluginHeader = (props: PluginHeaderProps) => { const titleText = title || 'Your plugin'; return ( -
- -
- -
{actionChildren}
- - {tabs && ( - - - - {tabs?.map(tab => ( - - {tab.label} - - ))} - - +
{actionChildren}
- )} -
+ {tabs && ( + + + + {tabs?.map(tab => ( + + {tab.label} + + ))} + + + + )} +
+ ); }; From 844f98c07e0c37daf178c5d11815bbbc3d68a2ca Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 23 Mar 2026 15:20:15 +0000 Subject: [PATCH 6/7] Add bg neutral on the tabs Signed-off-by: Charles de Dreuille --- packages/ui/src/components/PluginHeader/PluginHeader.module.css | 1 - packages/ui/src/components/PluginHeader/PluginHeader.tsx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/ui/src/components/PluginHeader/PluginHeader.module.css b/packages/ui/src/components/PluginHeader/PluginHeader.module.css index 703fd6e4cf..8115cc8a7f 100644 --- a/packages/ui/src/components/PluginHeader/PluginHeader.module.css +++ b/packages/ui/src/components/PluginHeader/PluginHeader.module.css @@ -72,6 +72,5 @@ .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/PluginHeader/PluginHeader.tsx b/packages/ui/src/components/PluginHeader/PluginHeader.tsx index e7f76d6a5b..7a2999e363 100644 --- a/packages/ui/src/components/PluginHeader/PluginHeader.tsx +++ b/packages/ui/src/components/PluginHeader/PluginHeader.tsx @@ -147,7 +147,7 @@ export const PluginHeader = (props: PluginHeaderProps) => {
{actionChildren}
{tabs && ( - + {tabs?.map(tab => ( From b5d08664d6d173b1061e27c7a59acc14154a1a12 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 23 Mar 2026 15:24:23 +0000 Subject: [PATCH 7/7] Replace div with Box Signed-off-by: Charles de Dreuille --- .../src/components/PluginHeader/PluginHeader.module.css | 1 - packages/ui/src/components/PluginHeader/PluginHeader.tsx | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/ui/src/components/PluginHeader/PluginHeader.module.css b/packages/ui/src/components/PluginHeader/PluginHeader.module.css index 8115cc8a7f..1ab0f9570a 100644 --- a/packages/ui/src/components/PluginHeader/PluginHeader.module.css +++ b/packages/ui/src/components/PluginHeader/PluginHeader.module.css @@ -53,7 +53,6 @@ width: 2rem; height: 2rem; border-radius: var(--bui-radius-2); - background-color: var(--bui-bg-neutral-2); color: var(--bui-fg-primary); & svg { diff --git a/packages/ui/src/components/PluginHeader/PluginHeader.tsx b/packages/ui/src/components/PluginHeader/PluginHeader.tsx index 7a2999e363..e410ce91f9 100644 --- a/packages/ui/src/components/PluginHeader/PluginHeader.tsx +++ b/packages/ui/src/components/PluginHeader/PluginHeader.tsx @@ -129,9 +129,13 @@ export const PluginHeader = (props: PluginHeaderProps) => {
- +

{titleLink ? (