feat(ui): add automatic active tab detection to Header#33783
Conversation
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>
|
Important This PR includes changes that affect public-facing API. Please ensure you are adding/updating documentation for new features or behavior. Changed Packages
|
🎨 Visual Testing with Chromatic
|
There was a problem hiding this comment.
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
activeTabIdisundefined(omitted) and a Router is present. - Expand
activeTabIdto supportstring | null, wherenullmeans “no active tab”. - Refactor
HeaderNavLinkto 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. |
| readonly root: 'bui-HeaderNavItem'; | ||
| }; | ||
| readonly analytics: true; | ||
| readonly resolveHref: true; |
There was a problem hiding this comment.
Is setting this a breaking change?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
Signed-off-by: Johan Persson <johanopersson@gmail.com>
1d348ba to
7608af5
Compare
|
Thank you for contributing to Backstage! The changes in this pull request will be part of the |
Hey, I just made a Pull Request!
When
activeTabIdis omitted,HeaderNavnow auto-detects the activetab from the current route using
matchRoutes. This eliminates theboilerplate
useActiveTabIdpattern that every consumer had toreimplement.
The
activeTabIdprop accepts three states:undefined(omitted) — auto-detect from current routestring— explicit tab ID (existing behavior, unchanged)null— explicitly no active tabAlso refactors
HeaderNavLinkto properly use the definition system(
resolveHref,analytics) and resolves relative tab hrefs correctly.✔️ Checklist
Signed-off-byline in the message.