+
+Bottom Navigation on iOS, with native blur.
+
+
+
+Bottom Navigation on Android, following Material Design 3 styling.
+
+
+
+On iPadOS tabs appear at the top with a button allowing you to go into the sidebar mode.
+
+
+
+On visionOS, the tabs appear on the left side, attached outside of the window.
+
+
+
+On tvOS tabs appear on the top, making navigation with the TV remote a breeze.
+
+
+
+On macOS, tabs appear on the left side, following the design of the Finder app.
+
+#### Automatic scroll to the top
+
+iOS TabView automatically scrolls to the top when ScrollView is embedded inside of it.
+
+#### Automatic PiP avoidance
+
+The operating system recognizes navigation in your app making the Picture in Picture window automatically avoid bottom navigation.
+
+#### Platform-specific styling
+
+For iOS bottom navigation has a built-in blur making your app stand out. For Android, you can choose between Material 2 and Material 3 and leverage Material You system styling.
+
+#### Sidebar
+
+TabView can turn in to a side bar on tvOS, iPadOS and macOS. The `sidebarAdaptable` prop controls this.
+
+## Getting started
+
+To get started follow the installation instructions in the `react-native-bottom-tabs` [documentation](https://callstackincubator.github.io/react-native-bottom-tabs/docs/getting-started/quick-start.html).
+
+Native Bottom Tabs Navigation resembles JavaScript Tabs API as closely as possible. Making your migration straightforward.
+
+As mentioned before, Native Bottom Tabs use native primitives to create the tabs. This approach also has some downsides: Native components enforce certain constraints that we need to follow.
+
+There are a few differences between the APIs worth noting. One of the biggest is how native tabs handle images. In JavaScript tabs, you can render React components as icons, in native tabs unfortunately it’s not possible. Instead, you have to provide one of the following options:
+
+```tsx
+
+
+You can check out the project [here](https://github.com/callstackincubator/react-native-bottom-tabs).
+
+Thanks for reading!
diff --git a/blog/authors.yml b/blog/authors.yml
new file mode 100644
index 00000000000..a184d71c1bb
--- /dev/null
+++ b/blog/authors.yml
@@ -0,0 +1,49 @@
+satya:
+ name: Satyajit Sahoo
+ url: https://satya164.page
+ image_url: https://avatars2.githubusercontent.com/u/1174278
+ title: Core Team
+ socials:
+ x: satya164
+ github: satya164
+
+michal:
+ name: Michał Osadnik
+ image_url: https://avatars3.githubusercontent.com/u/25709300
+ title: Core Team
+ socials:
+ x: mosdnk
+ github: osdnk
+
+brent:
+ name: Brent Vatne
+ url: https://bsky.app/profile/notbrent.bsky.social
+ image_url: https://avatars0.githubusercontent.com/u/90494
+ title: Core Team
+ socials:
+ x: notbrent
+ github: brentvatne
+
+artur:
+ name: Artur Yorsh
+ image_url: https://pbs.twimg.com/profile_images/1668375708962357248/ntCXYm7e_400x400.jpg
+ title: UI Kitten Team
+ socials:
+ x: artyorsh
+ github: artyorsh
+
+dawid:
+ name: Dawid Urbaniak
+ image_url: https://avatars0.githubusercontent.com/u/18584155
+ title: React Native Paper Team
+ socials:
+ x: trensik
+ github: Trancever
+
+oskar:
+ name: Oskar Kwaśniewski
+ image_url: https://avatars.githubusercontent.com/u/52801365
+ title: Callstack
+ socials:
+ x: o_kwasniewski
+ github: okwasniewsk
diff --git a/crowdin.yaml b/crowdin.yaml
index 05b3c635dfb..8ae89d87510 100644
--- a/crowdin.yaml
+++ b/crowdin.yaml
@@ -1,20 +1,17 @@
project_identifier_env: CROWDIN_DOCUSAURUS_PROJECT_ID
api_key_env: CROWDIN_DOCUSAURUS_API_KEY
-base_path: "./"
+base_path: './'
preserve_hierarchy: true
files:
- -
- source: '/docs/*.md'
+ - source: '/docs/*.md'
translation: '/translated_docs/%locale%/%original_file_name%'
languages_mapping: &anchor
locale:
'zh-CN': 'zh-Hans'
- -
- source: '/i18n/en.json'
+ - source: '/i18n/en.json'
translation: '/i18n/%locale%.json'
languages_mapping: *anchor
- -
- source: '/versioned_docs/**/*.md'
+ - source: '/versioned_docs/**/*.md'
translation: '/translated_docs/%locale%/**/%original_file_name%'
languages_mapping: *anchor
diff --git a/docusaurus.config.js b/docusaurus.config.js
index ee4e113b6a2..dd90010233c 100755
--- a/docusaurus.config.js
+++ b/docusaurus.config.js
@@ -1,7 +1,10 @@
-import path from 'path';
import remarkNpm2Yarn from '@docusaurus/remark-plugin-npm2yarn';
+import rehypeCodeblockMeta from './src/plugins/rehype-codeblock-meta.mjs';
export default {
+ future: {
+ experimental_faster: true,
+ },
title: 'React Navigation',
tagline: 'Routing and navigation for your React Native apps',
url: 'https://reactnavigation.org/',
@@ -9,11 +12,27 @@ export default {
favicon: 'img/favicon.ico',
organizationName: 'react-navigation',
projectName: 'react-navigation.github.io',
- scripts: ['/js/snack-helpers.js'],
+ onBrokenAnchors: 'throw',
+ onBrokenMarkdownLinks: 'throw',
+ scripts: ['/js/snack-helpers.js', '/js/toc-fixes.js'],
themeConfig: {
+ colorMode: {
+ defaultMode: 'light',
+ disableSwitch: false,
+ respectPrefersColorScheme: true,
+ },
prism: {
theme: require('prism-react-renderer').themes.github,
darkTheme: require('prism-react-renderer').themes.dracula,
+ magicComments: [
+ {
+ className: 'theme-code-block-highlighted-line',
+ line: 'highlight-next-line',
+ block: { start: 'highlight-start', end: 'highlight-end' },
+ },
+ { className: 'code-block-diff-add-line', line: 'diff-add' },
+ { className: 'code-block-diff-remove-line', line: 'diff-remove' },
+ ],
},
algolia: {
appId: 'QCWXRU195A',
@@ -28,111 +47,87 @@ export default {
src: 'img/spiro.svg',
},
items: [
- { to: 'docs/getting-started', label: 'Docs', position: 'left' },
- { to: 'blog', label: 'Blog', position: 'left' },
{
- href: 'https://github.com/react-navigation',
- label: 'GitHub',
+ type: 'docsVersionDropdown',
position: 'right',
},
{
- to: 'help',
- label: 'Help',
+ to: 'docs/getting-started',
+ activeBasePath: 'docs',
+ label: 'Docs',
+ position: 'right',
},
{
- type: 'docsVersionDropdown',
- position: 'left',
+ to: 'blog',
+ label: 'Blog',
+ position: 'right',
},
- ],
- },
- footer: {
- style: 'dark',
- links: [
{
- title: 'Docs',
+ type: 'dropdown',
+ label: 'Help',
items: [
{
- label: 'Getting Started',
- to: 'docs/getting-started',
+ label: 'Issues',
+ href: 'https://github.com/react-navigation/react-navigation/issues',
},
{
- label: 'Building your own Navigator',
- to: 'docs/custom-navigators',
+ label: 'Feature Requests',
+ href: 'https://react-navigation.canny.io/feature-requests',
},
{
- label: 'Contributing',
- to: 'docs/contributing',
+ label: 'Reactiflux Discord',
+ href: 'https://www.reactiflux.com',
},
- ],
- },
- {
- title: 'Support',
- items: [
{
- label: 'Chat in our Discord channel',
- href: 'https://discord.gg/reactiflux',
- },
- {
- label: 'Get help on Stack Overflow',
+ label: 'Stack Overflow',
href: 'https://stackoverflow.com/questions/tagged/react-navigation',
},
{
- label: 'Request a feature on Canny',
- href: 'https://react-navigation.canny.io/feature-requests',
+ label: 'Troubleshooting',
+ to: 'docs/troubleshooting',
},
{
- label: 'Report a bug on GitHub',
- href: 'https://github.com/react-navigation/react-navigation/issues/new/choose',
+ label: 'Contributing',
+ to: 'docs/contributing',
},
],
+ position: 'right',
},
{
- title: 'Social',
- items: [
- {
- label: 'Blog',
- to: 'blog',
- },
- {
- label: 'GitHub',
- href: 'https://github.com/react-navigation/react-navigation',
- },
- {
- label: 'Twitter',
- href: 'https://twitter.com/reactnavigation',
- },
- ],
+ href: 'https://x.com/reactnavigation',
+ className: 'navbar-social-link navbar-social-link-x',
+ 'aria-label': 'X',
+ position: 'right',
},
{
- title: 'Built with',
- items: [
- {
- label: 'Docusaurus',
- to: 'https://docusaurus.io/',
- },
- {
- label: 'GitHub Pages',
- href: 'https://pages.github.com/',
- },
- {
- label: 'Netlify',
- href: 'https://www.netlify.com/',
- },
- ],
+ href: 'https://github.com/react-navigation/react-navigation',
+ className: 'navbar-social-link navbar-social-link-github',
+ 'aria-label': 'GitHub',
+ position: 'right',
},
],
},
},
plugins: [
+ './src/plugins/disable-fully-specified.mjs',
+ './src/plugins/react-navigation-versions.mjs',
[
'@docusaurus/plugin-client-redirects',
{
redirects: [
{
from: '/next',
- to: '/docs/7.x/getting-started',
+ to: '/docs/migration-guides',
},
],
+ createRedirects(existingPath) {
+ if (
+ existingPath.includes('/docs/') &&
+ !/\/docs\/\d+\.x/.test(existingPath)
+ ) {
+ return existingPath.replace('/docs/', '/docs/7.x/');
+ }
+ },
},
],
],
@@ -144,8 +139,16 @@ export default {
editUrl:
'https://github.com/react-navigation/react-navigation.github.io/edit/main/',
includeCurrentVersion: false,
- lastVersion: '6.x',
+ lastVersion: '7.x',
+ breadcrumbs: false,
+ sidebarCollapsed: false,
remarkPlugins: [[remarkNpm2Yarn, { sync: true }]],
+ rehypePlugins: [
+ [
+ rehypeCodeblockMeta,
+ { match: { snack: true, lang: true, tabs: true } },
+ ],
+ ],
},
blog: {
remarkPlugins: [[remarkNpm2Yarn, { sync: true }]],
diff --git a/package.json b/package.json
index 4239daca30a..8c4108eb882 100755
--- a/package.json
+++ b/package.json
@@ -11,24 +11,34 @@
"deploy": "DEPLOYMENT_BRANCH=gh-pages docusaurus deploy",
"crowdin-upload": "crowdin upload sources --auto-update -b main",
"crowdin-download": "crowdin download -b main",
- "fetch-sponsors": "node scripts/fetch-sponsors.js"
+ "fetch-sponsors": "node scripts/fetch-sponsors.js && prettier --write src/data/sponsors.js"
},
"dependencies": {
- "@docusaurus/core": "3.0.0",
- "@docusaurus/plugin-client-redirects": "3.0.0",
- "@docusaurus/plugin-google-analytics": "3.0.0",
- "@docusaurus/preset-classic": "3.0.0",
- "@docusaurus/remark-plugin-npm2yarn": "3.0.0",
- "@octokit/graphql": "^7.0.2",
- "@react-navigation/core": "^7.0.0-alpha.2",
+ "@docusaurus/core": "3.6.1",
+ "@docusaurus/faster": "3.6.1",
+ "@docusaurus/plugin-client-redirects": "3.6.1",
+ "@docusaurus/plugin-google-analytics": "3.6.1",
+ "@docusaurus/preset-classic": "3.6.1",
+ "@docusaurus/remark-plugin-npm2yarn": "3.6.1",
+ "@octokit/graphql": "^7.1.0",
+ "@react-navigation/core": "^7.0.4",
"escape-html": "^1.0.3",
"mkdirp": "^3.0.1",
"netlify-plugin-cache": "^1.0.3",
- "prism-react-renderer": "^2.3.0",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
- "react-simple-code-editor": "^0.13.1"
+ "prism-react-renderer": "^2.4.0",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "react-simple-code-editor": "^0.14.1"
},
+ "devDependencies": {
+ "markdownlint": "^0.36.1",
+ "markdownlint-cli2": "^0.14.0",
+ "prettier": "^3.3.3"
+ },
+ "resolutions": {
+ "@rspack/core": "1.0.14"
+ },
+ "packageManager": "yarn@4.0.2",
"browserslist": {
"production": [
">0.2%",
@@ -40,10 +50,5 @@
"last 1 firefox version",
"last 1 safari version"
]
- },
- "devDependencies": {
- "markdownlint": "^0.32.1",
- "markdownlint-cli2": "^0.11.0"
- },
- "packageManager": "yarn@4.0.2"
+ }
}
diff --git a/scripts/fetch-sponsors.js b/scripts/fetch-sponsors.js
index 2bef5e0fb14..a8230303420 100644
--- a/scripts/fetch-sponsors.js
+++ b/scripts/fetch-sponsors.js
@@ -62,7 +62,10 @@ async function fetchAndWriteSponsorsAsync() {
'data',
'sponsors.js'
);
- fs.writeFileSync(sponsorsFilePath, `export default ${JSON.stringify(sponsors, null, 2)}`);
+ fs.writeFileSync(
+ sponsorsFilePath,
+ `export default ${JSON.stringify(sponsors, null, 2)}`
+ );
console.log(`Wrote updated sponsors to ${sponsorsFilePath}`);
}
diff --git a/sidebars.js b/sidebars.js
deleted file mode 100755
index 2c1f4c9e5de..00000000000
--- a/sidebars.js
+++ /dev/null
@@ -1,3 +0,0 @@
-module.exports = {
- docs: { }
-};
diff --git a/src/components/Pre.js b/src/components/Pre.js
new file mode 100644
index 00000000000..227c15c070b
--- /dev/null
+++ b/src/components/Pre.js
@@ -0,0 +1,314 @@
+import { useActiveVersion } from '@docusaurus/plugin-content-docs/client';
+import { useColorMode } from '@docusaurus/theme-common';
+import { usePluginData } from '@docusaurus/useGlobalData';
+import MDXPre from '@theme-original/MDXComponents/Pre';
+import React from 'react';
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+const SUPPORTED_TABS = {
+ config: [
+ { value: 'static', label: 'Static', default: true },
+ { value: 'dynamic', label: 'Dynamic' },
+ ],
+};
+
+export default function Pre({
+ children,
+ 'data-name': name,
+ 'data-snack': snack,
+ 'data-dependencies': deps,
+ 'data-tabs': tabs,
+ 'data-lang': lang,
+ ...rest
+}) {
+ const { colorMode } = useColorMode();
+ const activeVersion = useActiveVersion();
+ const { versions } = usePluginData('react-navigation-versions');
+
+ const child = React.Children.only(children);
+
+ // If we encounter tabs, we need to render 2 code blocks
+ if (tabs && tabs in SUPPORTED_TABS) {
+ return (
+
+ {React.cloneElement(children, {
+ ...child.props,
+ children: content.trim(),
+ })}
+
+ - React Navigation is built by Expo,{' '} - Software Mansion, and{' '} - Callstack, with contributions - from the{' '} + React Navigation relies on the support from the community. Thanks to{' '} + Software Mansion,{' '} + Callstack,{' '} + Expo, and our amazing{' '} - community + contributors {' '} - and{' '} - sponsors: + & sponsors:
-By default, the position is chosen automatically based on device width.
+- `beside-icon` the label is shown next to the icon (typical for iPad)
+
#### `tabBarLabelStyle`
Style object for the tab label.
+
+
+Example:
+
+```js
+ tabBarLabelStyle: {
+ fontSize: 16,
+ fontFamily: 'Georgia',
+ fontWeight: 300,
+ },
+```
#### `tabBarIcon`
@@ -214,17 +379,26 @@ Style object for the tab icon.
Text to show in a badge on the tab icon. Accepts a `string` or a `number`.
+
+
#### `tabBarBadgeStyle`
Style for the badge on the tab icon. You can specify a background color or text color here.
-#### `tabBarAccessibilityLabel`
+
-Accessibility label for the tab button. This is read by the screen reader when the user taps the tab. It's recommended to set this if you don't have a label for the tab.
+Example:
-#### `tabBarTestID`
+```js
+ tabBarBadgeStyle: {
+ color: 'black',
+ backgroundColor: 'yellow',
+ },
+```
-ID to locate this tab button in tests.
+#### `tabBarAccessibilityLabel`
+
+Accessibility label for the tab button. This is read by the screen reader when the user taps the tab. It's recommended to set this if you don't have a label for the tab.
#### `tabBarButton`
@@ -236,13 +410,19 @@ You can specify a custom implementation here:
tabBarButton: (props) =>
#### `tabBarInactiveTintColor`
Color for the icon and label in the inactive tabs.
+
#### `tabBarActiveBackgroundColor`
@@ -274,75 +454,140 @@ To show your screen under the tab bar, you can set the `position` style to absol
>
```
-You also might need to add a bottom margin to your content if you have a absolutely positioned tab bar. React Navigation won't do it automatically.
+You also might need to add a bottom margin to your content if you have an absolutely positioned tab bar. React Navigation won't do it automatically. See [`useBottomTabBarHeight`](#usebottomtabbarheight) for more details.
-To get the height of the bottom tab bar, you can use `BottomTabBarHeightContext` with [React's Context API](https://reactjs.org/docs/context.html#contextconsumer) or `useBottomTabBarHeight`:
+#### `tabBarBackground`
+
+Function which returns a React Element to use as background for the tab bar. You could render an image, a gradient, blur view etc.:
```js
-import { BottomTabBarHeightContext } from '@react-navigation/bottom-tabs';
+import { BlurView } from 'expo-blur';
// ...
-
+
+#### `tabBarPosition`
+
+Position of the tab bar. Available values are:
+
+- `bottom` (Default)
+- `top`
+- `left`
+- `right`
+
+When the tab bar is positioned on the `left` or `right`, it is styled as a sidebar. This can be useful when you want to show a sidebar on larger screens and a bottom tab bar on smaller screens:
+
+
+
+You can also render a compact sidebar by placing the label below the icon. This is only supported when the [`tabBarVariant`](#tabbarvariant) is set to `material`:
+
+
+
+```js
+ drawerActiveTintColor: 'green',
+```
+
#### `drawerActiveBackgroundColor`
Background color for the active item in the drawer.
+
+
+```js
+ screenOptions={{
+ drawerActiveTintColor: 'white',
+ drawerActiveBackgroundColor: '#003CB3',
+ drawerLabelStyle: {
+ color: 'white',
+ },
+ }}
+```
+
#### `drawerInactiveTintColor`
Color for the icon and label in the inactive items in the drawer.
@@ -285,10 +343,35 @@ Background color for the inactive items in the drawer.
Style object for the single item, which can contain an icon and/or a label.
+
+
+Example:
+
+```js
+ drawerItemStyle: {
+ backgroundColor: '#9dd3c8',
+ borderColor: 'black',
+ orderWidth: 2,
+ opacity: 0.6,
+ },
+```
+
#### `drawerLabelStyle`
Style object to apply to the `Text` style inside content section which renders a label.
+
+
+Example:
+
+```js
+ drawerLabelStyle: {
+ color: 'black',
+ fontSize: 20,
+ fontFamily: 'Georgia',
+ },
+```
+
#### `drawerContentContainerStyle`
Style object for the content section inside the `ScrollView`.
@@ -301,7 +384,7 @@ Style object for the wrapper view.
Style object for the drawer component. You can pass a custom background color for a drawer or a custom width here.
-
+
```js
+
#### `headerBackVisible`
Whether the back button is visible in the header. You can use it to show a back button alongside `headerLeft` if you have specified it.
@@ -83,13 +796,31 @@ This will have no effect on the first screen in the stack.
#### `headerBackTitle`
-Title string used by the back button on iOS. Defaults to the previous scene's title, or "Back" if there's not enough space. Use `headerBackTitleVisible: false` to hide it.
+Title string used by the back button on iOS. Defaults to the previous scene's title, "Back" or arrow icon depending on the available space. See `headerBackButtonDisplayMode` to read about limitations and customize the behavior.
+
+Use `headerBackButtonDisplayMode: "minimal"` to hide it.
Only supported on iOS.
-#### `headerBackTitleVisible`
+
+
+#### `headerBackButtonDisplayMode`
+
+How the back button displays icon and title.
+
+Supported values:
+
+- "default" - Displays one of the following depending on the available space: previous screen's title, generic title (e.g. 'Back') or no title (only icon).
+- "generic" – Displays one of the following depending on the available space: generic title (e.g. 'Back') or no title (only icon).
+- "minimal" – Always displays only the icon without a title.
+
+The space-aware behavior is disabled when:
+
+- The iOS version is 13 or lower
+- Custom font family or size is set (e.g. with `headerBackTitleStyle`)
+- Back button menu is disabled (e.g. with `headerBackButtonMenuEnabled`)
-Whether the back button title should be visible or not.
+In such cases, a static title and icon are always displayed.
Only supported on iOS.
@@ -102,6 +833,17 @@ Style object for header back title. Supported properties:
Only supported on iOS.
+
+
+Example:
+
+```js
+ headerBackTitleStyle: {
+ fontSize: 14,
+ fontFamily: 'Georgia',
+ },
+```
+
#### `headerBackImageSource`
Image to display in the header as the icon in the back button. Defaults to back icon image for the platform
@@ -119,14 +861,25 @@ Supported properties:
Only supported on iOS.
+
+
#### `headerLargeTitle`
Whether to enable header with large title which collapses to regular header on scroll.
+Defaults to `false`.
For large title to collapse on scroll, the content of the screen should be wrapped in a scrollable view such as `ScrollView` or `FlatList`. If the scrollable area doesn't fill the screen, the large title won't collapse on scroll. You also need to specify `contentInsetAdjustmentBehavior="automatic"` in your `ScrollView`, `FlatList` etc.
Only supported on iOS.
+
+
#### `headerLargeTitleShadowVisible`
Whether drop shadow of header is visible when a large title is shown.
@@ -142,9 +895,18 @@ Style object for large title in header. Supported properties:
Only supported on iOS.
-#### `headerShown`
+
-Whether to show the header. The header is shown by default. Setting this to `false` hides the header.
+Example:
+
+```js
+ headerLargeTitleStyle: {
+ fontFamily: 'Georgia',
+ fontSize: 22,
+ fontWeight: '500',
+ color: 'blue',
+ },
+```
#### `headerStyle`
@@ -152,10 +914,21 @@ Style object for header. Supported properties:
- `backgroundColor`
+
+
#### `headerShadowVisible`
Whether to hide the elevation shadow (Android) or the bottom border (iOS) on the header.
+Android:
+
+
+iOS:
+
+
#### `headerTransparent`
Boolean indicating whether the navigation bar is translucent.
@@ -166,7 +939,7 @@ This is useful if you want to render a semi-transparent header or a blurred back
Note that if you don't want your content to appear under the header, you need to manually add a top margin to your content. React Navigation won't do it automatically.
-To get the height of the header, you can use [`HeaderHeightContext`](elements.md#headerheightcontext) with [React's Context API](https://reactjs.org/docs/context.html#contextconsumer) or [`useHeaderHeight`](elements.md#useheaderheight).
+To get the height of the header, you can use [`HeaderHeightContext`](elements.md#headerheightcontext) with [React's Context API](https://react.dev/reference/react/useContext#contextconsumer) or [`useHeaderHeight`](elements.md#useheaderheight).
#### `headerBlurEffect`
@@ -175,25 +948,61 @@ Blur effect for the translucent header. The `headerTransparent` option needs to
Supported values:
- `extraLight`
+
- `light`
+
+
- `dark`
+
+
- `regular`
+
+
- `prominent`
+
+
- `systemUltraThinMaterial`
+
+
- `systemThinMaterial`
+
+
- `systemMaterial`
+
+
- `systemThickMaterial`
+
+
- `systemChromeMaterial`
+
+
- `systemUltraThinMaterialLight`
+
+
- `systemThinMaterialLight`
+
+
- `systemMaterialLight`
+
+
- `systemThickMaterialLight`
+
+
- `systemChromeMaterialLight`
+
+
- `systemUltraThinMaterialDark`
+
- `systemThinMaterialDark`
+
+
- `systemMaterialDark`
+
- `systemThickMaterialDark`
+
+
- `systemChromeMaterialDark`
+
Only supported on iOS.
@@ -201,408 +1010,372 @@ Only supported on iOS.
Function which returns a React Element to render as the background of the header. This is useful for using backgrounds such as an image or a gradient.
-#### `headerTintColor`
-
-Tint color for the header. Changes the color of back button and title.
-
-#### `headerLeft`
-
-Function which returns a React Element to display on the left side of the header. This replaces the back button. See `headerBackVisible` to show the back button along side left element.
+
-#### `headerRight`
+Example:
-Function which returns a React Element to display on the right side of the header.
+```js
+ headerBackground: () => (
+
-Note that if you render a custom element by passing a function, animations for the title won't work.
+#### `headerLeft`
-#### `headerTitleAlign`
+Function which returns a React Element to display on the left side of the header. This replaces the back button. See `headerBackVisible` to show the back button along side left element. It receives the following properties in the arguments:
-How to align the header title. Possible values:
+- `tintColor` - The tint color to apply. Defaults to the [theme](themes.md)'s primary color.
+- `canGoBack` - Boolean indicating whether there is a screen to go back to.
+- `label` - Label text for the button. Usually the title of the previous screen.
+- `href` - The `href` to use for the anchor tag on web
-- `left`
-- `center`
+
-Defaults to `left` on platforms other than iOS.
+Example:
-Not supported on iOS. It's always `center` on iOS and cannot be changed.
+```js
+ headerLeft: () => (
+
-Boolean indicating whether to hide the navigation bar during searching. Defaults to `true`.
+Example:
-Only supported on iOS.
+```js
+headerRight: () =>
-##### `headerIconColor`
+- `center`
+
-The color of the search and close icons shown in the header
+Defaults to `left` on platforms other than iOS.
-Only supported on Android.
+Not supported on iOS. It's always `center` on iOS and cannot be changed.
-##### `shouldShowHintSearchIcon`
+#### `headerTitleStyle`
-Whether to show the search hint icon when search bar is focused. Defaults to `true`.
+Style object for header title. Supported properties:
-Only supported on Android.
+- `fontFamily`
+- `fontSize`
+- `fontWeight`
+- `color`
-##### `onBlur`
+
-A callback that gets called when search bar has lost focus.
+Example:
-##### `onCancelButtonPress`
+```js
+ headerTitleStyle: {
+ color: 'blue',
+ fontSize: 22,
+ fontFamily: 'Georgia',
+ fontWeight: 300,
+ },
+```
-A callback that gets called when the cancel button is pressed.
+#### `headerSearchBarOptions`
-##### `onChangeText`
+Options to render a native search bar on iOS. Search bars are rarely static so normally it is controlled by passing an object to `headerSearchBarOptions` navigation option in the component's body.
-A callback that gets called when the text changes. It receives the current text value of the search bar.
+You also need to specify `contentInsetAdjustmentBehavior="automatic"` in your `ScrollView`, `FlatList` etc. If you don't have a `ScrollView`, specify `headerTransparent: false`.
Example:
```js
-const [search, setSearch] = React.useState('');
-
React.useLayoutEffect(() => {
navigation.setOptions({
headerSearchBarOptions: {
- onChangeText: (event) => setSearch(event.nativeEvent.text),
+ // search bar options
},
});
}, [navigation]);
```
-#### `header`
-
-Custom header to use instead of the default header.
-
-This accepts a function that returns a React Element to display as a header. The function receives an object containing the following properties as the argument:
-
-- `navigation` - The navigation object for the current screen.
-- `route` - The route object for the current screen.
-- `options` - The options for the current screen
-- `back` - Options for the back button, contains an object with a `title` property to use for back button label.
-
-Example:
-
-```js
-import { getHeaderTitle } from '@react-navigation/elements';
-
-// ..
-
-header: ({ navigation, route, options, back }) => {
- const title = getHeaderTitle(options, route.name);
-
- return (
-
-Only supported on Android and iOS.
+##### `tintColor`
-#### `statusBarColor`
+The color for the cursor caret and cancel button text.
-Sets the status bar color (similar to the `StatusBar` component). Defaults to initial status bar color.
+Only supported on iOS.
-Only supported on Android.
+
-#### `statusBarTranslucent`
+##### `cancelButtonText`
-Sets the translucency of the status bar (similar to the `StatusBar` component). Defaults to `false`.
+The text to be used instead of default `Cancel` button text.
-Only supported on Android.
+Only supported on iOS.
-#### `contentStyle`
+##### `disableBackButtonOverride`
-Style object for the scene content.
+Whether the back button should close search bar's text input or not. Defaults to `false`.
-#### `customAnimationOnGesture`
+Only supported on Android.
-Whether the gesture to dismiss should use animation provided to `animation` prop. Defaults to `false`.
+##### `hideNavigationBar`
-Doesn't affect the behavior of screens presented modally.
+Boolean indicating whether to hide the navigation bar during searching. Defaults to `true`.
Only supported on iOS.
-#### `fullScreenGestureEnabled`
-
-Whether the gesture to dismiss should work on the whole screen. Using gesture to dismiss with this option results in the same transition animation as `simple_push`. This behavior can be changed by setting `customAnimationOnGesture` prop. Achieving the default iOS animation isn't possible due to platform limitations. Defaults to `false`.
+##### `hideWhenScrolling`
-Doesn't affect the behavior of screens presented modally.
+Boolean indicating whether to hide the search bar when scrolling. Defaults to `true`.
Only supported on iOS.
-#### `gestureEnabled`
+##### `inputType`
-Whether you can use gestures to dismiss this screen. Defaults to `true`. Only supported on iOS.
+The type of the input. Defaults to `"text"`.
-#### `animationTypeForReplace`
+Supported values:
-The type of animation to use when this screen replaces another screen. Defaults to `pop`.
+- `"text"`
+- `"phone"`
+- `"number"`
+- `"email"`
-Supported values:
+Only supported on Android.
-- `push`: the new screen will perform push animation.
-- `pop`: the new screen will perform pop animation.
+##### `obscureBackground`
-#### `animation`
+Boolean indicating whether to obscure the underlying content with semi-transparent overlay. Defaults to `true`.
-How the screen should animate when pushed or popped.
+##### `placeholder`
-Supported values:
+Text displayed when search field is empty.
-- `default`: use the platform default animation
-- `fade`: fade screen in or out
-- `fade_from_bottom`: fade the new screen from bottom
-- `flip`: flip the screen, requires `presentation: "modal"` (iOS only)
-- `simple_push`: default animation, but without shadow and native header transition (iOS only, uses default animation on Android)
-- `slide_from_bottom`: slide in the new screen from bottom
-- `slide_from_right`: slide in the new screen from right (Android only, uses default animation on iOS)
-- `slide_from_left`: slide in the new screen from left (Android only, uses default animation on iOS)
-- `none`: don't animate the screen
+##### `textColor`
-Only supported on Android and iOS.
+The color of the text in the search field.
-#### `presentation`
+
-How should the screen be presented.
+##### `hintTextColor`
-Supported values:
+The color of the hint text in the search field.
-- `card`: the new screen will be pushed onto a stack, which means the default animation will be slide from the side on iOS, the animation on Android will vary depending on the OS version and theme.
-- `modal`: the new screen will be presented modally. this also allows for a nested stack to be rendered inside the screen.
-- `transparentModal`: the new screen will be presented modally, but in addition, the previous screen will stay so that the content below can still be seen if the screen has translucent background.
-- `containedModal`: will use "UIModalPresentationCurrentContext" modal style on iOS and will fallback to "modal" on Android.
-- `containedTransparentModal`: will use "UIModalPresentationOverCurrentContext" modal style on iOS and will fallback to "transparentModal" on Android.
-- `fullScreenModal`: will use "UIModalPresentationFullScreen" modal style on iOS and will fallback to "modal" on Android. A screen using this presentation style can't be dismissed by gesture.
-- `formSheet`: will use "UIModalPresentationFormSheet" modal style on iOS and will fallback to "modal" on Android.
+Only supported on Android.
-Only supported on Android and iOS.
+
-#### `orientation`
+##### `headerIconColor`
-The display orientation to use for the screen.
+The color of the search and close icons shown in the header
-Supported values:
+Only supported on Android.
-- `default` - resolves to "all" without "portrait_down" on iOS. On Android, this lets the system decide the best orientation.
-- `all`: all orientations are permitted.
-- `portrait`: portrait orientations are permitted.
-- `portrait_up`: right-side portrait orientation is permitted.
-- `portrait_down`: upside-down portrait orientation is permitted.
-- `landscape`: landscape orientations are permitted.
-- `landscape_left`: landscape-left orientation is permitted.
-- `landscape_right`: landscape-right orientation is permitted.
+
+
+
+
+There are 3 categories of items that can be displayed in the header:
+
+### Action
+
+A regular button that performs an action when pressed, or shows a menu.
+
+Common properties:
+
+- `type`: Must be `button` or `menu`.
+- `label`: Label of the item. The label is not shown if `icon` is specified. However, it is used by screen readers, or if the header items get collapsed due to lack of space.
+- `labelStyle`: Style object for the label. Supported properties:
+ - `fontFamily`
+ - `fontSize`
+ - `fontWeight`
+ - `color`
+- `icon`: Optional icon to show instead of the label.
+
+ The icon can be an image:
+
+ ```js
+ {
+ type: 'image',
+ source: require('./path/to/image.png'),
+ }
+ ```
+
+ Or a [SF Symbols](https://developer.apple.com/sf-symbols/) name:
+
+ ```js
+ {
+ type: 'sfSymbol',
+ name: 'heart',
+ }
+ ```
+
+- `variant`: Visual variant of the button. Supported values:
+ - `plain` (default)
+ - `done`
+ - `prominent`
+- `tintColor`: Tint color to apply to the item.
+- `disabled`: Whether the item is disabled.
+- `width`: Width of the item.
+- `hidesSharedBackground` (iOS 26+): Whether the background this item may share with other items should be hidden. Setting this to `true` hides the liquid glass background.
+- `sharesBackground` (iOS 26+): Whether this item can share a background with other items.
+- `identifier` (iOS 26+) - An identifier used to match items across transitions.
+- `badge` (iOS 26+): An optional badge to display alongside the item. Supported properties:
+ - `value`: The value to display in the badge. It can be a string or a number.
+ - `style`: Style object for the badge. Supported properties:
+ - `fontFamily`
+ - `fontSize`
+ - `fontWeight`
+ - `color`
+- `accessibilityLabel`: Accessibility label for the item.
+- `accessibilityHint`: Accessibility hint for the item.
+
+Supported properties when `type` is `button`:
+
+- `onPress`: Function to call when the button is pressed.
+- `selected`: Whether the button is in a selected state.
+
+Example:
+
+```js
+unstable_headerRightItems: () => [
+ {
+ type: 'button',
+ label: 'Edit',
+ icon: {
+ type: 'sfSymbol',
+ name: 'pencil',
+ },
+ onPress: () => {
+ // Do something
+ },
+ },
+],
+```
+
+Supported properties when `type` is `menu`:
+
+- `changesSelectionAsPrimaryAction`: Whether the menu is a selection menu. Tapping an item in a selection menu will add a checkmark to the selected item. Defaults to `false`.
+- `menu`: An object containing the menu items. It contains the following properties:
+
+ - `title`: Optional title to show on top of the menu.
+ - `items`: An array of menu items. A menu item can be either an `action` or a `submenu`.
+
+ - `action`: An object with the following properties:
+
+ - `type`: Must be `action`.
+ - `label`: Label of the menu item.
+ - `icon`: Optional icon to show alongside the label. The icon can be a [SF Symbols](https://developer.apple.com/sf-symbols/) name:
+
+ ```js
+ {
+ type: 'sfSymbol',
+ name: 'trash',
+ }
+ ```
+
+ - `onPress`: Function to call when the menu item is pressed.
+ - `state`: Optional state of the menu item. Supported values:
+ - `on`
+ - `off`
+ - `mixed`
+ - `disabled`: Whether the menu item is disabled.
+ - `destructive`: Whether the menu item is styled as destructive.
+ - `hidden`: Whether the menu item is hidden.
+ - `keepsMenuPresented`: Whether to keep the menu open after selecting this item. Defaults to `false`.
+ - `discoverabilityLabel`: An elaborated title that explains the purpose of the action.
+
+ - `submenu`: An object with the following properties:
+
+ - `type`: Must be `submenu`.
+ - `label`: Label of the submenu item.
+ - `icon`: Optional icon to show alongside the label. The icon can be a [SF Symbols](https://developer.apple.com/sf-symbols/) name:
+
+ ```js
+ {
+ type: 'sfSymbol',
+ name: 'pencil',
+ }
+ ```
+
+ - `items`: An array of menu items (can be either `action` or `submenu`).
+
+Example:
+
+```js
+unstable_headerRightItems: () => [
+ {
+ type: 'menu',
+ label: 'Options',
+ icon: {
+ type: 'sfSymbol',
+ name: 'ellipsis',
+ },
+ menu: {
+ title: 'Options',
+ items: [
+ {
+ type: 'action',
+ label: 'Edit',
+ icon: {
+ type: 'sfSymbol',
+ name: 'pencil',
+ },
+ onPress: () => {
+ // Do something
+ },
+ },
+ {
+ type: 'submenu',
+ label: 'More',
+ items: [
+ {
+ type: 'action',
+ label: 'Delete',
+ destructive: true,
+ onPress: () => {
+ // Do something
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+],
+```
+
+### Spacing
+
+An item to add spacing between other items in the header.
+
+Supported properties:
+
+- `type`: Must be `spacing`.
+- `spacing`: Amount of spacing to add.
+
+```js
+unstable_headerRightItems: () => [
+ {
+ type: 'button',
+ label: 'Edit',
+ onPress: () => {
+ // Do something
+ },
+ },
+ {
+ type: 'spacing',
+ spacing: 10,
+ },
+ {
+ type: 'button',
+ label: 'Delete',
+ onPress: () => {
+ // Do something
+ },
+ },
+],
+```
+
+### Custom
+
+A custom item to display any React Element in the header.
+
+Supported properties:
+
+- `type`: Must be `custom`.
+- `element`: A React Element to display as the item.
+- `hidesSharedBackground`: Whether the background this item may share with other items in the bar should be hidden. Setting this to `true` hides the liquid glass background on iOS 26+.
+
+Example:
+
+```js
+unstable_headerRightItems: () => [
+ {
+ type: 'custom',
+ element:
-