Skip to main content

Drawer

A vertical side-navigation panel that lists the app's top-level destinations and highlights the one currently active.

Drawer is a mobile-only component. It renders the full navigation panel on mobile via React Native Paper; on web it renders nothing (use a web layout shell for side navigation there), so it can be imported safely from shared cross-platform code.

Usage

import { useState } from 'react';
import { Drawer } from '@sublime-ui/library';
import type { NavItem } from '@sublime-ui/library';

export default function DrawerExample() {
const items: NavItem[] = [
{ key: 'home', label: 'Home', icon: 'home' },
{ key: 'reports', label: 'Reports', icon: 'chart-line' },
{ key: 'settings', label: 'Settings', icon: 'cog' },
];
const [active, setActive] = useState('home');

return <Drawer items={items} activeKey={active} onSelect={setActive} />;
}

Examples

Items with notification badges

Any NavItem can carry a badge (string or number) that renders as a small counter pill on the right edge of the row.

import { useState } from 'react';
import { Drawer } from '@sublime-ui/library';
import type { NavItem } from '@sublime-ui/library';

export default function DrawerWithBadgesExample() {
const items: NavItem[] = [
{ key: 'inbox', label: 'Inbox', icon: 'inbox', badge: 12 },
{ key: 'drafts', label: 'Drafts', icon: 'file-document-edit', badge: 'NEW' },
{ key: 'archive', label: 'Archive', icon: 'archive' },
];
const [active, setActive] = useState('inbox');

return <Drawer items={items} activeKey={active} onSelect={setActive} />;
}

With a header

Pass any React node as header to render a branded region above the navigation list, separated by a divider.

import { useState } from 'react';
import { Drawer, Text } from '@sublime-ui/library';
import type { NavItem } from '@sublime-ui/library';

export default function DrawerWithHeaderExample() {
const items: NavItem[] = [
{ key: 'dashboard', label: 'Dashboard', icon: 'view-dashboard' },
{ key: 'orders', label: 'Orders', icon: 'package-variant' },
{ key: 'customers', label: 'Customers', icon: 'account-group' },
];
const [active, setActive] = useState('dashboard');

return (
<Drawer
items={items}
activeKey={active}
onSelect={setActive}
header={<Text variant="title">Acme Admin</Text>}
/>
);
}

Use footer for persistent actions pinned to the bottom of the panel, such as a sign-out button.

import { useState } from 'react';
import { Drawer, Button } from '@sublime-ui/library';
import type { NavItem } from '@sublime-ui/library';

export default function DrawerWithFooterExample() {
const items: NavItem[] = [
{ key: 'projects', label: 'Projects', icon: 'folder-multiple' },
{ key: 'team', label: 'Team', icon: 'account-multiple' },
];
const [active, setActive] = useState('projects');

const signOut = () => {
console.log('Signing out');
};

return (
<Drawer
items={items}
activeKey={active}
onSelect={setActive}
footer={
<Button variant="ghost" tone="danger" onPress={signOut}>
Sign out
</Button>
}
/>
);
}

A complete navigation panel combining a branded header, badged items, and a footer action — the typical shape inside a mobile app shell.

import { useState } from 'react';
import { Drawer, Text, Button } from '@sublime-ui/library';
import type { NavItem } from '@sublime-ui/library';

export default function FullDrawerExample() {
const items: NavItem[] = [
{ key: 'home', label: 'Home', icon: 'home' },
{ key: 'messages', label: 'Messages', icon: 'message-text', badge: 3 },
{ key: 'billing', label: 'Billing', icon: 'credit-card' },
{ key: 'settings', label: 'Settings', icon: 'cog' },
];
const [active, setActive] = useState('home');

const openProfile = () => {
console.log('Opening profile');
};

return (
<Drawer
items={items}
activeKey={active}
onSelect={setActive}
testID="main-drawer"
header={<Text variant="title">Field Service</Text>}
footer={
<Button variant="soft" tone="primary" onPress={openProfile}>
My profile
</Button>
}
/>
);
}

Props

items

Type: NavItem[] Default:Required: Yes

The navigation destinations to render, in order. Each NavItem has a unique key, a label, an icon (a Material Community Icons name), and an optional badge (string | number).

activeKey

Type: string Default:Required: Yes

The key of the currently selected item. The matching row is highlighted with the primary soft background and emphasized text.

onSelect

Type: (key: string) => void Default:Required: Yes

Called with the key of an item when its row is pressed. Drive activeKey from this callback to update the selected destination.

Type: ReactNode Default:Required: No

Optional content rendered in a padded region above the navigation list, separated from it by a divider. Use it for branding or a workspace switcher.

Type: ReactNode Default:Required: No

Optional content pinned below the navigation list, separated by a divider. Use it for persistent actions such as sign-out or a profile shortcut.

testID

Type: string Default:Required: No

Test identifier forwarded to the underlying panel. Each item row is additionally tagged as `${testID}-${item.key}` (falling back to drawer when testID is omitted) for use in automated tests.

See also

  • BottomNav — a bottom tab bar for switching between a small number of top-level destinations.
  • AppBar — the top application bar that pairs with a drawer for the screen title and actions.
  • GlassAppBar — a translucent variant of the app bar for immersive layouts.