Tabs: selecting a tab programmatically clicks the trigger, navigating away when triggers are links
Description
When Tabs.Root is controlled and its value changes programmatically, the tabs machine appears to dispatch a synthetic click on the trigger for the newly selected tab. If that trigger is rendered asChild onto an anchor the browser follows the anchor's href and performs a full page navigation that the application never asked for.
In a Next.js App Router app this breaks client-side routing entirely: router.push updates the URL, the tabs machine reacts to the new value by clicking the matching trigger, and the resulting document navigation supersedes the in-flight RSC navigation. Every tab navigation becomes a full page reload.
Link to Reproduction
<Tabs.Root value={lastPathSegment}>
<Tabs.List>
<Tabs.Trigger value="a" asChild><Link href="/a">A</Link></Tabs.Trigger>
<Tabs.Trigger value="b" asChild><Link href="/b">B</Link></Tabs.Trigger>
</Tabs.List>
</Tabs.Root>Steps to reproduce
Navigate from /a to /b programmatically (router.push('/b'), not by clicking).
A synthetic click fires on the /b anchor and the browser hard-navigates.
Observed via a capture-phase listener during a programmatic navigation:
{ "target": "A", "href": "/b", "isTrusted": false, "defaultPrevented": false }Expected: changing value should update selection state only; it should not
synthesise a click on the trigger. Or at least have this configurable in some way.
Chakra UI Version
3.37.0
Browser
No response
Operating System
- macOS
- Windows
- Linux
Additional Information
activationMode="manual"does not prevent it — this is a selection sync, not keyboard activation.- Nesting the link inside the trigger (no
asChild) does not help: the click is dispatched on the descendant anchor. - An
onClickhandler on the link never runs; it is dropped by the nestedasChildprop merge (Tabs.Trigger asChild→Text asChild→Link). The same merge appears to drop Next's own Link handler, which is why nothing callspreventDefault(). That prop-merge behaviour may be a second, related issue.
Source: chakra-ui/chakra-ui