Skip to content

[Bug]: BottomSheetModal β†’ BottomSheetView uses absolute positioning, preventing full-height stretch (breaks flex layouts)Β #2525

@sintanial

Description

@sintanial

Version

v5

Reanimated Version

v3

Gesture Handler Version

v2

Platforms

Web

What happened?

πŸ“ Description

When using BottomSheetModal, the internal BottomSheetView has wrapper and is rendered with position: absolute.
Because of this, it’s impossible to stretch the view to fill the full height of the modal β€” even with simple static layouts.

This breaks normal flexbox layouts. For example, when you want your main content to take flex: 1 and a footer (e.g., a button) to stay pinned to the bottom using flex: 0 or same behavior when using justifyContent: space-between on parent for two child to make space vertical between each other !

βœ… Expected Behavior

BottomSheetView (inside BottomSheetModal) should behave like a regular flex container, allowing flex: 1 to fill parent container! This problem only on last version of library. For example on version 5.1.2 not using absolute position and problem is gone !

❌ Current Behavior

  • On web, BottomSheetView has wrapper with position: absolute
  • flex: 1 content doesn’t expand to fill available space
  • Elements meant to be pinned to the bottom cannot align properly

Reproduction steps

import React, { useCallback, useRef, useEffect } from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import {
  BottomSheetModal,
  BottomSheetModalProvider,
  BottomSheetView,
} from '@gorhom/bottom-sheet';

const App = () => {
  // ref
  const bottomSheetModalRef = useRef<BottomSheetModal>(null);

  // callbacks
  const handleSheetChanges = useCallback((index: number) => {
    console.log('handleSheetChanges', index);
  }, []);

  // open on mount
  useEffect(() => {
    setTimeout(() => {
      bottomSheetModalRef.current?.present();
    }, 500);
  }, []);

  return (
    <GestureHandlerRootView style={styles.container}>
      <BottomSheetModalProvider>
        <BottomSheetModal
          index={1}
          ref={bottomSheetModalRef}
          onChange={handleSheetChanges}
          snapPoints={['50%', '50%']}
        >
          <BottomSheetView style={styles.sheetContent}>
            <View style={styles.mainContent}>
              <Text>Awesome πŸŽ‰</Text>
            </View>
            <View style={styles.footer}>
              <Button title="Continue" onPress={() => {}} />
            </View>
          </BottomSheetView>
        </BottomSheetModal>
      </BottomSheetModalProvider>
    </GestureHandlerRootView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'grey',
    justifyContent: 'center',
    alignItems: 'center',
  },
  sheetContent: {
    flex: 1,
    backgroundColor: 'white',
    // πŸ‘‡ This layout breaks on web because BottomSheetView has absolute positioning
    flexDirection: 'column',
    justifyContent: 'space-between',
  },
  mainContent: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  footer: {
    padding: 16,
  },
});

export default App;

Reproduction sample

https://snack.expo.dev/@sintanial/bottom-sheet---issue-reproduction-template

DevTool web inspector screenshot

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions