> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cskn.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Screens and bars

> StackScreen, its bar buttons, search, toolbars and StackTabBar.

Each screen in a [`StackNavigator`](https://docs.cskn.dev/ui/stack/overview) is usually a `StackScreen`: a navigation bar on top and its own scroll area below. Each screen keeps its scroll position, so a list is where you left it when you come back.

```tsx theme={null}
import { StackScreen, StackBackButton, StackBarButton } from '@cskn/ui';

<StackScreen
  title="Groceries"
  subtitle="12 items"
  largeTitle
  left={<StackBackButton label="Lists" onPress={() => nav.back()} />}
  right={<StackBarButton label="Add item" onPress={addItem}><Icon name="plus" /></StackBarButton>}
  fab={{ label: 'Add item', onPress: addItem }}
  onRefresh={() => refetch()}
  tabBar
>
  <ItemList />
</StackScreen>
```

## StackScreen

**title** `string` *required*

The bar title.

**largeTitle** `boolean | ReactNode`

A large title that folds into the bar as content scrolls under it. Pass a node, such as a logo, to show that large while the bar still folds to `title`.

**subtitle** `ReactNode`

A quieter second line under the title: a count, a status.

**left** `ReactNode`

The bar's leading slot, usually a back or close button.

**right** `ReactNode`

The bar's trailing slot, usually `StackBarButton`s.

**tabBar** `boolean`

Leave room under the content for a `StackTabBar`.

**toolbar** `ReactNode`

A row of actions along the bottom, for a screen without a tab bar. An iOS toolbar (floating glass in the modern look) or Material's bottom app bar, with the screen's `fab` in it. Usually `StackBarButton`s.

**hero** `ReactNode`

A picture across the top that runs under the bar and status bar, like an album cover. Over it the bar is see-through with white buttons; once it scrolls away the normal bar returns. On iOS it stretches when pulled down.

**heroHeight** `number` (default: 300)

The hero's height in px.

**onRefresh** `() =\> Promise\<unknown\>`

Pull down to refresh; the spinner holds until the promise settles.

**fab** `\{ label, onPress, icon? \}`

A Material extended floating action button, on Android only; it folds to an icon on scroll. On iOS put the same action in the bar.

**search** `StackSearch`

A search field under the title. See [Search](#search).

**keyboardDismiss** `'none' | 'onDrag'` (default: 'none')

`onDrag` puts the keyboard away when the content is dragged.

**background** `string`

The screen's background. Grouped lists look best on one that differs from `surface`.

**scrollRef** `RefObject\<HTMLDivElement\>`

The screen's scroller.

When the keyboard opens, the screen leaves room for it and scrolls the focused field into view.

## Bar buttons

| Component | iOS | Android |
| - | - | - |
| `StackBackButton` `label` `onPress` | ‹ and the previous screen's title | ← icon |
| `StackCloseButton` `label` `onPress` | Grey circle with × | × icon |
| `StackBarButton` | Accent-colored text or icon | 48 dp icon button |

**onPress** `() =\> void`

Tap handler. Optional with `menu`.

**strong** `boolean`

The confirming action, such as Save or Done: bold on iOS, accent on Android. Keep its label short.

**menu** `ContextMenuItem[]`

A tap opens a menu instead: a pull-down under the button on iOS, Material's overflow menu on Android, a menu on desktop. Same items as [`ContextMenu`](https://docs.cskn.dev/ui/components/overlays#contextmenu).

**label** `string`

Accessible name. Required when the button shows only an icon.

**disabled** `boolean`

Greyed out.

```tsx theme={null}
<StackBarButton
  label="Sort"
  menu={[
    { label: 'Name', onPress: () => setSort('name') },
    { label: 'Date added', onPress: () => setSort('date') },
  ]}
>
  <Icon name="sliders" />
</StackBarButton>
```

A form in a sheet usually has Cancel on the left and a `strong` Save on the right.

## Search

```tsx theme={null}
const [query, setQuery] = useState('');

<StackScreen
  title="Books"
  largeTitle
  search={{ value: query, onChange: setQuery, placeholder: 'Search books', cancelLabel: 'Cancel' }}
>
  <BookList books={books.filter((b) => b.title.toLowerCase().includes(query.toLowerCase()))} />
</StackScreen>
```

The field sits under the title and scrolls with the content. Focusing it enters search mode: the bar and title make way and the field moves to the top, with Cancel beside it on iOS and a back arrow inside it on Android. You filter the content yourself. ⌘F / Ctrl+F focuses it and Esc leaves it.

Search is a history entry at the same depth, so Android's back leaves search rather than the screen, and coming back from a result keeps the search open.

**value / onChange** `string / (value) =\> void` *required*

The query.

**placeholder** `string` *required*

Field placeholder.

**cancelLabel** `string` *required*

iOS's Cancel button, and the accessible name of Android's back arrow.

**clearLabel** `string` (default: 'Clear')

Accessible name of the clear button.

**onSubmit** `() =\> void`

The keyboard's Search key.

**scopes / scope / onScopeChange** `\{ value, label \}[] / string / (value) =\> void`

A scope bar under the field while searching: a segmented control on iOS, filter chips on Android.

**suggestions / suggestionsTitle / onSuggestion** `\{ label, icon? \}[] / string / (label) =\> void`

Recent searches or suggestions shown while the query is empty. A tap makes one the query, or calls `onSuggestion`.

## StackTabBar

```tsx theme={null}
<StackTabBar
  items={[
    { key: 'home', label: 'Home', icon: 'home' },
    { key: 'inbox', label: 'Inbox', icon: 'mail', badge: unread },
  ]}
  minimizeOnScroll
  accessory={(placement) => <MiniPlayer compact={placement === 'inline'} />}
/>
```

A translucent bar with a hairline on iOS, a tonal Material bar with a pill behind the active icon on Android. Taps animate as each platform does; reduced motion turns the animations off.

**items** `\{ key, label, icon, badge? \}[]` *required*

The tabs. `icon` is an [icon name](https://docs.cskn.dev/ui/components/icons.md) or a node.

**value / onChange** `Tab / (key) =\> void`

Only needed outside a navigator with `tabs`; inside one the bar binds itself. `onChange` fires for every tap, including on the current tab.

**minimizeOnScroll** `boolean`

iOS 26 look: scrolling down shrinks the bar to a capsule with the current tab's icon. Other looks ignore it.

**search** `\{ label, onPress, active? \}`

A search tab: its own glass circle beside the bar in the iOS 26 look, the last tab elsewhere.

**accessory** `ReactNode | (placement) =\> ReactNode`

Something that stays above every tab, such as a mini player or an upload in progress. A glass capsule above the bar in the iOS 26 look, moving beside it when the bar shrinks (`placement` is then `'inline'`); a strip above the bar in other looks.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.