---
title: "Jetpack Compose floating toolbars for PDF viewer | Nutrient Android SDK"
canonical_url: "https://www.nutrient.io/guides/android/jetpack-compose/components/floating-toolbars/"
md_url: "https://www.nutrient.io/guides/android/jetpack-compose/components/floating-toolbars.md"
last_updated: "2026-10-12T10:12:58.189Z"
description: "Render the Nutrient toolbars as Material 3 Expressive floating pills with NutrientFloatingToolbar and NutrientFloatingContextualToolbar: docking to any edge, collapsing, building blocks, and the status bar scrim."
---

# Floating toolbars

`NutrientFloatingToolbar` renders the main toolbar’s items as a [Material 3 Expressive floating toolbar](https://m3.material.io/components/toolbars/overview). The user can drag this pill to any edge of the window. The pill lays out horizontally at the top or bottom and vertically at a side, and it moves with spring animation. `NutrientFloatingContextualToolbar` does the same for the contextual toolbar that’s currently shown. Both read from the [`ToolbarCoordinator`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.compose.toolbar.adapter/-toolbar-coordinator/index.html), so the items, their state, and the SDK’s handling of taps are identical to the docked bars.

Use them in a Compose host that draws its own chrome around `DocumentView`. They’re alternatives to the docked [`NutrientMainToolbar`](https://www.nutrient.io/guides/android/jetpack-compose/components/main-toolbar/) and [`NutrientContextualToolbar`](https://www.nutrient.io/guides/android/jetpack-compose/components/contextual-toolbar/), not replacements. The toolbars that the SDK mounts itself stay docked.

## Basic usage

Turn off both of the SDK’s toolbars and compose the pills over the document:

```kotlin

val configuration = PdfActivityConfiguration.Builder(context).defaultToolbarEnabled(false).defaultContextualToolbarEnabled(false).build()
val documentState = rememberDocumentState(uri, configuration)
val coordinator by documentState.toolbarCoordinator.collectAsState()

Box(Modifier.fillMaxSize()) {
    DocumentView(documentState = documentState, modifier = Modifier.fillMaxSize())
    coordinator?.let { c ->
        NutrientFloatingToolbar(coordinator = c)
        NutrientFloatingContextualToolbar(coordinator = c)
    }
}

```

The main pill starts docked at the bottom. It follows the viewer’s user interface visibility, so it slides away in immersive mode. The contextual pill appears when the user enters a mode and disappears when the user leaves it. The Catalog app’s `MainToolbarFloatingExample` shows both.

## Where the pill docks

A `FloatingToolbarState` holds the pill’s current `edge`. Its `allowedEdges` limit where the user can drop the pill after a drag. Create it with `rememberFloatingToolbarState`, which keeps the state through configuration changes and process death:

```kotlin

val state = rememberFloatingToolbarState(
    initialEdge = FloatingToolbarEdge.Bottom,
    allowedEdges = setOf(FloatingToolbarEdge.Top, FloatingToolbarEdge.Bottom), // never a side rail.
)
NutrientFloatingToolbar(coordinator = c, state = state)

// Move it yourself:
state.dockTo(FloatingToolbarEdge.Top)

```

`FloatingToolbarEdge` is `Top`, `Bottom`, `Start`, or `End`. `Start` and `End` are logical edges, so they swap sides in a right-to-left layout. `state.isDragging` and `state.previewedEdge` report a drag in progress, so other chrome can react to it. Pass `draggable = false` to pin the pill in place.

The contextual pill also follows the bar’s allowed docks and close button placement. A bar that the SDK restricts to the top therefore never becomes a side rail.

## Collapsing

With `collapsible = true`, the main pill shrinks to its active item after a tap and expands again on the next tap:

```kotlin

NutrientFloatingToolbar(coordinator = c, state = state, collapsible = true)

state.collapse()
state.expand()
state.isExpanded   // observe.
state.activeItemId // the item the collapsed pill shows.

```

## Appearance

The pill takes its colors from the Material 3 floating toolbar color roles of the host’s `MaterialTheme`. With `vibrant = true` (the default), the pill uses `primaryContainer` with vibrant icon button colors. With `vibrant = false`, it uses the standard variant on `surfaceContainer`. The roles tint the icons, so a tint baked into a `ToolbarIcon.Resource` or `ToolbarIcon.Vector` is ignored. `ToolbarIcon.Composed` content renders as is. A selected item, such as the item of an open outline or an active tool, renders with a filled `primary` container. Items declared with `OverflowBehavior.Never` stay in the pill’s overflow menu, and items that don’t fit follow them there.

While inline search is active, the pill hides, and a full-width search pill springs in at the top edge. The search pill takes its colors from the ambient Material 3 color scheme.

The pill reads `windowInsets` (default `WindowInsets.safeDrawing`) to stay clear of the system bars and the display cutout on whichever edge it docks to.

## Building your own pill

The SDK’s pills are built from public components. A host that wants to arrange the same items differently can use them directly:

- `NutrientFloatingToolbarItemButton(item, vibrant, edge, onAction)` renders one item as a Material 3 icon button with the selected fill. It also adds a submenu dropdown for a `ToolbarItem.Submenu` and a tooltip that opens away from `edge`.

- `NutrientFloatingToolbarMenuItem(item, onClick)` renders an item as a row in a dropdown menu, such as an overflow menu.

- `NutrientFloatingToolbarSearchTheme { … }` provides the Material-derived colors that the SDK’s inline search bar uses inside a pill. A `NutrientToolbarSearchBar(coordinator)` composed inside it then matches the pill.

```kotlin

val items by c.items.collectAsState()
Row {
    items.visible.forEach { item ->
        NutrientFloatingToolbarItemButton(item = item, edge = FloatingToolbarEdge.Bottom, onAction = c::dispatch)
    }
}

```

Dispatching the action back to the coordinator is what makes the SDK handle the tap. The Catalog app’s `MainToolbarFabMenuExample` uses these pieces to build a Material 3 Expressive floating action button (FAB) menu. The collapsed FAB shows the active item. Tapping it expands a labeled list of actions, and a long press drags it between the bottom corners.

## Status bar scrim

A floating pill sits below the status bar. Unlike the SDK’s edge-to-edge toolbar, it leaves the strip above it uncovered, so the document scrolls under the clock and system icons. `NutrientDocumentStatusBarScrim` covers that strip with a tint and, on API 31 and later, a blur. It samples the document through a backdrop that the `DocumentView` records into:

```kotlin

val backdrop = rememberNutrientBackdropState()

Box(Modifier.fillMaxSize()) {
    // Must draw before the scrim: the scrim samples whatever drew before it.
    DocumentView(
        documentState = documentState,
        modifier = Modifier.fillMaxSize().nutrientBackdropSource(backdrop),
    )
    NutrientDocumentStatusBarScrim(
        documentState = documentState,
        state = backdrop,
        modifier = Modifier.align(Alignment.TopCenter),
    )
    coordinator?.let { NutrientFloatingToolbar(coordinator = it) }
}

```

The scrim stays hidden while the SDK’s own toolbar is mounted and while the viewer is in immersive mode. It appears only once the page scrolls up into the strip, and it fades in over the first part of the strip. The default tint follows the window’s status bar icon appearance: translucent white under dark icons and translucent black under light icons. `color` and `blurRadius` override the defaults, which live in `NutrientStatusBarScrimDefaults`. `NutrientStatusBarScrim` is the same scrim with an explicit `visible` flag, for chrome that a `DocumentState` doesn’t drive. In `PdfActivity` and `nutrientToolbarsComposeView` hosts, the document is a sibling `View` that can’t be sampled, so the scrim falls back to a flat tint there.

## API

These are the signatures of `NutrientFloatingToolbar` and `NutrientFloatingContextualToolbar`. The table after them describes each parameter and its default:

```kotlin

@Composable
fun NutrientFloatingToolbar(
    coordinator: ToolbarCoordinator,
    modifier: Modifier = Modifier,
    state: FloatingToolbarState = rememberFloatingToolbarState(),
    vibrant: Boolean = true,
    draggable: Boolean = true,
    collapsible: Boolean = false,
    windowInsets: WindowInsets = WindowInsets.safeDrawing,
)

@Composable
fun NutrientFloatingContextualToolbar(
    coordinator: ToolbarCoordinator,
    modifier: Modifier = Modifier,
    state: FloatingToolbarState = rememberFloatingToolbarState(),
    vibrant: Boolean = true,
    draggable: Boolean = true,
    defaultGroupingProvider: ContextualToolbarGroupingProvider? = null,
    windowInsets: WindowInsets = WindowInsets.safeDrawing,
)

```

| Parameter                 | Default                          | What it does                                                                    |
| ------------------------- | -------------------------------- | ------------------------------------------------------------------------------- |
| `coordinator`             |                                  | The [`ToolbarCoordinator`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.compose.toolbar.adapter/-toolbar-coordinator/index.html) the pill renders.                                  |
| `state`                   | `rememberFloatingToolbarState()` | Current edge, allowed edges, and expansion; saved across configuration changes. |
| `vibrant`                 | `true`                           | Vibrant or standard Material 3 floating toolbar colors.                         |
| `draggable`               | `true`                           | Whether the user can drag the pill between edges.                               |
| `collapsible`             | `false`                          | Main pill only: shrink to the active item after a tap.                          |
| `defaultGroupingProvider` | `null`                           | Contextual pill only: grouping when none is registered on the coordinator.      |
| `windowInsets`            | `WindowInsets.safeDrawing`       | Insets the pill keeps clear of on the edge it docks to.                         |

## Related

- [Main toolbar](https://www.nutrient.io/guides/android/jetpack-compose/components/main-toolbar.md) and [contextual toolbar](https://www.nutrient.io/guides/android/jetpack-compose/components/contextual-toolbar.md) — The docked composables.

- [Toolbar hosting](https://www.nutrient.io/guides/android/jetpack-compose/components/toolbar-hosting.md) — The coordinator and the inset model.

- [Main toolbar](https://www.nutrient.io/guides/android/customizing-the-interface/customizing-menus.md) — Customizing the items the pill shows.

- Catalog app — `MainToolbarFloatingExample`, `MainToolbarFabMenuExample`, and `MainToolbarCustomizationExample`.
---

## Related pages

- [Contextual toolbar](/guides/android/jetpack-compose/components/contextual-toolbar.md)
- [Main toolbar](/guides/android/jetpack-compose/components/main-toolbar.md)
- [Tab bar](/guides/android/jetpack-compose/components/tab-bar.md)
- [Toolbar hosting](/guides/android/jetpack-compose/components/toolbar-hosting.md)

