Dynamic toolbar
Pre-alphaThe registry and the CLI are not published yet.Roadmap
Contextual UI

Dynamic toolbar

A bottom bar that replaces navigation during a mode, with actions that follow the context.

Draft

Specified, not implemented yet. The bar is ToolBar with its visible prop, driven by the screen’s state. The API may change.

While the user browses, the bottom of the screen belongs to navigation. When they enter a mode that needs its own commands, such as selecting, editing or cropping, a toolbar takes that place. Its actions stay in the same spots but turn on and off as the context changes. When the mode ends, navigation comes back.

Files
Design brief.pdf1.8 MB · Today
Estimate.xlsx46 KB · Yesterday
Team photo.jpgShared with you · 3.2 MB
References.zip12 MB · Mon
Interview notes.txt4 KB · Mon
Roadmap.key8.4 MB · Last week
Invoice 0917.pdf220 KB · Last week
Logo final v3.svg18 KB · Aug 30
Moodboard.pngShared with you · 5.1 MB
Contract draft.docx96 KB · Aug 21
FilesRecentSharedSettings
mode browse · selected 0enabled

In this example the mode is file selection. Tap Select, or hold a row, then change the selection and watch which actions stay enabled. Nothing moves in the bar, only the colors change.

The bar, frame by frame:

Files
browse

The tab bar. Rows open files.

Select items
select · 0

The toolbar replaces the tab bar, every action greyed out.

1 selected
select · 1

One file: everything applies, Rename included.

2 selected
select · 2

Two files, one shared: no Rename, no Delete.

When to use it

  • A temporary mode with several commands that should be at thumb reach: selecting items, editing a note, cropping a photo.
  • Commands whose availability depends on the current context: what is selected, whether there is something to undo, whether the content is valid.

Don’t use it for a single primary action, that’s a button in the screen. Don’t show a toolbar that has nothing to offer in the current mode, and don’t swap navigation out while the user is simply browsing.

How it works

Two things change, at two different moments.

The bar follows the mode. Entering the mode slides the tab bar down and the toolbar up in the same slot, in 240ms. Leaving it does the reverse. The two bars are never visible together, and the content keeps its scroll position.

The actions follow the context. Each action declares when it applies, and the toolbar recomputes whenever the context changes.

ModeActionEnabled when
SelectingRenameExactly one item is selected.
SelectingDeleteEvery selected item belongs to the user.
EditingUndoThere is something to undo.
EditingSaveThe content has changed and is valid.

Disable, don’t remove

The number and order of actions stay fixed for the whole mode. If an action disappeared, the next one would slide under the thumb that was about to tap it. A greyed-out action also tells the user the command exists and that the context is what blocks it.

Only remove an action when it can never apply in this mode, and decide it on entering the mode, not on each change.

Exiting and overflow

  • Every mode has an explicit way out: a Done or Cancel in the app bar, and the system back gesture. The toolbar never is the only exit.
  • More than four actions: keep the three most used and put the rest behind a More action opening a Menu.

Implementation

There is no dedicated hook: the mode and its context are screen state, and ToolBar renders the actions.

LibraryUsed for
React stateThe current mode and its context. Enabled actions are derived from them, never stored.
react-native-reanimatedThe bar swap: entering / exiting slide transitions on the tab bar and the toolbar.
React NavigationtabBarStyle: { display: 'none' } on the tab navigator during the mode, and beforeRemove to exit the mode on back.

In a screen

Conceptual
const [mode, setMode] = useState<"browse" | "edit">("browse");
const editing = mode === "edit";

useLayoutEffect(() => {
	navigation
		.getParent()
		?.setOptions({ tabBarStyle: editing ? { display: "none" } : undefined });
}, [editing]);

<ToolBar visible={editing}>
	<ToolBar.Action
		icon="undo"
		label="Undo"
		disabled={!history.canUndo}
		onPress={history.undo}
	/>
	<ToolBar.Action
		icon="redo"
		label="Redo"
		disabled={!history.canRedo}
		onPress={history.redo}
	/>
	<ToolBar.Action
		icon="check"
		label="Save"
		disabled={!draft.dirty || !draft.valid}
		onPress={save}
	/>
</ToolBar>;

Accessibility

  • Announce the mode change when the toolbar appears.
  • Disabled actions stay focusable with accessibilityState={{ disabled: true }}, so screen reader users hear why they can’t act. An accessibilityHint can say what’s missing.
  • Don’t rely on color: the disabled state must also be exposed to assistive tech, and a destructive action keeps its label.
  • With Reduce Motion on, the bars swap without sliding.