Summary
<TabBarItem> emits a plain <a href>. The SPA router only intercepts [data-stx-link], so every tap on a bottom tab is a full document load: the runtime reboots, every signal and store is discarded, and the screen flashes white. In the phone UI this is the primary navigation control, so the app's main interaction is its worst one.
Evidence
packages/components/src/ui/mobile/TabBarItem.stx:32
<a
href=""
class=""
data-stx-tab-bar-itemNo data-stx-link, and not <StxLink>. The router's rule (packages/router/src/client.ts:1847) is explicit: [data-stx-link] is an author saying "this is a link the router owns". Nothing else is intercepted.
CLAUDE.md states the rule this breaks:
<StxLink>instead of<a href>for every internal link. A plain<a href>triggers a full page reload — losing stores, scroll position, and any client-side state.
<TabBar> itself is otherwise carefully built — floating bar, safe-area handling, labelled nav landmark. The anchor is the one thing missed.
Impact
wildloop's three footer tabs. Every switch is a cold document load, which is the single largest reason the iOS build feels like a browser rather than an app.
Ask
<TabBarItem>emits<StxLink>(or an<a data-stx-link>) so a tab switch is a fragment swap rather than a page load.- Keep
aria-current="page"and the existing active styling. - A test that renders
<TabBar>with items and asserts every emitted anchor carriesdata-stx-link— the regression that would otherwise return unnoticed.
Note this is the floor, not the goal: a fragment swap still fetches before the view changes, whereas a phone app switches instantly and loads into the screen it already showed. That gap is a navigator concern and belongs in its own issue. This one stops the full reload.