0
0
React Nativemobile~20 mins

Modal and bottom sheet in React Native - Mini App: Build & Ship

Choose your learning style9 modes available
Build: Modal and Bottom Sheet Demo
This screen shows how to open a modal and a bottom sheet. The modal appears in the center with a message and a close button. The bottom sheet slides up from the bottom with some options and a close button.
Target UI
-------------------------
| Modal and Bottom Sheet |
|-----------------------|
| [Open Modal]          |
| [Open Bottom Sheet]   |
|                       |
|                       |
-------------------------
Add a button labeled 'Open Modal' that opens a modal in the center of the screen.
The modal should have a message 'This is a modal' and a button 'Close' to close it.
Add a button labeled 'Open Bottom Sheet' that opens a bottom sheet sliding up from the bottom.
The bottom sheet should have a message 'This is a bottom sheet' and a button 'Close' to close it.
Use React Native's Modal component for the modal.
Use a View with animation or React Native's built-in components to simulate the bottom sheet.
Ensure both modal and bottom sheet can be closed by their respective close buttons.
Starter Code
React Native
import React, { useState } from 'react';
import { View, Text, Button, Modal, StyleSheet, Animated, TouchableOpacity } from 'react-native';

export default function ModalBottomSheetDemo() {
  const [modalVisible, setModalVisible] = useState(false);
  const [bottomSheetVisible, setBottomSheetVisible] = useState(false);

  // TODO: Add animation state and handlers for bottom sheet

  return (
    <View style={styles.container}>
      <Button title="Open Modal" onPress={() => setModalVisible(true)} />
      <Button title="Open Bottom Sheet" onPress={() => setBottomSheetVisible(true)} />

      <Modal
        visible={modalVisible}
        transparent={true}
        animationType="fade"
        onRequestClose={() => setModalVisible(false)}
      >
        {/* TODO: Add modal content here */}
      </Modal>

      {/* TODO: Add bottom sheet view here */}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingHorizontal: 20,
  },
  // TODO: Add styles for modal and bottom sheet
});
Task 1
Task 2
Task 3
Task 4
Solution
React Native
import React, { useState, useRef, useEffect } from 'react';
import { View, Text, Button, Modal, StyleSheet, Animated, TouchableOpacity, Dimensions } from 'react-native';

const screenHeight = Dimensions.get('window').height;

export default function ModalBottomSheetDemo() {
  const [modalVisible, setModalVisible] = useState(false);
  const [bottomSheetVisible, setBottomSheetVisible] = useState(false);
  const slideAnim = useRef(new Animated.Value(screenHeight)).current;

  useEffect(() => {
    if (bottomSheetVisible) {
      Animated.timing(slideAnim, {
        toValue: screenHeight - 250,
        duration: 300,
        useNativeDriver: false
      }).start();
    } else {
      Animated.timing(slideAnim, {
        toValue: screenHeight,
        duration: 300,
        useNativeDriver: false
      }).start();
    }
  }, [bottomSheetVisible, slideAnim]);

  return (
    <View style={styles.container}>
      <Button title="Open Modal" onPress={() => setModalVisible(true)} />
      <View style={{ height: 20 }} />
      <Button title="Open Bottom Sheet" onPress={() => setBottomSheetVisible(true)} />

      <Modal
        visible={modalVisible}
        transparent={true}
        animationType="fade"
        onRequestClose={() => setModalVisible(false)}
      >
        <View style={styles.modalBackground}>
          <View style={styles.modalBox}>
            <Text style={styles.modalText}>This is a modal</Text>
            <Button title="Close" onPress={() => setModalVisible(false)} />
          </View>
        </View>
      </Modal>

      <Animated.View style={[styles.bottomSheet, { top: slideAnim }]}>
        <Text style={styles.sheetText}>This is a bottom sheet</Text>
        <TouchableOpacity style={styles.closeButton} onPress={() => setBottomSheetVisible(false)}>
          <Text style={styles.closeButtonText}>Close</Text>
        </TouchableOpacity>
      </Animated.View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingHorizontal: 20,
    backgroundColor: '#fff'
  },
  modalBackground: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.5)',
    justifyContent: 'center',
    alignItems: 'center'
  },
  modalBox: {
    width: 300,
    padding: 20,
    backgroundColor: 'white',
    borderRadius: 10,
    alignItems: 'center'
  },
  modalText: {
    fontSize: 18,
    marginBottom: 15
  },
  bottomSheet: {
    position: 'absolute',
    left: 0,
    width: '100%',
    height: 250,
    backgroundColor: 'white',
    borderTopLeftRadius: 15,
    borderTopRightRadius: 15,
    padding: 20,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: -3 },
    shadowOpacity: 0.3,
    shadowRadius: 4,
    elevation: 5
  },
  sheetText: {
    fontSize: 18,
    marginBottom: 20
  },
  closeButton: {
    backgroundColor: '#2196F3',
    paddingVertical: 10,
    borderRadius: 5,
    alignItems: 'center'
  },
  closeButtonText: {
    color: 'white',
    fontSize: 16
  }
});

We use React Native's Modal component to show a modal in the center with a semi-transparent dark background. The modal box contains a message and a close button that sets modalVisible to false.

For the bottom sheet, we use an Animated.View that slides up from the bottom. We animate its top position from off-screen (screen height) to visible (screen height - 250). The bottom sheet has a message and a close button that hides it by setting bottomSheetVisible to false.

This approach keeps UI simple and uses React Native's built-in components and animation for smooth transitions.

Final Result
Completed Screen
-------------------------
| Modal and Bottom Sheet |
|-----------------------|
| [Open Modal]          |
|                       |
| [Open Bottom Sheet]   |
|                       |
|                       |
-------------------------

When 'Open Modal' is tapped:
  -------------------------
  |                       |
  |   This is a modal     |
  |   [Close]             |
  |                       |
  -------------------------

When 'Open Bottom Sheet' is tapped:
  -------------------------
  |                       |
  |                       |
  |                       |
  |-----------------------|
  | This is a bottom sheet|
  | [Close]               |
  -------------------------
Tapping 'Open Modal' shows a centered modal with a message and a close button.
Tapping 'Close' inside modal hides the modal.
Tapping 'Open Bottom Sheet' slides up a bottom sheet from the bottom with a message and close button.
Tapping 'Close' inside bottom sheet slides it down and hides it.
Stretch Goal
Add swipe down gesture to close the bottom sheet.
💡 Hint
Use PanResponder or Gesture Handler to detect swipe down and set bottomSheetVisible to false.