# Navigation and disclosure

Tabs, accordions, toolbars, location, pagination and progress steps.

## Quick start

After the [application setup](/docs/installation/#component-consumption), copy this component into your application. It imports only public packages; the complete live demo later on this page also uses documentation layout helpers.

```tsx
'use client';
import { Tabs } from '@fayegram-ai/faye-ui/navigation/tabs';
import { Accordion } from '@fayegram-ai/faye-ui/navigation/accordion';
import { Stack } from '@fayegram-ai/faye-ui/layout/layout';

export function PlaceNavigation() {
  return <Stack gap="4">
    <Tabs.Root defaultValue="overview"><Tabs.List aria-label="Place sections">
      <Tabs.Tab value="overview">Overview</Tabs.Tab><Tabs.Tab value="details">Details</Tabs.Tab>
    </Tabs.List>
      <Tabs.Panel value="overview">A quiet place by the water.</Tabs.Panel>
      <Tabs.Panel value="details">Open daily, with step-free access.</Tabs.Panel>
    </Tabs.Root>
    <Accordion.Root><Accordion.Item value="arrival">
      <Accordion.Header><Accordion.Trigger>How do I get there?</Accordion.Trigger></Accordion.Header>
      <Accordion.Panel>The station is a short walk away.</Accordion.Panel>
    </Accordion.Item></Accordion.Root>
  </Stack>;
}
```

API reference: [Tabs](/docs/api-navigation-tabs/), [Accordion](/docs/api-navigation-accordion/).

## Usage contract
Tabs choose panels; navigation links change location. Stepper reports progress but does not invent a workflow state machine. Pagination is one-based; table pagination is explicitly zero-based. Keep that distinction visible in application state. The pagination example uses siblings={0} and boundaries={0} at narrow widths, with first/last controls omitted and a visible total beside the current-page result. This keeps touch targets on one row. Applications choose the page window and breakpoint for their available space.

## Customization
Use semantic tokens for visual changes, public component parts for structural customization, and explicit props for instance behavior. The surrounding site lets you compare light and dark, different brands and density.

## Source and verification
The examples below import actual public package entries. Full source is downloadable. Source coverage does not establish keyboard, hydration or browser compatibility; those require the application test suite.

## Action geometry and mixed content

Default tabs, toolbar shells, accordion triggers and navigation actions use medium control height (36px comfortable, 32px compact). Explicit sm/md/lg variants use 32/36/44px comfortable and 28/32/36px compact. A toolbar includes its border in that outer height; child actions subtract the two border edges and use no block padding. It does not stack a full-sized padded button inside another padded box. Coarse-pointer actions remain at least 44px high and wide; the containing toolbar may therefore be 46px high. Long accordion labels and wrapped toolbars grow instead of clipping.

Actions use 13px text at sm and 14px at md/lg with tight control line-height, 8/8/12px horizontal inset, and a 4/6/8px icon-to-label gap. Tabs use adjacent padded targets instead of adding a separate 20px gap. Their indicator follows the selected tab in either direction and orientation. Horizontal tab lists scroll when needed; focus remains visible inside the target.

The examples compose public Icon with ordinary text spans. Toolbar.Button can also render a public Button without adding another vertical padding layer. Keyboard ownership stays with Base UI: disabled toolbar actions remain focusable by default, while tabs require Enter/Space to activate after arrow-key focus unless activateOnFocus is enabled.

Disabled Accordion and Collapsible triggers use the shared disabled opacity and unavailable cursor, without hover/press feedback. Enabling them restores normal interaction without changing their frame. Their keyboard and focus behavior remains owned by Base UI.

The `layout.toolbar` token remains available for application-owned toolbar bands and explicit root profiles. The inline Toolbar uses `control.sm/md/lg` at every size; `layout.toolbar` is now an explicitly documented authoring value. Existing profiles that set a larger root height remain intentional overrides.

## Pagination and location controls

`Pagination` uses one-based controlled state. `siblings` controls the pages around the current page; `boundaries` controls each end. `showFirst`/`showLast` add jump actions, `hidePrevious`/`hideNext` remove adjacent actions, and the four icon/label props customize those controls. A zero `count` renders no page choices and disables navigation. Table pagination remains zero-based and supports unknown totals and all-rows mode.

`Breadcrumbs.separator` accepts text or an icon, which remains decorative. An item with `href` remains a real link, including the current item; the last item carries `aria-current="page"`. Condensed breadcrumb menus can be supplied as item labels using the public Menu parts; an automatic collapse policy is not built in.

## Accordion surfaces and indicators

Accordion triggers include an animated chevron at the logical end by default. Item `variants={{variant:'divided'}}`, `plain` and `outlined` control the surface boundary. `indicatorPosition="start"` moves the trigger indicator to the logical start; `indicator` replaces its artwork and `hideIndicator` removes it. Chevron rotation, panel size transitions, hover/press reactions and reduced motion remain available in each style. Expanded state does not add a selected frame; keyboard focus uses a single inset ring.

## Executable example source

```tsx
'use client';
import { LayoutGrid, Activity, Settings, Undo2, Redo2, Palette, Compass } from '@lucide/icons';
import { useState } from 'react';
import { useMediaQuery } from '@fayegram-ai/faye-ui/hooks';
import { Tabs } from '@fayegram-ai/faye-ui/navigation/tabs';
import { Accordion } from '@fayegram-ai/faye-ui/navigation/accordion';
import { Collapsible } from '@fayegram-ai/faye-ui/navigation/collapsible';
import { Toolbar } from '@fayegram-ai/faye-ui/navigation/toolbar';
import { NavigationMenu } from '@fayegram-ai/faye-ui/navigation/navigation-menu';
import { Breadcrumbs } from '@fayegram-ai/faye-ui/navigation/breadcrumbs';
import { Pagination } from '@fayegram-ai/faye-ui/navigation/pagination';
import { Stepper } from '@fayegram-ai/faye-ui/navigation/stepper';
import { Icon } from '@fayegram-ai/faye-ui/core/icon';
import { Button } from '@fayegram-ai/faye-ui/controls/button';
import { Section, Result } from '../example';
export default function Navigation() {
    const compact=useMediaQuery('(max-width:40rem)');
    const [page, setPage] = useState(1), [message, setMessage] = useState('Ready');
    return <><Section title="Accordion surfaces and indicators"><Accordion.Root>{(['divided','plain','outlined'] as const).map(variant=><Accordion.Item key={variant} value={variant} variants={{variant}}><Accordion.Header><Accordion.Trigger>{variant} with trailing chevron</Accordion.Trigger></Accordion.Header><Accordion.Panel>The end indicator rotates smoothly on open and close. Keyboard focus stays inside the trigger.</Accordion.Panel></Accordion.Item>)}<Accordion.Item value="leading" variants={{variant:'outlined'}}><Accordion.Header><Accordion.Trigger indicatorPosition="start">Optional leading indicator</Accordion.Trigger></Accordion.Header><Accordion.Panel>Indicator placement follows the writing direction. Custom artwork and hiding the indicator are also supported.</Accordion.Panel></Accordion.Item></Accordion.Root></Section><Section title="Tabs"><Tabs.Root defaultValue="overview"><Tabs.List aria-label="Project sections"><Tabs.Tab value="overview"><Icon icon={LayoutGrid} size="sm"/><span>Overview</span></Tabs.Tab><Tabs.Tab value="activity"><Icon icon={Activity} size="sm"/><span>Activity</span></Tabs.Tab><Tabs.Tab value="settings"><Icon icon={Settings} size="sm"/><span>Settings</span></Tabs.Tab><Tabs.Indicator /></Tabs.List><Tabs.Panel value="overview">Project summary with stable panel identity.</Tabs.Panel><Tabs.Panel value="activity">A locally rendered activity panel.</Tabs.Panel><Tabs.Panel value="settings">Workspace preferences.</Tabs.Panel></Tabs.Root></Section><Section title="Accordion and disclosure"><Accordion.Root><Accordion.Item value="tokens"><Accordion.Header><Accordion.Trigger>Why semantic tokens?</Accordion.Trigger></Accordion.Header><Accordion.Panel>They preserve meaning across color schemes and brands.</Accordion.Panel></Accordion.Item><Accordion.Item value="extensions"><Accordion.Header><Accordion.Trigger>Where do data engines live?</Accordion.Trigger></Accordion.Header><Accordion.Panel>In optional packages, never the core dependency graph.</Accordion.Panel></Accordion.Item></Accordion.Root><Collapsible.Root><Collapsible.Trigger render={<Button />}>Show implementation note</Collapsible.Trigger><Collapsible.Panel>Disclosure owns its state; motion respects reduced-motion preferences.</Collapsible.Panel></Collapsible.Root></Section><Section title="Toolbar and navigation menu"><Toolbar.Root aria-label="Document tools"><Toolbar.Group><Toolbar.Button onClick={() => setMessage('Undo selected')}><Icon icon={Undo2} size="sm"/><span>Undo</span></Toolbar.Button><Toolbar.Button onClick={() => setMessage('Redo selected')}><Icon icon={Redo2} size="sm"/><span>Redo</span></Toolbar.Button></Toolbar.Group><Toolbar.Separator /><Toolbar.Link href="/docs/theming/"><Icon icon={Palette} size="sm"/><span>Theming</span></Toolbar.Link><Toolbar.Input aria-label="Toolbar search" placeholder="Find in document"/></Toolbar.Root><NavigationMenu.Root><NavigationMenu.List><NavigationMenu.Item><NavigationMenu.Trigger><Icon icon={Compass} size="sm"/><span>Explore</span></NavigationMenu.Trigger><NavigationMenu.Content><NavigationMenu.Link href="/docs/theming/">Theme system</NavigationMenu.Link><NavigationMenu.Link href="/docs/layout/">Layout primitives</NavigationMenu.Link></NavigationMenu.Content></NavigationMenu.Item></NavigationMenu.List><NavigationMenu.Portal><NavigationMenu.Positioner><NavigationMenu.Popup><NavigationMenu.Arrow/><NavigationMenu.Viewport /></NavigationMenu.Popup></NavigationMenu.Positioner></NavigationMenu.Portal></NavigationMenu.Root><Result>{message}</Result></Section><Section title="Location and progress"><Breadcrumbs items={[{ label: 'Documentation', href: '/docs/overview/' }, { label: 'Navigation' }]} /><Stepper steps={[{ key: 'details', label: 'Details', status: 'complete' }, { key: 'review', label: 'Review', status: 'current' }, { key: 'publish', label: 'Publish' }]}/><Pagination showFirst={!compact} showLast={!compact} siblings={compact?0:1} boundaries={compact?0:2} page={page} count={12} onPageChange={setPage}/><Result>Page {page} of 12</Result></Section></>;
}
```
