# TabBar

> A mobile navigation bar for three to five top-level destinations.

Category: Navigation · Status: stable · Package: @bindshq/stance-react@0.1.1 · Docs: https://stanceui.com/components/tab-bar

Use TabBar for app-level navigation on small screens, usually pinned to the bottom with position="bottom" and hidden on larger screens with hideFrom. Each item is a link that changes the page, so TabBar uses navigation semantics and aria-current rather than the tabs pattern.

## Import

```tsx
import { TabBar, TabBarItem } from '@bindshq/stance-react';
```

Styles are imported once per app: `@bindshq/stance-tokens/css` and `@bindshq/stance-react/styles.css`.

## Examples

### Basic

```tsx
import { Icon, TabBar, TabBarItem } from '@bindshq/stance-react';

export function Basic() {
  return (
    <TabBar label="Main" style={{ maxWidth: 420 }}>
      <TabBarItem href="#home" icon={<Icon name="home" />} active>
        Home
      </TabBarItem>
      <TabBarItem href="#templates" icon={<Icon name="file-text" />}>
        Templates
      </TabBarItem>
      <TabBarItem href="#users" icon={<Icon name="users" />}>
        Users
      </TabBarItem>
      <TabBarItem href="#settings" icon={<Icon name="settings" />}>
        Settings
      </TabBarItem>
    </TabBar>
  );
}
```

### With a badge

Describe what the badge means with badgeLabel so it is announced.

```tsx
import { Icon, TabBar, TabBarItem } from '@bindshq/stance-react';

export function WithBadge() {
  return (
    <TabBar label="Main" style={{ maxWidth: 420 }}>
      <TabBarItem href="#home" icon={<Icon name="home" />}>
        Home
      </TabBarItem>
      <TabBarItem href="#inbox" icon={<Icon name="bell" />} badge={3} badgeLabel="3 unread" active>
        Activity
      </TabBarItem>
      <TabBarItem href="#account" icon={<Icon name="user" />}>
        Account
      </TabBarItem>
    </TabBar>
  );
}
```

### Icons only

Labels remain available to screen readers.

```tsx
import { Icon, TabBar, TabBarItem } from '@bindshq/stance-react';

export function IconsOnly() {
  return (
    <TabBar label="Main" labels="hidden" style={{ maxWidth: 320 }}>
      <TabBarItem href="#home" icon={<Icon name="home" />} active>
        Home
      </TabBarItem>
      <TabBarItem href="#search" icon={<Icon name="search" />}>
        Search
      </TabBarItem>
      <TabBarItem href="#account" icon={<Icon name="user" />}>
        Account
      </TabBarItem>
    </TabBar>
  );
}
```

### Top position

```tsx
import { Icon, TabBar, TabBarItem } from '@bindshq/stance-react';

export function TopPosition() {
  return (
    <TabBar label="Sections" position="top" style={{ maxWidth: 420 }}>
      <TabBarItem href="#overview" icon={<Icon name="layout-grid" />} active>
        Overview
      </TabBarItem>
      <TabBarItem href="#reports" icon={<Icon name="bar-chart" />}>
        Reports
      </TabBarItem>
      <TabBarItem href="#activity" icon={<Icon name="activity" />}>
        Activity
      </TabBarItem>
    </TabBar>
  );
}
```

## API reference

| Component | Prop | Type | Default | Description |
| --- | --- | --- | --- | --- |
| TabBar | `label` | `string` | `'Primary'` | Accessible name of the navigation landmark. |
| TabBar | `position` | `'static' \| 'top' \| 'bottom'` | `'static'` | bottom fixes the bar to the viewport (respecting the safe area); top makes it sticky. |
| TabBar | `hideFrom` | `'md' \| 'lg' \| 'never'` | `'never'` | Hide at and above this breakpoint. |
| TabBar | `labels` | `'visible' \| 'hidden'` | `'visible'` | Visually hide labels while keeping them accessible. |
| TabBarItem | `icon` (required) | `ReactNode` | None | Icon above the label. |
| TabBarItem | `active` | `boolean` | `false` | Marks the current destination with aria-current="page". |
| TabBarItem | `badge` | `ReactNode` | None | Count or dot on the icon. |
| TabBarItem | `badgeLabel` | `string` | None | Announced description of the badge, e.g. “3 unread”. |
| TabBarItem | `asChild` | `boolean` | `false` | Render your router link; its children become the label. |
| TabBarItem | `href` | `string` | None | Destination when not using asChild. |

## Accessibility

- A <nav> landmark containing a list of links; the current destination has aria-current="page".
- Touch targets are at least 56px tall, above the WCAG 2.2 minimum target size.
- When labels are hidden visually they still name each link for screen readers.
- Badges are decorative on the icon; badgeLabel provides the spoken equivalent.

## Keyboard

| Keys | Action |
| --- | --- |
| `Tab` | Moves between destinations. |
| `Enter` | Follows the link. |

## Guidelines

**Do**

- Limit to three to five destinations.
- Pair with a Sidebar on larger screens.

**Don’t**

- Use for actions such as “New”; use a FloatingActionButton.
- Switch content within a page; use Tabs.

## Related

- https://stanceui.com/components/sidebar
- https://stanceui.com/components/tabs
