From b41d77b8452d24400a0bb129d351f6e85432db9e Mon Sep 17 00:00:00 2001 From: D N <4661784+retyui@users.noreply.github.com> Date: Sun, 20 Sep 2026 00:11:44 +0200 Subject: [PATCH 1/7] New role `prominent` (SDK27+) --- .../docs/docs/guides/usage-with-react-navigation.mdx | 1 + .../ios/TabView/NewTabView.swift | 2 +- .../react-native-bottom-tabs/ios/TabViewImpl.swift | 2 +- .../react-native-bottom-tabs/ios/TabViewProps.swift | 12 +++++++++++- packages/react-native-bottom-tabs/src/types.ts | 2 +- 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/docs/docs/docs/guides/usage-with-react-navigation.mdx b/docs/docs/docs/guides/usage-with-react-navigation.mdx index 78e49d55..2622b962 100644 --- a/docs/docs/docs/guides/usage-with-react-navigation.mdx +++ b/docs/docs/docs/guides/usage-with-react-navigation.mdx @@ -403,6 +403,7 @@ A value that defines the purpose of the tab. This can be used to pin and separat Available options: - `search` - The search role. +- `prominent` - Mark one tab as visually more important than the others (`SDK 27+`). #### `sceneStyle` diff --git a/packages/react-native-bottom-tabs/ios/TabView/NewTabView.swift b/packages/react-native-bottom-tabs/ios/TabView/NewTabView.swift index 2f18f210..c817bc7e 100644 --- a/packages/react-native-bottom-tabs/ios/TabView/NewTabView.swift +++ b/packages/react-native-bottom-tabs/ios/TabView/NewTabView.swift @@ -38,7 +38,7 @@ struct NewTabView: AnyTabView { onSelect: onSelect ) - Tab(value: tabData.key, role: tabData.role?.convert()) { + Tab(value: tabData.key, role: tabData.role.flatMap { $0.convert() }) { RepresentableView(view: child.view) .ignoresSafeArea(.container, edges: .all) .tabAppear(using: context) diff --git a/packages/react-native-bottom-tabs/ios/TabViewImpl.swift b/packages/react-native-bottom-tabs/ios/TabViewImpl.swift index 68053e1f..14286c69 100644 --- a/packages/react-native-bottom-tabs/ios/TabViewImpl.swift +++ b/packages/react-native-bottom-tabs/ios/TabViewImpl.swift @@ -233,7 +233,7 @@ struct TabViewImpl: View { let preservesOriginalIconColors = preservesOriginalIconColors(tabData: tabData) let useBakedTintColors = shouldUseExperimentalBakedTintColors(props: props) let shouldRenderLabelIntoImage = - props.hasCustomTintColors && props.labeled && tabData.role != .search && icon != nil + props.hasCustomTintColors && props.labeled && tabData.role == nil && icon != nil item.accessibilityLabel = tabData.title diff --git a/packages/react-native-bottom-tabs/ios/TabViewProps.swift b/packages/react-native-bottom-tabs/ios/TabViewProps.swift index dd4c3c88..19e2290e 100644 --- a/packages/react-native-bottom-tabs/ios/TabViewProps.swift +++ b/packages/react-native-bottom-tabs/ios/TabViewProps.swift @@ -30,12 +30,22 @@ internal enum MinimizeBehavior: String { public enum TabBarRole: String { case search + case prominent @available(iOS 18, macOS 15, visionOS 2, tvOS 18, *) - func convert() -> TabRole { + func convert() -> TabRole? { switch self { case .search: return .search + case .prominent: + #if compiler(>=6.4) + if #available(iOS 27, macOS 27, visionOS 27, tvOS 27, *) { + return .prominent + } + #endif + // `.prominent` role was introduced in iOS 27 SDK; ignore it on older OS versions + // instead of crashing or silently mapping to the wrong role. + return nil } } } diff --git a/packages/react-native-bottom-tabs/src/types.ts b/packages/react-native-bottom-tabs/src/types.ts index 3f4eda80..84223786 100644 --- a/packages/react-native-bottom-tabs/src/types.ts +++ b/packages/react-native-bottom-tabs/src/types.ts @@ -5,7 +5,7 @@ export type IconSource = string | ImageSourcePropType; export type AppleIcon = { sfSymbol: SFSymbol }; -export type TabRole = 'search'; +export type TabRole = 'search' | 'prominent'; export type IconRenderingMode = 'automatic' | 'original'; From b1927fe6a36cf71fea9f9d8d01df40040c218231 Mon Sep 17 00:00:00 2001 From: Thiago Brezinski Date: Tue, 22 Sep 2026 14:13:05 +0100 Subject: [PATCH 2/7] Add iOS tab role example - Add an example for switching between search and prominent tab roles - Demonstrate experimental baked tint colors --- packages/example-shared/src/App.tsx | 2 + .../example-shared/src/Examples/Roles.tsx | 109 ++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 packages/example-shared/src/Examples/Roles.tsx 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..319f1d22 --- /dev/null +++ b/packages/example-shared/src/Examples/Roles.tsx @@ -0,0 +1,109 @@ +import { 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); + + return ( + + + +