AppBar
Top app bars display navigation, title, and actions at the top of the screen. Follows the Material Design 3 Top App Bar specification.
Usage
import { AppBar } from '@rootnative/components'
import { ThemeProvider } from '@rootnative/core'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { View } from 'react-native'
export default function App() {
return (
<SafeAreaProvider>
<ThemeProvider>
<View style={{ flex: 1 }}>
<AppBar title="Home" />
</View>
</ThemeProvider>
</SafeAreaProvider>
)
}
Variants
| Variant | Description |
|---|---|
small | Compact single-row bar (default) |
center-aligned | Title centered in the bar |
medium | Expanded two-row bar |
large | Expanded with larger title typography |
With Back Button
import { AppBar } from '@rootnative/components'
import { ThemeProvider } from '@rootnative/core'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { Alert, View } from 'react-native'
export default function App() {
return (
<SafeAreaProvider>
<ThemeProvider>
<View style={{ flex: 1 }}>
<AppBar
title="Details"
canGoBack
onBackPress={() => Alert.alert('Back pressed')}
/>
</View>
</ThemeProvider>
</SafeAreaProvider>
)
}
With Actions
import { AppBar } from '@rootnative/components'
import { ThemeProvider } from '@rootnative/core'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { Alert, View } from 'react-native'
export default function App() {
return (
<SafeAreaProvider>
<ThemeProvider>
<View style={{ flex: 1 }}>
<AppBar
title="Inbox"
actions={[
{ icon: 'magnify', accessibilityLabel: 'Search', onPress: () => Alert.alert('Search') },
{ icon: 'dots-vertical', accessibilityLabel: 'More', onPress: () => Alert.alert('More') },
]}
/>
</View>
</ThemeProvider>
</SafeAreaProvider>
)
}
Collapse on Scroll
The medium and large variants collapse to the small (64dp) form as the
content scrolls, per the MD3 spec: the container height shrinks, the title
transitions to titleLarge typography, and the on-scroll tonal shift is
applied automatically — no elevated toggling needed.
Wire it up with useScroll from @rootnative/inertia: pass scrollY to the
bar's scrollOffset prop and the matching onScroll to a
Motion.ScrollView. Everything runs on the UI thread — there is no JS-side
scroll listener.
import { AppBar, Typography } from '@rootnative/components'
import { ThemeProvider } from '@rootnative/core'
import { Motion, useScroll } from '@rootnative/inertia'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { View } from 'react-native'
function Screen() {
const { scrollY, onScroll } = useScroll()
return (
<View style={{ flex: 1 }}>
<AppBar title="Large App Bar" variant="large" scrollOffset={scrollY} />
<Motion.ScrollView
onScroll={onScroll}
scrollEventThrottle={16}
contentContainerStyle={{ padding: 16, rowGap: 16 }}
>
{Array.from({ length: 30 }, (_, i) => (
<Typography key={i}>Scroll content row {i + 1}</Typography>
))}
</Motion.ScrollView>
</View>
)
}
export default function App() {
return (
<SafeAreaProvider>
<ThemeProvider>
<Screen />
</ThemeProvider>
</SafeAreaProvider>
)
}
The bar collapses over a scroll distance equal to the height it loses
(48px for medium, 88px for large), so the motion tracks the finger 1:1.
scrollOffset is ignored by the small and center-aligned variants —
keep using elevated for those.
Props
| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
title | string | - | Yes | Title text displayed in the bar. |
variant | enum | small | No | Layout variant. |
colorScheme | enum | surface | No | Color scheme that determines the default container and content colors. `containerColor` and `contentColor` props override these defaults. |
canGoBack | boolean | | No | When `true`, renders a back button in the leading slot. |
onBackPress | () => void | - | No | Called when the auto-rendered back button is pressed. |
insetTop | boolean | | No | When `true`, wraps the bar in a SafeAreaView that handles the top inset. |
elevated | boolean | | No | When `true`, applies the MD3 on-scroll tonal shift: the container color animates from its resting color to its elevated color (`surface` → `surfaceContainer` for the default `'surface'` color scheme). No shadow is added. Only the `'surface'` scheme defines a distinct elevated color; other schemes keep the same container color. Toggle this from your scroll handler when content scrolls under the bar. When `scrollOffset` is provided on a `'medium'`/`'large'` bar, the tonal shift is driven from the scroll position automatically and this prop only forces the elevated color on. |
scrollOffset | SharedValue<number> | - | No | Vertical scroll offset (in px) of the content scrolling under the bar, as a Reanimated shared value. Pass `scrollY` from `@rootnative/inertia`'s `useScroll()` and give the matching `onScroll` to your scroll view: ```tsx const { scrollY, onScroll } = useScroll() <AppBar variant="large" title="Title" scrollOffset={scrollY} /> <Motion.ScrollView onScroll={onScroll} scrollEventThrottle={16}> ``` Drives the MD3 collapse-on-scroll behavior of the `'medium'` and `'large'` variants: the container collapses to the small (64dp) form and the title interpolates to `titleLarge` as the user scrolls, with the on-scroll tonal shift riding the same progress. Ignored by the `'small'` and `'center-aligned'` variants. |
leading | ReactNode | - | No | Custom leading content. When provided, overrides `canGoBack`. |
trailing | ReactNode | - | No | Custom trailing content. When provided, overrides `actions`. |
actions | AppBarAction[] | - | No | Array of actions rendered in the trailing slot. Each entry is either an icon action (`{ icon }`) or a text action (`{ label }`, e.g. "Save"). |
containerColor | string | - | No | Override the container (background) color. Applied to both normal and elevated states. |
contentColor | string | - | No | Override the content (title and icon) color. |
titleStyle | StyleProp<TextStyle> | - | No | Additional style applied to the title text. |
style | StyleProp<ViewStyle> | - | No | Custom style applied to the root container. |