Lynx/Modules/Navigation/TabBar
@sigx/lynx-navigation · Stable · Component library

TabBar#

The headless default chrome for a Tabs navigator — unstyled buttons with full accessibility wiring (label, element, trait, status, an opacity active marker and tap-to-switch), or a fully custom bar via renderTab.

Import#

TSX
import { TabBar } from '@sigx/lynx-navigation';

Basic usage#

Mount <TabBar /> as a child of <Tabs>. It reads each <Tabs.Screen>'s metadata (name, label, icon, accessibilityLabel) and renders one button per tab, switching the active tab on tap. Tab bodies stay mounted (inactive ones are display:none), so per-tab state survives switching.

TSX
import { Tabs, TabBar, Stack, Header } from '@sigx/lynx-navigation';

export const Main = () => (
    <Tabs initialTab="trips">
        <Tabs.Screen name="trips" label="Trips">
            <Stack initialRoute="tripsHome">
                <Header />
            </Stack>
        </Tabs.Screen>
        <Tabs.Screen name="account" label="Account">
            <Stack initialRoute="accountHome">
                <Header />
            </Stack>
        </Tabs.Screen>
        <TabBar />
    </Tabs>
);

TabBar is intentionally unstyled — it provides behavior and accessibility, not theming. For a themed bar use NavTabBar from @sigx/lynx-daisyui.

Custom rendering with renderTab#

Pass renderTab to fully override per-item rendering. It receives the tab's TabInfo (its name, label, icon and accessibilityLabel) plus a TabRenderContext with active (whether this tab is the selected one) and onPress() (call it to switch to this tab):

TSX
import { Tabs, TabBar } from '@sigx/lynx-navigation';

export const Main = () => (
    <Tabs initialTab="trips">
        {/* …Tabs.Screen children… */}
        <TabBar
            renderTab={(info, ctx) => (
                <view bindtap={ctx.onPress} style={{ opacity: ctx.active ? 1 : 0.5 }}>
                    <text>{info.label ?? info.name}</text>
                </view>
            )}
        />
    </Tabs>
);

To read or drive the active tab from elsewhere, use useTabs(){ active, setActive(name), tabs }. setActive ignores unknown tab names (no-op).

Props#

PropTypeDescription
renderTab(info: TabInfo, ctx: TabRenderContext) => JSXElementFully overrides per-item rendering. Called once per tab; receives the tab's TabInfo and a TabRenderContext (active, onPress()). When omitted, TabBar renders its default headless buttons.

Types#

TypeShapeDescription
TabInfo{ readonly name: string; readonly icon?: IconSpec | JSXElement; readonly label?: string; readonly accessibilityLabel?: string }Metadata for a single tab, sourced from its <Tabs.Screen>.
TabRenderContext{ readonly active: boolean; onPress(): void }The render context passed to renderTab for each item — active marks the selected tab; onPress() switches to it.

See also#

  • Tabs — the persistent tab navigator that hosts TabBar and Tabs.Screen.
  • Screen.TabBarItem — a scoped tab-bar item slot for custom renderTab consumers.
  • Usage — tabs with per-tab stacks, modals and persistence.
  • API reference — every export, signature and type.