From 1bb69243494d1ac4edbaf3e107a8e4861a7d184a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Thu, 25 Sep 2025 17:11:34 +0200 Subject: [PATCH 1/7] fix: remove default selection of tab for tabs that have href defined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .../ui/src/components/Tabs/Tabs.stories.tsx | 57 +++++++++++++++++++ packages/ui/src/components/Tabs/Tabs.tsx | 15 ++++- 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/packages/ui/src/components/Tabs/Tabs.stories.tsx b/packages/ui/src/components/Tabs/Tabs.stories.tsx index cbfe3d8562..c818d0fe4b 100644 --- a/packages/ui/src/components/Tabs/Tabs.stories.tsx +++ b/packages/ui/src/components/Tabs/Tabs.stories.tsx @@ -455,3 +455,60 @@ export const RootPathMatching: Story = { ), }; + +export const AutoSelectionOfTabs: Story = { + args: { + children: '', + }, + render: () => ( + +
+ + Current URL: /random-page + + + {/* Without hrefs */} + + {' '} + Case 1: Without hrefs + + + + Settings + Preferences + Advanced + + + Settings content - React Aria manages this selection + + + Preferences content - works normally + + + Advanced content - local state only + + + + {/* With hrefs */} + + {' '} + Case 2: With hrefs By default no selection is shown + because the URL doesn't match any tab's href.{' '} + + + + + Catalog + + + Create + + + Docs + + + +
+
+ ), +}; diff --git a/packages/ui/src/components/Tabs/Tabs.tsx b/packages/ui/src/components/Tabs/Tabs.tsx index dacb355fc9..371de4ef41 100644 --- a/packages/ui/src/components/Tabs/Tabs.tsx +++ b/packages/ui/src/components/Tabs/Tabs.tsx @@ -115,9 +115,22 @@ export const Tabs = (props: TabsProps) => { } } } + + //No route matches - check if all tabs have hrefs (pure navigation) + const allTabsHaveHref = tabListChildren.every( + child => isValidElement(child) && child.props.href, + ); + + if (allTabsHaveHref) { + // Pure navigation tabs, no route match + return null; + } else { + // Mixed tabs or pure local state + return undefined; + } } } - return null; + return undefined; })(); if (!children) return null; From 82540078e800ebeb26d6d0f751b67019ee682b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Mon, 29 Sep 2025 10:00:18 +0200 Subject: [PATCH 2/7] chore: update package.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index b510a5a864..babce203dd 100644 --- a/package.json +++ b/package.json @@ -105,6 +105,7 @@ "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "@yarnpkg/plugin-npm@npm:^3.1.0": "patch:@yarnpkg/plugin-npm@npm%3A3.1.0#~/.yarn/patches/@yarnpkg-plugin-npm-npm-3.1.0-6533d0f5a1.patch", + "GendocuPublicApis": "npm:gendocu-public-apis@^1.0.0", "ast-types@0.14.2": "patch:ast-types@npm%3A0.14.2#./.yarn/patches/ast-types-npm-0.14.2-43c4ac4b0d.patch", "ast-types@^0.14.1": "patch:ast-types@npm%3A0.14.2#./.yarn/patches/ast-types-npm-0.14.2-43c4ac4b0d.patch", "ast-types@npm:0.14.2": "patch:ast-types@npm%3A0.16.1#./.yarn/patches/ast-types-npm-0.16.1-43c4ac4b0d.patch", From 97818157bba7038533d9805f16ad38ab47a1887b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Fri, 3 Oct 2025 16:39:03 +0200 Subject: [PATCH 3/7] add changeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .changeset/thin-hoops-bathe.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/thin-hoops-bathe.md diff --git a/.changeset/thin-hoops-bathe.md b/.changeset/thin-hoops-bathe.md new file mode 100644 index 0000000000..508d548431 --- /dev/null +++ b/.changeset/thin-hoops-bathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/ui': patch +--- + +Remove auto selection of tabs for tabs that all have href defined From edc15d8cd738bf9479dd382f9325ea1fe4b654b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Fri, 3 Oct 2025 16:50:39 +0200 Subject: [PATCH 4/7] Revert "chore: update package.json" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 82540078e800ebeb26d6d0f751b67019ee682b07. Signed-off-by: Sofia Sjöblad --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index babce203dd..b510a5a864 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,6 @@ "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "@yarnpkg/plugin-npm@npm:^3.1.0": "patch:@yarnpkg/plugin-npm@npm%3A3.1.0#~/.yarn/patches/@yarnpkg-plugin-npm-npm-3.1.0-6533d0f5a1.patch", - "GendocuPublicApis": "npm:gendocu-public-apis@^1.0.0", "ast-types@0.14.2": "patch:ast-types@npm%3A0.14.2#./.yarn/patches/ast-types-npm-0.14.2-43c4ac4b0d.patch", "ast-types@^0.14.1": "patch:ast-types@npm%3A0.14.2#./.yarn/patches/ast-types-npm-0.14.2-43c4ac4b0d.patch", "ast-types@npm:0.14.2": "patch:ast-types@npm%3A0.16.1#./.yarn/patches/ast-types-npm-0.16.1-43c4ac4b0d.patch", From 67cf9829946b301952ec74a467578b71364e285b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Mon, 6 Oct 2025 10:54:20 +0200 Subject: [PATCH 5/7] fix: update stories to comply with react-aria MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .../HeaderPage/HeaderPage.stories.tsx | 32 +++++++++++++---- .../ui/src/components/Tabs/Tabs.stories.tsx | 36 ++++++++++++++++--- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx index c4849ddc20..c3c2b59ae1 100644 --- a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx +++ b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx @@ -44,22 +44,27 @@ const tabs: HeaderTab[] = [ { id: 'overview', label: 'Overview', + href: '/overview', }, { id: 'checks', label: 'Checks', + href: '/checks', }, { id: 'tracks', label: 'Tracks', + href: '/tracks', }, { id: 'campaigns', label: 'Campaigns', + href: '/campaigns', }, { id: 'integrations', label: 'Integrations', + href: '/integrations', }, ]; @@ -89,10 +94,19 @@ const withRouter = (Story: StoryFn) => ( ); +// White background decorator for stories +const withWhiteBackground = (Story: StoryFn) => ( +
+ +
+); + // Extract layout decorator as a reusable constant const layoutDecorator = [ (Story: StoryFn) => ( - <> +
- +
), ]; @@ -129,6 +143,7 @@ export const Default: Story = { args: { title: 'Page Title', }, + decorators: [withWhiteBackground], }; export const WithTabs: Story = { @@ -136,11 +151,11 @@ export const WithTabs: Story = { ...Default.args, tabs, }, - decorators: [withRouter], + decorators: [withRouter, withWhiteBackground], }; export const WithCustomActions: Story = { - decorators: [withRouter], + decorators: [withRouter, withWhiteBackground], render: () => ( ( ( ); +// White background decorator for stories +const withWhiteBackground = (Story: StoryFn) => ( +
+ +
+); + export const Default: Story = { args: { children: '', }, - decorators: [withRouter], + decorators: [withRouter, withWhiteBackground], render: () => ( - Tab 1 - Tab 2 - Tab 3 With long title + + Tab 1 + + + Tab 2 + + + Tab 3 With long title + ), @@ -54,7 +69,7 @@ export const WithTabPanels: Story = { args: { children: '', }, - decorators: [withRouter], + decorators: [withRouter, withWhiteBackground], render: () => ( @@ -79,6 +94,7 @@ export const WithMockedURLTab2: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -111,6 +127,7 @@ export const WithMockedURLTab3: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -143,6 +160,7 @@ export const WithMockedURLNoMatch: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -181,6 +199,7 @@ export const ExactMatchingDefault: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -217,6 +236,7 @@ export const PrefixMatchingForNestedRoutes: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -257,6 +277,7 @@ export const PrefixMatchingDeepNesting: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -292,6 +313,7 @@ export const MixedMatchingStrategies: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -343,6 +365,7 @@ export const PrefixMatchingEdgeCases: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -385,6 +408,7 @@ export const PrefixMatchingWithSlash: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -426,6 +450,7 @@ export const RootPathMatching: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -460,6 +485,7 @@ export const AutoSelectionOfTabs: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => (
From 23d8df0ce0534026e5e913576724faa68f74a4fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Mon, 6 Oct 2025 11:31:35 +0200 Subject: [PATCH 6/7] fix: add react-aria label to button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .../ui/src/components/HeaderPage/HeaderPage.stories.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx index c3c2b59ae1..bba6e8a857 100644 --- a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx +++ b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx @@ -163,7 +163,11 @@ export const WithCustomActions: Story = { <> - } /> + } + aria-label="More options" + /> {menuItems.map(option => ( Date: Tue, 7 Oct 2025 09:48:51 +0200 Subject: [PATCH 7/7] Revert "fix: update stories to comply with react-aria" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 67cf9829946b301952ec74a467578b71364e285b. Signed-off-by: Sofia Sjöblad --- .../HeaderPage/HeaderPage.stories.tsx | 32 ++++------------- .../ui/src/components/Tabs/Tabs.stories.tsx | 36 +++---------------- 2 files changed, 12 insertions(+), 56 deletions(-) diff --git a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx index bba6e8a857..9e6e63ddf5 100644 --- a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx +++ b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx @@ -44,27 +44,22 @@ const tabs: HeaderTab[] = [ { id: 'overview', label: 'Overview', - href: '/overview', }, { id: 'checks', label: 'Checks', - href: '/checks', }, { id: 'tracks', label: 'Tracks', - href: '/tracks', }, { id: 'campaigns', label: 'Campaigns', - href: '/campaigns', }, { id: 'integrations', label: 'Integrations', - href: '/integrations', }, ]; @@ -94,19 +89,10 @@ const withRouter = (Story: StoryFn) => ( ); -// White background decorator for stories -const withWhiteBackground = (Story: StoryFn) => ( -
- -
-); - // Extract layout decorator as a reusable constant const layoutDecorator = [ (Story: StoryFn) => ( -
+ <>
-
+ ), ]; @@ -143,7 +129,6 @@ export const Default: Story = { args: { title: 'Page Title', }, - decorators: [withWhiteBackground], }; export const WithTabs: Story = { @@ -151,11 +136,11 @@ export const WithTabs: Story = { ...Default.args, tabs, }, - decorators: [withRouter, withWhiteBackground], + decorators: [withRouter], }; export const WithCustomActions: Story = { - decorators: [withRouter, withWhiteBackground], + decorators: [withRouter], render: () => ( ( ( ); -// White background decorator for stories -const withWhiteBackground = (Story: StoryFn) => ( -
- -
-); - export const Default: Story = { args: { children: '', }, - decorators: [withRouter, withWhiteBackground], + decorators: [withRouter], render: () => ( - - Tab 1 - - - Tab 2 - - - Tab 3 With long title - + Tab 1 + Tab 2 + Tab 3 With long title ), @@ -69,7 +54,7 @@ export const WithTabPanels: Story = { args: { children: '', }, - decorators: [withRouter, withWhiteBackground], + decorators: [withRouter], render: () => ( @@ -94,7 +79,6 @@ export const WithMockedURLTab2: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -127,7 +111,6 @@ export const WithMockedURLTab3: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -160,7 +143,6 @@ export const WithMockedURLNoMatch: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -199,7 +181,6 @@ export const ExactMatchingDefault: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -236,7 +217,6 @@ export const PrefixMatchingForNestedRoutes: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -277,7 +257,6 @@ export const PrefixMatchingDeepNesting: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -313,7 +292,6 @@ export const MixedMatchingStrategies: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -365,7 +343,6 @@ export const PrefixMatchingEdgeCases: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -408,7 +385,6 @@ export const PrefixMatchingWithSlash: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -450,7 +426,6 @@ export const RootPathMatching: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -485,7 +460,6 @@ export const AutoSelectionOfTabs: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => (