Skip to content

feat(ui): add automatic active tab detection to Header#33783

Merged
Naycon merged 8 commits intomasterfrom
bui-header-nav-add-active-tab-matching
Apr 7, 2026
Merged

feat(ui): add automatic active tab detection to Header#33783
Naycon merged 8 commits intomasterfrom
bui-header-nav-add-active-tab-matching

Conversation

@Naycon
Copy link
Copy Markdown
Collaborator

@Naycon Naycon commented Apr 7, 2026

Hey, I just made a Pull Request!

When activeTabId is omitted, HeaderNav now auto-detects the active
tab from the current route using matchRoutes. This eliminates the
boilerplate useActiveTabId pattern that every consumer had to
reimplement.

The activeTabId prop accepts three states:

  • undefined (omitted) — auto-detect from current route
  • string — explicit tab ID (existing behavior, unchanged)
  • null — explicitly no active tab

Also refactors HeaderNavLink to properly use the definition system
(resolveHref, analytics) and resolves relative tab hrefs correctly.

✔️ Checklist

  • A changeset describing the change and affected packages.
  • Added or updated documentation
  • Tests for new functionality and regression tests for bug fixes
  • Screenshots attached (for UI changes)
  • All your commits have a Signed-off-by line in the message.

Naycon added 7 commits March 31, 2026 15:09
Signed-off-by: Johan Persson <johanopersson@gmail.com>
Signed-off-by: Johan Persson <johanopersson@gmail.com>
…licit activeTabId

Signed-off-by: Johan Persson <johanopersson@gmail.com>
… recipe

Signed-off-by: Johan Persson <johanopersson@gmail.com>
Signed-off-by: Johan Persson <johanopersson@gmail.com>
Signed-off-by: Johan Persson <johanopersson@gmail.com>
Add resolveHref to HeaderNavItemDefinition so tab links with relative
hrefs are resolved against the router context before rendering.

Signed-off-by: Johan Persson <johanopersson@gmail.com>
@Naycon Naycon requested a review from a team as a code owner April 7, 2026 09:02
Copilot AI review requested due to automatic review settings April 7, 2026 09:02
@backstage-goalie
Copy link
Copy Markdown
Contributor

backstage-goalie Bot commented Apr 7, 2026

Important

This PR includes changes that affect public-facing API. Please ensure you are adding/updating documentation for new features or behavior.

Changed Packages

Package Name Package Path Changeset Bump Current Version
@backstage/ui packages/ui minor v0.14.0-next.1

@backstage-goalie backstage-goalie Bot added size:medium Medium-sized pull requests receive no change in priority for reviews. waiting-for:review The PR needs a review and will be visible in the review queue unless already assigned an owner. labels Apr 7, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

🎨 Visual Testing with Chromatic

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates HeaderNav to support automatic active-tab detection from the current React Router location when activeTabId is omitted, while also allowing null to explicitly opt out of an active tab. It also aligns HeaderNavLink with the definition system for href resolution and analytics.

Changes:

  • Add router-based active tab auto-detection when activeTabId is undefined (omitted) and a Router is present.
  • Expand activeTabId to support string | null, where null means “no active tab”.
  • Refactor HeaderNavLink to use the definition system (resolveHref, analytics) and update stories/docs accordingly.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/ui/src/components/Header/HeaderNav.tsx Adds auto-detection via matchRoutes, refactors link rendering to use definition-based href resolution and analytics.
packages/ui/src/components/Header/types.ts Updates activeTabId type to string | null and introduces internal HeaderNavLinkProps.
packages/ui/src/components/Header/HeaderNavDefinition.ts Moves analytics + resolveHref to the item definition and expands item prop defs.
packages/ui/src/components/Header/Header.stories.tsx Simplifies stories to rely on auto-detection; adds explicit active tab story.
packages/ui/src/recipes/PluginHeaderAndHeader.stories.tsx Removes local active-tab hook and configures router entries to demonstrate auto-detection.
docs-ui/src/app/components/header/page.mdx Updates docs text to describe the new activeTabId behavior.
docs-ui/src/app/components/header/props-definition.tsx Updates prop documentation to reflect null and omission semantics.
docs-ui/src/app/components/header/components.tsx Sets MemoryRouter initial entries so examples render with a deterministic active tab.
packages/ui/report.api.md Updates extracted API report to reflect definition/type changes.
.changeset/cold-ways-double.md Adds a changeset documenting the behavior change.

Comment thread packages/ui/src/components/Header/HeaderNav.tsx
Comment thread packages/ui/report.api.md
readonly root: 'bui-HeaderNavItem';
};
readonly analytics: true;
readonly resolveHref: true;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is setting this a breaking change?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, maybe it depends on how you reason about it? 🤔 It's breaking in that it changes the behavior, but the previous behavior was broken and not following any reasonable patterns. But yes, can mark it as a breaking change just in case someone relied on it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking more generally actually, what is the impact on behavior from setting or clearing this, should we consider both to be breaking, neither, or just one direction? Not blocking this PR btw, just realized it's something that's useful to settle

@backstage-goalie backstage-goalie Bot added waiting-for:merge The PR has been approved and is awaiting merge. and removed waiting-for:review The PR needs a review and will be visible in the review queue unless already assigned an owner. labels Apr 7, 2026
Signed-off-by: Johan Persson <johanopersson@gmail.com>
Copilot AI review requested due to automatic review settings April 7, 2026 13:11
@Naycon Naycon force-pushed the bui-header-nav-add-active-tab-matching branch from 1d348ba to 7608af5 Compare April 7, 2026 13:11
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Comment thread packages/ui/src/components/Header/HeaderNavDefinition.ts
Comment thread docs-ui/src/app/components/header/props-definition.tsx
@Naycon Naycon merged commit b4a1875 into master Apr 7, 2026
32 checks passed
@Naycon Naycon deleted the bui-header-nav-add-active-tab-matching branch April 7, 2026 15:22
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

Thank you for contributing to Backstage! The changes in this pull request will be part of the 1.50.0 release, scheduled for Tue, 14 Apr 2026.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:medium Medium-sized pull requests receive no change in priority for reviews. waiting-for:merge The PR has been approved and is awaiting merge.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants