Android navigation

Material destination indicators for a bottom navigation bar or vertical rail.

Workspace destinations

Current destination: Home.

Use it for

  • Three to five destinations at the bottom of a compact Android layout.
  • A vertical destination rail beside a wider workspace.

Not for

  • Tabs that switch between panels within the same page.

Three ways in. They share one source, so the pixels match whichever you pick.

1. Import the package

npm install @noorddev/vlak-react

// once, next to your app's root
import "@noorddev/vlak-react/css";

import { AndroidNavigation } from "@noorddev/vlak-react";

Precompiled React and one stylesheet. No compiler to configure. Per-component imports work too: @noorddev/vlak-react/components/android-navigation.

2. Vendor the source

npx @noorddev/vlak-cli add android-navigation

The StyleX leaf lands in components/vlak/, for your own compiler to own. See StyleX.

3. Through shadcn

npx shadcn add https://vlak.dev/r/android-navigation.json

The same registry item, installed by shadcn's CLI.

CSS only

<link rel="stylesheet" href="node_modules/@noorddev/vlak/css/vlak.css" />

No React. Link vlak.css and use the markup and classes below.

import { AndroidNavigation } from "@noorddev/vlak-react";

<AndroidNavigation aria-label="Workspace" items={[{ value: "home", label: "Home" }, { value: "files", label: "Files" }, { value: "settings", label: "Settings" }]} defaultValue="home" onValueChange={setScreen} />

AndroidNavigation

PropTypeDefaultDescription
itemsrequiredAndroidNavigationItem[]
valuestring
defaultValuestring
onValueChange(value: string) => void
orientation"horizontal" | "vertical""horizontal"

Also accepts Omit<HTMLAttributes<HTMLElement>, "defaultValue" | "onChange">.

KeysDoes
TabMoves between enabled destinations.
Left or Right arrowMoves focus in a horizontal bar, respecting text direction.
Up or Down arrowMoves focus in a vertical rail.
Home or EndFocuses the first or last enabled destination.
Enter or SpaceActivates a button destination; native links use Enter.
<nav class="rs-android-navigation" aria-label="Workspace"><ul class="rs-android-navigation-list"><li class="rs-android-navigation-item"><button class="rs-android-navigation-control rs-android-navigation-current" type="button" aria-current="page"><span class="rs-android-navigation-indicator rs-android-navigation-active-indicator" aria-hidden="true">⌂</span><span class="rs-android-navigation-label">Home</span></button></li><li class="rs-android-navigation-item"><button class="rs-android-navigation-control" type="button"><span class="rs-android-navigation-indicator" aria-hidden="true">□</span><span class="rs-android-navigation-label">Files</span></button></li></ul></nav>
.rs-android-navigation.rs-android-navigation-list.rs-android-navigation-rail.rs-android-navigation-item.rs-android-navigation-control.rs-android-navigation-current.rs-android-navigation-disabled.rs-android-navigation-indicator.rs-android-navigation-active-indicator.rs-android-navigation-label