From 085239596477801b9c96c1968df8d0fc95d05857 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 20 Oct 2025 19:20:58 +0000 Subject: [PATCH 1/4] docs: add web platform support guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add comprehensive documentation for web platform support showing how to use platform-specific files (.web.ts/.native.ts) or custom tab bars to provide JavaScript-based tab implementations on web. The guide includes: - Explanation of why web requires a different approach - Three implementation approaches with pros/cons - Code examples for each approach - Icon library recommendations for cross-platform support - Styling considerations between native and web platforms Updated README and introduction to reference the new web platform guide. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- README.md | 2 + .../docs/getting-started/introduction.mdx | 6 + docs/docs/docs/guides/_meta.json | 2 +- docs/docs/docs/guides/web-platform-support.md | 264 ++++++++++++++++++ 4 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 docs/docs/docs/guides/web-platform-support.md diff --git a/README.md b/README.md index ca2c390d..1a5befb3 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ https://github.com/user-attachments/assets/09e96ac3-827d-4ac0-add0-e7b88ee9197c | **tvOS** | | | **macOS** | | +> **Note:** This library uses native platform primitives which are not available on web. For web support, see the [Web Platform Support guide](https://oss.callstack.com/react-native-bottom-tabs/docs/guides/web-platform-support) in the documentation. + ## Package Versions | Name | Latest Version | diff --git a/docs/docs/docs/getting-started/introduction.mdx b/docs/docs/docs/getting-started/introduction.mdx index c42dadb8..94d757ee 100644 --- a/docs/docs/docs/getting-started/introduction.mdx +++ b/docs/docs/docs/getting-started/introduction.mdx @@ -10,3 +10,9 @@ React Native Bottom Tabs is a library that provides a native bottom tabs experie - visionOS - tvOS - macOS + +:::note + +For **web** platform support, native tabs are not available. See the [Web Platform Support](/docs/guides/web-platform-support) guide for JavaScript-based alternatives. + +::: diff --git a/docs/docs/docs/guides/_meta.json b/docs/docs/docs/guides/_meta.json index 23e1a0c2..fa7dd987 100644 --- a/docs/docs/docs/guides/_meta.json +++ b/docs/docs/docs/guides/_meta.json @@ -1 +1 @@ -["usage-with-react-navigation", "usage-with-expo-router", "usage-with-one", "standalone-usage", {"type": "divider"}, "handling-scrollview-insets", "usage-with-vector-icons", {"type": "divider"}, "android-native-styling", "edge-to-edge-support"] +["usage-with-react-navigation", "usage-with-expo-router", "usage-with-one", "standalone-usage", {"type": "divider"}, "web-platform-support", "handling-scrollview-insets", "usage-with-vector-icons", {"type": "divider"}, "android-native-styling", "edge-to-edge-support"] diff --git a/docs/docs/docs/guides/web-platform-support.md b/docs/docs/docs/guides/web-platform-support.md new file mode 100644 index 00000000..9cdad7a1 --- /dev/null +++ b/docs/docs/docs/guides/web-platform-support.md @@ -0,0 +1,264 @@ +# Web Platform Support + +React Native Bottom Tabs uses native platform primitives (SwiftUI on iOS and Material Design on Android) which are not available on web. For web applications, you'll need to use JavaScript-based tab implementations as a fallback. + +## Why Web Requires a Different Approach + +Native bottom tabs rely on platform-specific UI components that don't exist in web browsers. React Native Web translates React Native components to web equivalents, but native modules require explicit web implementations. + +:::note + +Web support requires using platform-specific files or a custom tab bar implementation. This guide shows you both approaches. + +::: + +## Approach 1: Platform-Specific Files (Recommended) + +React Native's Metro bundler automatically resolves platform-specific files. You can create separate implementations for native platforms and web. + +### File Structure + +``` +src/ +├── navigation/ +│ ├── TabNavigator.native.tsx # Used on iOS/Android +│ └── TabNavigator.web.tsx # Used on web +``` + +### Native Implementation + +```tsx title="TabNavigator.native.tsx" +import { createNativeBottomTabNavigator } from '@bottom-tabs/react-navigation'; +import { HomeScreen } from '../screens/HomeScreen'; +import { SettingsScreen } from '../screens/SettingsScreen'; + +const Tabs = createNativeBottomTabNavigator(); + +export function TabNavigator() { + return ( + + ({ sfSymbol: 'house' }), + }} + /> + ({ sfSymbol: 'gear' }), + }} + /> + + ); +} +``` + +### Web Implementation + +For web, use `@react-navigation/bottom-tabs` which provides a JavaScript-based implementation: + +```bash +npm install @react-navigation/bottom-tabs +``` + +```tsx title="TabNavigator.web.tsx" +import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; +import { HomeScreen } from '../screens/HomeScreen'; +import { SettingsScreen } from '../screens/SettingsScreen'; + +const Tab = createBottomTabNavigator(); + +export function TabNavigator() { + return ( + + ( + + ), + }} + /> + ( + + ), + }} + /> + + ); +} +``` + +### Using in Your App + +Import the component normally - React Native will automatically use the correct file: + +```tsx title="App.tsx" +import { NavigationContainer } from '@react-navigation/native'; +import { TabNavigator } from './navigation/TabNavigator'; + +export default function App() { + return ( + + + + ); +} +``` + +## Approach 2: Custom Tab Bar with Standalone Usage + +If you're using the standalone `TabView` component, you can provide a custom `tabBar` prop that renders a web-compatible implementation. + +```tsx +import { Platform } from 'react-native'; +import TabView from 'react-native-bottom-tabs'; + +function MyTabs() { + const [index, setIndex] = React.useState(0); + const [routes] = React.useState([ + { key: 'home', title: 'Home' }, + { key: 'settings', title: 'Settings' }, + ]); + + const renderScene = SceneMap({ + home: HomeScreen, + settings: SettingsScreen, + }); + + return ( + + ); +} +``` + +### Example Custom Web Tab Bar + +```tsx +function CustomWebTabBar() { + return ( + + + Home + + + Settings + + + ); +} + +const styles = StyleSheet.create({ + tabBar: { + flexDirection: 'row', + backgroundColor: '#fff', + borderTopWidth: 1, + borderTopColor: '#e0e0e0', + height: 60, + }, + tab: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, +}); +``` + +## Approach 3: Conditional Platform Rendering + +For simpler cases, you can conditionally render different navigators based on platform: + +```tsx +import { Platform } from 'react-native'; +import { createNativeBottomTabNavigator } from '@bottom-tabs/react-navigation'; +import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; + +const NativeTabs = createNativeBottomTabNavigator(); +const JSTabs = createBottomTabNavigator(); + +const Tabs = Platform.OS === 'web' ? JSTabs : NativeTabs; + +export function TabNavigator() { + return ( + + + + + ); +} +``` + +:::warning + +This approach requires installing both `@bottom-tabs/react-navigation` and `@react-navigation/bottom-tabs`, which increases bundle size for all platforms. + +::: + +## Styling Considerations + +When implementing web tabs, consider these styling differences: + +### Native Platforms +- Use `sfSymbol` for iOS icons +- Platform-specific appearance attributes +- Native gestures and animations + +### Web Platform +- Use web-compatible icon libraries (e.g., `react-icons`, `@expo/vector-icons`) +- CSS-based styling and animations +- Standard web accessibility practices + +## Icon Libraries for Web + +For web compatibility, use icon libraries that work across all platforms: + +### Expo Vector Icons + +```tsx +import { Ionicons } from '@expo/vector-icons'; + +options={{ + tabBarIcon: ({ color, size }) => ( + + ), +}} +``` + +### React Icons + +```tsx +import { FiHome } from 'react-icons/fi'; + +options={{ + tabBarIcon: ({ color }) => , +}} +``` + +## Summary + +| Approach | Pros | Cons | +|----------|------|------| +| **Platform-Specific Files** | Clean separation, optimal bundle size | Requires maintaining two implementations | +| **Custom Tab Bar** | Full control, single codebase | More code to maintain | +| **Conditional Rendering** | Simple to understand | Both libraries in bundle | + +For most projects, **platform-specific files** provide the best balance of code organization, bundle size, and developer experience. + +## Additional Resources + +- [React Navigation Bottom Tabs](https://reactnavigation.org/docs/bottom-tab-navigator/) +- [React Native Web Documentation](https://necolas.github.io/react-native-web/) +- [Metro Bundler Platform-Specific Extensions](https://reactnative.dev/docs/platform-specific-code#platform-specific-extensions) From 4694e146e6f1a0bfd9b3fab5196262597a169335 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 20 Oct 2025 19:25:28 +0000 Subject: [PATCH 2/4] docs: simplify web platform support guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Streamline the guide to focus only on platform-specific files (.web.ts/.native.ts) approach. Removed alternative approaches to keep the documentation concise and easier to follow. Changes: - Removed "Custom Tab Bar" approach - Removed "Conditional Platform Rendering" approach - Simplified icon support section - Removed comparison table - Reduced from 265 to 138 lines 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- docs/docs/docs/guides/web-platform-support.md | 137 +----------------- 1 file changed, 5 insertions(+), 132 deletions(-) diff --git a/docs/docs/docs/guides/web-platform-support.md b/docs/docs/docs/guides/web-platform-support.md index 9cdad7a1..2b95a477 100644 --- a/docs/docs/docs/guides/web-platform-support.md +++ b/docs/docs/docs/guides/web-platform-support.md @@ -2,17 +2,7 @@ React Native Bottom Tabs uses native platform primitives (SwiftUI on iOS and Material Design on Android) which are not available on web. For web applications, you'll need to use JavaScript-based tab implementations as a fallback. -## Why Web Requires a Different Approach - -Native bottom tabs rely on platform-specific UI components that don't exist in web browsers. React Native Web translates React Native components to web equivalents, but native modules require explicit web implementations. - -:::note - -Web support requires using platform-specific files or a custom tab bar implementation. This guide shows you both approaches. - -::: - -## Approach 1: Platform-Specific Files (Recommended) +## How It Works React Native's Metro bundler automatically resolves platform-specific files. You can create separate implementations for native platforms and web. @@ -114,118 +104,11 @@ export default function App() { } ``` -## Approach 2: Custom Tab Bar with Standalone Usage - -If you're using the standalone `TabView` component, you can provide a custom `tabBar` prop that renders a web-compatible implementation. - -```tsx -import { Platform } from 'react-native'; -import TabView from 'react-native-bottom-tabs'; - -function MyTabs() { - const [index, setIndex] = React.useState(0); - const [routes] = React.useState([ - { key: 'home', title: 'Home' }, - { key: 'settings', title: 'Settings' }, - ]); - - const renderScene = SceneMap({ - home: HomeScreen, - settings: SettingsScreen, - }); - - return ( - - ); -} -``` - -### Example Custom Web Tab Bar - -```tsx -function CustomWebTabBar() { - return ( - - - Home - - - Settings - - - ); -} - -const styles = StyleSheet.create({ - tabBar: { - flexDirection: 'row', - backgroundColor: '#fff', - borderTopWidth: 1, - borderTopColor: '#e0e0e0', - height: 60, - }, - tab: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - }, -}); -``` - -## Approach 3: Conditional Platform Rendering - -For simpler cases, you can conditionally render different navigators based on platform: - -```tsx -import { Platform } from 'react-native'; -import { createNativeBottomTabNavigator } from '@bottom-tabs/react-navigation'; -import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; - -const NativeTabs = createNativeBottomTabNavigator(); -const JSTabs = createBottomTabNavigator(); - -const Tabs = Platform.OS === 'web' ? JSTabs : NativeTabs; - -export function TabNavigator() { - return ( - - - - - ); -} -``` - -:::warning - -This approach requires installing both `@bottom-tabs/react-navigation` and `@react-navigation/bottom-tabs`, which increases bundle size for all platforms. - -::: - -## Styling Considerations - -When implementing web tabs, consider these styling differences: +## Icon Support -### Native Platforms -- Use `sfSymbol` for iOS icons -- Platform-specific appearance attributes -- Native gestures and animations +On web, you cannot use SF Symbols. Instead, use cross-platform icon libraries: -### Web Platform -- Use web-compatible icon libraries (e.g., `react-icons`, `@expo/vector-icons`) -- CSS-based styling and animations -- Standard web accessibility practices - -## Icon Libraries for Web - -For web compatibility, use icon libraries that work across all platforms: - -### Expo Vector Icons +**Expo Vector Icons** (recommended): ```tsx import { Ionicons } from '@expo/vector-icons'; @@ -237,7 +120,7 @@ options={{ }} ``` -### React Icons +**React Icons:** ```tsx import { FiHome } from 'react-icons/fi'; @@ -247,16 +130,6 @@ options={{ }} ``` -## Summary - -| Approach | Pros | Cons | -|----------|------|------| -| **Platform-Specific Files** | Clean separation, optimal bundle size | Requires maintaining two implementations | -| **Custom Tab Bar** | Full control, single codebase | More code to maintain | -| **Conditional Rendering** | Simple to understand | Both libraries in bundle | - -For most projects, **platform-specific files** provide the best balance of code organization, bundle size, and developer experience. - ## Additional Resources - [React Navigation Bottom Tabs](https://reactnavigation.org/docs/bottom-tab-navigator/) From 770a69df781304bbf4823f2c60cda7c3c293e420 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 20 Oct 2025 19:28:37 +0000 Subject: [PATCH 3/4] docs: update icon examples to match codebase patterns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated web platform support guide to reflect actual icon handling patterns used in the example app: - Show Platform.OS conditional for iOS SF Symbols vs Android/web PNG assets - Use require() for PNG/SVG files instead of icon component libraries - Add focused/unfocused icon pattern example - Remove icon library examples in favor of image asset approach - Demonstrate cross-platform pattern that works on iOS, Android, and web This matches the patterns in apps/example/src/Examples/ directory. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- docs/docs/docs/guides/web-platform-support.md | 67 ++++++++++++++----- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/docs/docs/docs/guides/web-platform-support.md b/docs/docs/docs/guides/web-platform-support.md index 2b95a477..9a3c1b6a 100644 --- a/docs/docs/docs/guides/web-platform-support.md +++ b/docs/docs/docs/guides/web-platform-support.md @@ -19,6 +19,7 @@ src/ ```tsx title="TabNavigator.native.tsx" import { createNativeBottomTabNavigator } from '@bottom-tabs/react-navigation'; +import { Platform } from 'react-native'; import { HomeScreen } from '../screens/HomeScreen'; import { SettingsScreen } from '../screens/SettingsScreen'; @@ -31,14 +32,20 @@ export function TabNavigator() { name="Home" component={HomeScreen} options={{ - tabBarIcon: () => ({ sfSymbol: 'house' }), + tabBarIcon: () => + Platform.OS === 'ios' + ? { sfSymbol: 'house' } + : require('../assets/icons/home.png'), }} /> ({ sfSymbol: 'gear' }), + tabBarIcon: () => + Platform.OS === 'ios' + ? { sfSymbol: 'gear' } + : require('../assets/icons/settings.png'), }} /> @@ -48,7 +55,7 @@ export function TabNavigator() { ### Web Implementation -For web, use `@react-navigation/bottom-tabs` which provides a JavaScript-based implementation: +For web, install `@react-navigation/bottom-tabs` which provides a JavaScript-based implementation: ```bash npm install @react-navigation/bottom-tabs @@ -68,18 +75,14 @@ export function TabNavigator() { name="Home" component={HomeScreen} options={{ - tabBarIcon: ({ color, size }) => ( - - ), + tabBarIcon: () => require('../assets/icons/home.png'), }} /> ( - - ), + tabBarIcon: () => require('../assets/icons/settings.png'), }} /> @@ -106,27 +109,55 @@ export default function App() { ## Icon Support -On web, you cannot use SF Symbols. Instead, use cross-platform icon libraries: +Icons can be provided using different methods depending on your platform: -**Expo Vector Icons** (recommended): +### SF Symbols (iOS only) ```tsx -import { Ionicons } from '@expo/vector-icons'; +options={{ + tabBarIcon: () => ({ sfSymbol: 'house' }), +}} +``` + +### Image Assets (PNG/SVG) + +Use `require()` for PNG or SVG files. This works on iOS, Android, and web: + +```tsx +options={{ + tabBarIcon: () => require('../assets/icons/home.png'), +}} +``` +```tsx options={{ - tabBarIcon: ({ color, size }) => ( - - ), + tabBarIcon: () => require('../assets/icons/home.svg'), }} ``` -**React Icons:** +### Cross-Platform Pattern + +For a single codebase supporting iOS, Android, and web, use Platform-specific conditionals: ```tsx -import { FiHome } from 'react-icons/fi'; +import { Platform } from 'react-native'; options={{ - tabBarIcon: ({ color }) => , + tabBarIcon: () => + Platform.OS === 'ios' + ? { sfSymbol: 'house' } + : require('../assets/icons/home.png'), +}} +``` + +### Focused/Unfocused Icons + +```tsx +options={{ + tabBarIcon: ({ focused }) => + focused + ? require('../assets/icons/home-filled.png') + : require('../assets/icons/home-outline.png'), }} ``` From e566af4b4ada7b0b0a0ad9ad9018d19a3806c96e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwa=C5=9Bniewski?= Date: Fri, 24 Oct 2025 09:40:23 +0200 Subject: [PATCH 4/4] Apply suggestion from @okwasniewski --- docs/docs/docs/guides/web-platform-support.md | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/docs/docs/docs/guides/web-platform-support.md b/docs/docs/docs/guides/web-platform-support.md index 9a3c1b6a..37f3337a 100644 --- a/docs/docs/docs/guides/web-platform-support.md +++ b/docs/docs/docs/guides/web-platform-support.md @@ -107,59 +107,6 @@ export default function App() { } ``` -## Icon Support - -Icons can be provided using different methods depending on your platform: - -### SF Symbols (iOS only) - -```tsx -options={{ - tabBarIcon: () => ({ sfSymbol: 'house' }), -}} -``` - -### Image Assets (PNG/SVG) - -Use `require()` for PNG or SVG files. This works on iOS, Android, and web: - -```tsx -options={{ - tabBarIcon: () => require('../assets/icons/home.png'), -}} -``` - -```tsx -options={{ - tabBarIcon: () => require('../assets/icons/home.svg'), -}} -``` - -### Cross-Platform Pattern - -For a single codebase supporting iOS, Android, and web, use Platform-specific conditionals: - -```tsx -import { Platform } from 'react-native'; - -options={{ - tabBarIcon: () => - Platform.OS === 'ios' - ? { sfSymbol: 'house' } - : require('../assets/icons/home.png'), -}} -``` - -### Focused/Unfocused Icons - -```tsx -options={{ - tabBarIcon: ({ focused }) => - focused - ? require('../assets/icons/home-filled.png') - : require('../assets/icons/home-outline.png'), -}} -``` ## Additional Resources