diff --git a/.changeset/ios-prominent-tab-role.md b/.changeset/ios-prominent-tab-role.md new file mode 100644 index 00000000..340cc1d1 --- /dev/null +++ b/.changeset/ios-prominent-tab-role.md @@ -0,0 +1,5 @@ +--- +'react-native-bottom-tabs': minor +--- + +Add the `prominent` tab role (iOS 27+), and fix iOS 27 tabs keeping their selected tint after switching tabs or minimizing the tab bar diff --git a/docs/docs/docs/guides/standalone-usage.mdx b/docs/docs/docs/guides/standalone-usage.mdx index d9f02c43..29c06bde 100644 --- a/docs/docs/docs/guides/standalone-usage.mdx +++ b/docs/docs/docs/guides/standalone-usage.mdx @@ -241,7 +241,7 @@ Each route in the `routes` array can have the following properties: - `activeTintColor`: Custom active tint color for this specific tab - `lazy`: Whether to lazy load this tab's content - `freezeOnBlur`: Whether to freeze the tab's content when it's not visible -- `role`: A value that defines the purpose of the tab +- `role`: A value that defines the purpose of the tab on iOS: `'search'` (iOS 18+) or `'prominent'` (iOS 27+, displayed as a regular tab on earlier versions) - `style`: Style object for the component wrapping the screen content - `preventsDefault`: Whether to prevent default tab switching behavior when pressed diff --git a/docs/docs/docs/guides/usage-with-react-navigation.mdx b/docs/docs/docs/guides/usage-with-react-navigation.mdx index 78e49d55..8ff246ac 100644 --- a/docs/docs/docs/guides/usage-with-react-navigation.mdx +++ b/docs/docs/docs/guides/usage-with-react-navigation.mdx @@ -398,11 +398,12 @@ Test ID for the tab item. This can be used to find the tab item in the native vi #### `role` -A value that defines the purpose of the tab. This can be used to pin and separate search tabs +A value that defines the purpose of the tab. Available options: -- `search` - The search role. +- `search` - Marks the tab as the search tab, which the system can pin to the trailing end of the tab bar. On iOS 27+, it may also receive the prominent treatment when no tab has the `prominent` role. +- `prominent` - Gives the tab more visual emphasis than the others. Only one tab can be prominent. Requires building with the iOS 27 SDK, and on earlier iOS versions the tab is displayed as a regular tab. #### `sceneStyle` diff --git a/packages/example-shared/src/App.tsx b/packages/example-shared/src/App.tsx index 5e70681a..420d3427 100644 --- a/packages/example-shared/src/App.tsx +++ b/packages/example-shared/src/App.tsx @@ -28,6 +28,7 @@ import SixTabs from './Examples/SixTabs'; import FourTabsRTL from './Examples/FourTabsRTL'; import MaterialBottomTabs from './Examples/MaterialBottomTabs'; import SFSymbols from './Examples/SFSymbols'; +import Roles from './Examples/Roles'; import LabeledTabs from './Examples/Labeled'; import NativeBottomTabs from './Examples/NativeBottomTabs'; import TintColorsExample from './Examples/TintColors'; @@ -99,6 +100,7 @@ const examples = [ { component: FourTabs, name: 'Four Tabs' }, { component: FiveTabs, name: 'Five Tabs' }, { component: SixTabs, name: 'Six Tabs' }, + { component: Roles, name: 'Roles', platform: 'ios' }, { component: SFSymbols, name: 'SF Symbols', diff --git a/packages/example-shared/src/Examples/Roles.tsx b/packages/example-shared/src/Examples/Roles.tsx new file mode 100644 index 00000000..ddfbff4b --- /dev/null +++ b/packages/example-shared/src/Examples/Roles.tsx @@ -0,0 +1,107 @@ +import { useMemo, useState } from 'react'; +import { Button, StyleSheet, Switch, Text, View } from 'react-native'; +import TabView, { SceneMap } from 'react-native-bottom-tabs'; +import type { TabRole } from 'react-native-bottom-tabs'; +import { Article } from '../Screens/Article'; +import { Albums } from '../Screens/Albums'; +import { Contacts } from '../Screens/Contacts'; + +const renderScene = SceneMap({ + article: Article, + albums: Albums, + role: Contacts, +}); + +export default function Roles() { + const [role, setRole] = useState('search'); + const [bakedTintColors, setBakedTintColors] = useState(false); + const [index, setIndex] = useState(0); + const routes = useMemo( + () => [ + { + key: 'article', + title: 'Article', + focusedIcon: { sfSymbol: 'document' }, + }, + { + key: 'albums', + title: 'Albums', + focusedIcon: { sfSymbol: 'square.grid.2x2' }, + }, + { + key: 'role', + title: role === 'search' ? 'Search' : 'Contacts', + focusedIcon: { + sfSymbol: + role === 'search' ? 'magnifyingglass' : 'person.crop.circle', + }, + role, + testID: `roles-${role}-tab`, + }, + ], + [role] + ); + + const selectRole = (nextRole: TabRole) => { + setIndex(0); + setRole(nextRole); + }; + + return ( + + + +