Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,16 @@ jobs:
- name: Build package
run: yarn prepare

build-web:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Setup
uses: ./.github/actions/setup

- name: Build example for Web
run: |
yarn example expo export --platform web
# build-web:
# runs-on: ubuntu-latest
#
# steps:
# - name: Checkout
# uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
#
# - name: Setup
# uses: ./.github/actions/setup
#
# - name: Build example for Web
# run: |
# yarn example expo export --platform web
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2021 Janic Duplessis
Copyright (c) 2025 AppAndFlow

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
24 changes: 15 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
# @th3rdwave/react-navigation-bottom-sheet
# @appandflow/react-navigation-bottom-sheet

Bottom sheet navigator for React Navigation.

Can also work with Expo Router [example](./example/expo-router/)

Integrates [@gorhom/bottom-sheet](https://github.com/gorhom/react-native-bottom-sheet) with [React Navigation](https://github.com/react-navigation/react-navigation).

## Installation

```sh
yarn add @th3rdwave/react-navigation-bottom-sheet @react-navigation/native @gorhom/bottom-sheet
yarn add @appandflow/react-navigation-bottom-sheet @react-navigation/native @gorhom/bottom-sheet
```

If you don't have those already, you will also need to install the [@gorhom/bottom-sheet dependencies](https://gorhom.github.io/react-native-bottom-sheet/#dependencies) react-native-reanimated and react-native-gesture-handler.

## Usage

```js
import { createBottomSheetNavigator } from "@th3rdwave/react-navigation-bottom-sheet";
import { createBottomSheetNavigator } from '@appandflow/react-navigation-bottom-sheet';

// ...

const BottomSheet = createBottomSheetNavigator();

<BottomSheet.Navigator
// Default options
screenOptions={{ snapPoints: ["60%", "90%"] }}
screenOptions={{ snapPoints: ['60%', '90%'] }}
>
{/* The first screen should be your app content */}
<BottomSheet.Screen name="app" component={MyApp} />
Expand All @@ -32,18 +34,22 @@ const BottomSheet = createBottomSheetNavigator();
name="secondSheet"
component={SecondSheetComponent}
// Can pass any prop from @gorhom/bottom-sheet's BottomSheetModal
options={{ snapPoints: [200, "100%"], index: 1 }}
options={{ snapPoints: [200, '100%'], index: 1 }}
/>
</BottomSheet.Navigator>;

// ...

// Open like any regular react-navigation screen.
navigation.navigate("firstSheet", { id: 1 });

navigation.navigate('firstSheet', { id: 1 });
```

See the [example app](./example/src/SimpleExample.tsx) for full usage details.
See the React Navigation [example app](./example/react-navigation/src/SimpleExample.tsx) or the Expo Router example under [`example/expo-router/app`](./example/expo-router/app) for full usage details.

### Running the examples

- `yarn example:react-navigation` – launches the classic React Navigation sample
- `yarn example:expo-router` – launches the Expo Router sample

## API

Expand All @@ -52,7 +58,7 @@ See the [example app](./example/src/SimpleExample.tsx) for full usage details.
#### `snapPoints`

```ts
Array<string | number>
Array<string | number>;
```

Points for the bottom sheet to snap to, points should be sorted from bottom to top. It accepts array of number and string.
Expand Down
6 changes: 6 additions & 0 deletions example/expo-router/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

# @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb
# The following patterns were generated by expo-cli

expo-env.d.ts
# @end expo-cli
36 changes: 36 additions & 0 deletions example/expo-router/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"expo": {
"name": "@appandflow/react-navigation-bottom-sheet expo-router",
"slug": "appandflow-react-navigation-bottom-sheet-expo-router",
"description": "Expo Router example app for @appandflow/react-navigation-bottom-sheet",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "light",
"newArchEnabled": true,
"splash": {
"image": "./assets/splash-icon.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"ios": {
"supportsTablet": true,
"bundleIdentifier": "testlibrary.example.exporouter"
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#ffffff"
},
"edgeToEdgeEnabled": true,
"package": "testlibrary.example.exporouter"
},
"web": {
"favicon": "./assets/favicon.png"
},
"plugins": ["expo-router"],
"experiments": {
"typedRoutes": true
}
}
}
40 changes: 40 additions & 0 deletions example/expo-router/app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { BottomSheetBackdrop } from '@gorhom/bottom-sheet';
import type { BottomSheetBackdropProps } from '@gorhom/bottom-sheet';
import { createBottomSheetNavigator } from '@appandflow/react-navigation-bottom-sheet';
import { withLayoutContext } from 'expo-router';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import type { BottomSheetParamList } from '../utils/types';

const BottomSheetNavigator = createBottomSheetNavigator<BottomSheetParamList>();

const BottomSheet = withLayoutContext(BottomSheetNavigator.Navigator);

const renderBackdrop = (props: BottomSheetBackdropProps) => (
<BottomSheetBackdrop {...props} appearsOnIndex={0} disappearsOnIndex={-1} />
);

export const unstable_settings = {
initialRouteName: 'index',
};

export default function RootLayout() {
return (
<GestureHandlerRootView>
<BottomSheet
screenOptions={{
backdropComponent: renderBackdrop,
enableDynamicSizing: false,
}}
>
<BottomSheet.Screen name="index" />
<BottomSheet.Screen name="sheet" />
<BottomSheet.Screen
name="big-sheet"
options={{
snapPoints: ['60%', '80%'],
}}
/>
</BottomSheet>
</GestureHandlerRootView>
);
}
1 change: 1 addition & 0 deletions example/expo-router/app/big-sheet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './sheet-screen';
24 changes: 24 additions & 0 deletions example/expo-router/app/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Button, Text, View } from 'react-native';
import { styles } from '../utils/styles';
import { Link, useRouter } from 'expo-router';

export default function HomeScreen() {
const router = useRouter();
return (
<View style={styles.container}>
<Text>Home Screen</Text>
<View style={styles.spacer} />
{/* @ts-ignore - Suppress the error since the runtime will work fine */}
<Link href="/sheet?id=1" asChild>
<Button title="Open sheet" />
</Link>
<View style={styles.spacer} />
<Button
title="Open a big sheet"
onPress={() => {
router.push('/big-sheet?id=1');
}}
/>
</View>
);
}
52 changes: 52 additions & 0 deletions example/expo-router/app/sheet-screen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Button, Text, View } from 'react-native';
import { useBottomSheetNavigation } from '@appandflow/react-navigation-bottom-sheet';
import { styles } from '../utils/styles';
import type { BottomSheetParamList } from '../utils/types';
import { useLocalSearchParams, usePathname, useRouter } from 'expo-router';

export default function SheetScreen() {
const { id } = useLocalSearchParams<{ id: string }>();
const router = useRouter();
const navigation = useBottomSheetNavigation<BottomSheetParamList>();
const pathname = usePathname();
return (
<View style={[styles.container, styles.content]}>
<Text>Sheet Screen {id}</Text>
<View style={styles.spacer} />
<Button
title="Open new sheet"
onPress={() => {
router.push({
pathname: '/sheet',
params: { id: Number(id) + 1 },
});
}}
/>
<View style={styles.spacer} />
<Button
title="Open new big sheet"
onPress={() => {
router.navigate(`/big-sheet?id=${Number(id) + 1}`);
}}
/>
<View style={styles.spacer} />
<Button
title="Close this sheet"
onPress={() => {
router.back();
}}
/>
{pathname.includes('big-sheet') && (
<>
<View style={styles.spacer} />
<Button
title="Snap to top"
onPress={() => {
navigation.snapTo(1);
}}
/>
</>
)}
</View>
);
}
1 change: 1 addition & 0 deletions example/expo-router/app/sheet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './sheet-screen';
File renamed without changes
File renamed without changes
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const path = require('path');
const { getConfig } = require('react-native-builder-bob/babel-config');
const pkg = require('../package.json');
const pkg = require('../../package.json');

const root = path.resolve(__dirname, '..');
const root = path.resolve(__dirname, '..', '..');

module.exports = function (api) {
api.cache(true);
Expand Down
1 change: 1 addition & 0 deletions example/expo-router/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import 'expo-router/entry';
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const path = require('path');
const { getDefaultConfig } = require('@expo/metro-config');
const { withMetroConfig } = require('react-native-monorepo-config');

const root = path.resolve(__dirname, '..');
const root = path.resolve(__dirname, '..', '..');

/**
* Metro configuration
Expand All @@ -16,5 +16,9 @@ const config = withMetroConfig(getDefaultConfig(__dirname), {
});

config.resolver.unstable_enablePackageExports = true;
config.resolver.platforms ??= [];
if (!config.resolver.platforms.includes('native')) {
config.resolver.platforms = ['native', ...config.resolver.platforms];
}

module.exports = config;
37 changes: 37 additions & 0 deletions example/expo-router/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "@appandflow/react-navigation-bottom-sheet-example-expo-router",
"description": "Expo Router example app for @appandflow/react-navigation-bottom-sheet",
"version": "0.0.1",
"private": true,
"main": "expo-router/entry",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web"
},
"dependencies": {
"@appandflow/react-navigation-bottom-sheet": "*",
"@expo/metro-runtime": "~6.1.2",
"@gorhom/bottom-sheet": "^5.2.6",
"@react-navigation/native": "^7.1.8",
"expo": "54.0.23",
"expo-constants": "~18.0.10",
"expo-linking": "~8.0.8",
"expo-router": "~6.0.14",
"expo-status-bar": "~3.0.8",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-native": "0.81.5",
"react-native-gesture-handler": "~2.28.0",
"react-native-reanimated": "~4.1.1",
"react-native-safe-area-context": "~5.6.0",
"react-native-screens": "~4.16.0",
"react-native-web": "~0.21.0",
"react-native-worklets": "0.5.1"
},
"devDependencies": {
"react-native-builder-bob": "^0.40.13",
"react-native-monorepo-config": "^0.1.9"
}
}
14 changes: 14 additions & 0 deletions example/expo-router/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"types": [
"expo-router/types"
]
},
"include": [
"**/*.ts",
"**/*.tsx",
".expo/types/**/*.ts",
"expo-env.d.ts"
]
}
18 changes: 18 additions & 0 deletions example/expo-router/utils/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { StyleSheet } from 'react-native';

export const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
content: {
marginVertical: 20,
},
spacer: {
margin: 5,
},
button: {
color: 'blue',
},
});
5 changes: 5 additions & 0 deletions example/expo-router/utils/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type BottomSheetParamList = {
'index': undefined;
'sheet': { id: number };
'big-sheet': { id: number };
};
Loading