Skip to main content

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

VariantDescription
smallCompact single-row bar (default)
center-alignedTitle centered in the bar
mediumExpanded two-row bar
largeExpanded 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

PropTypeDefaultRequiredDescription
titlestring-YesTitle text displayed in the bar.
variantenumsmallNoLayout variant.
colorSchemeenumsurfaceNoColor scheme that determines the default container and content colors. `containerColor` and `contentColor` props override these defaults.
canGoBackbooleanNoWhen `true`, renders a back button in the leading slot.
onBackPress() => void-NoCalled when the auto-rendered back button is pressed.
insetTopbooleanNoWhen `true`, wraps the bar in a SafeAreaView that handles the top inset.
elevatedbooleanNoWhen `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.
scrollOffsetSharedValue<number>-NoVertical 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.
leadingReactNode-NoCustom leading content. When provided, overrides `canGoBack`.
trailingReactNode-NoCustom trailing content. When provided, overrides `actions`.
actionsAppBarAction[]-NoArray of actions rendered in the trailing slot. Each entry is either an icon action (`{ icon }`) or a text action (`{ label }`, e.g. "Save").
containerColorstring-NoOverride the container (background) color. Applied to both normal and elevated states.
contentColorstring-NoOverride the content (title and icon) color.
titleStyleStyleProp<TextStyle>-NoAdditional style applied to the title text.
styleStyleProp<ViewStyle>-NoCustom style applied to the root container.