Announcing React Native Versatile Modal: One Modal Component to Rule Them All

Announcing React Native Versatile Modal: One Modal Component to Rule Them All

React Native Modal

I’m thrilled to announce the release of my first npm package: @nonsobarn/react-native-versatile-modal! 🚀

The Problem That Needed Solving

As React Native developers, we’ve all been there. You need a simple alert modal in one part of your app, a bottom sheet in another, a side drawer for navigation, and a full-screen modal for immersive experiences. Traditionally, this meant:

  • Installing multiple modal libraries with different APIs
  • Dealing with inconsistent animations and behaviors
  • Wrestling with conflicting dependencies
  • Maintaining different code patterns throughout your app

I found myself constantly switching between different modal solutions or building custom ones from scratch. That’s when I decided to build a unified solution that handles all modal use cases with a consistent, developer-friendly API.

What is React Native Versatile Modal?

React Native Versatile Modal is a comprehensive modal component that provides four essential modal types in one lightweight package:

🎯 4 Modal Types, One Component

// Bottom Sheet - Perfect for mobile-first UIs
<ModalWrapper
  visible={visible}
  onClose={() => setVisible(false)}
  type="bottom-sheet"
  bottomSheetHeight="60%"
  enableSwipeDown={true}
>
  <YourContent />
</ModalWrapper>

// Drawer - Ideal for navigation menus
<ModalWrapper
  visible={visible}
  onClose={() => setVisible(false)}
  type="drawer"
  drawerPosition="left"
  drawerWidth="80%"
>
  <NavigationMenu />
</ModalWrapper>

// Center Modal - Classic dialogs and alerts
<ModalWrapper
  visible={visible}
  onClose={() => setVisible(false)}
  type="center"
  centerModalWidth="90%"
>
  <AlertContent />
</ModalWrapper>

// Full Screen - Immersive experiences
<ModalWrapper
  visible={visible}
  onClose={() => setVisible(false)}
  type="full-screen"
>
  <FullScreenContent />
</ModalWrapper>

✨ Key Features

  • 🚀 Smooth Animations: 60fps performance using React Native’s native driver
  • 👆 Gesture Support: Swipe-to-dismiss for bottom sheets and intuitive interactions
  • 🎯 TypeScript Ready: Full type definitions included for better development experience
  • 🎨 Fully Customizable: Theme colors, animations, dimensions – make it your own
  • 🪶 Zero Dependencies: Lightweight with no extra baggage (except React Native peer deps)
  • ♿ Accessible: Built with accessibility in mind from day one
  • 📱 Responsive: Easy integration with your responsive design system

Why This Package Stands Out

1. Consistent API Across All Modal Types

No more learning different APIs for different modal types. The same intuitive props work across all variations.

2. Performance-First Design

Leveraging React Native’s native driver for animations ensures buttery-smooth 60fps performance, even on lower-end devices.

3. Developer Experience

// Simple usage for common cases
<ModalWrapper visible={visible} onClose={handleClose} type="bottom-sheet">
  <YourContent />
</ModalWrapper>

// Advanced customization when needed
<ModalWrapper
  visible={visible}
  onClose={handleClose}
  type="bottom-sheet"
  animationDuration={400}
  backdropOpacity={0.7}
  theme={{
    backgroundColor: '#1a1a1a',
    backdropColor: '#000000',
  }}
  enableSwipeDown={true}
  swipeThreshold={100}
>
  <YourContent />
</ModalWrapper>

4. TypeScript Excellence

Full type safety with comprehensive TypeScript definitions:

import ModalWrapper, {
  ModalType,
  ModalWrapperProps,
  ThemeConfig,
} from '@nonsobarn/react-native-versatile-modal';

Installation

npm install @nonsobarn/react-native-versatile-modal
# or
yarn add @nonsobarn/react-native-versatile-modal

Real-World Usage Examples

Custom Styled Bottom Sheet

<ModalWrapper
  visible={settingsVisible}
  onClose={() => setSettingsVisible(false)}
  type="bottom-sheet"
  bottomSheetHeight="70%"
  theme={{
    backgroundColor: '#1a1a1a',
    backdropColor: '#000000',
    handleColor: '#666666',
  }}
  containerStyle={{
    borderTopLeftRadius: 30,
    borderTopRightRadius: 30,
  }}
>
  <View style={styles.settingsContent}>
    <Text style={styles.settingsTitle}>Settings</Text>
    {/* Your settings options */}
  </View>
</ModalWrapper>

Non-Dismissible Confirmation Modal

<ModalWrapper
  visible={confirmVisible}
  onClose={() => setConfirmVisible(false)}
  type="center"
  enableBackdropDismiss={false}
  enableSwipeDown={false}
>
  <View style={styles.alertBox}>
    <Text>This action cannot be undone. Are you sure?</Text>
    <Button title="Confirm" onPress={handleConfirm} />
  </View>
</ModalWrapper>

What I Learned Building This Package

📦 Package Publishing & Semantic Versioning

Going through the entire npm package lifecycle taught me the importance of proper semantic versioning. Every version bump tells a story about your changes:

  • Patch (0.0.1): Bug fixes
  • Minor (0.1.0): New features, backward compatible
  • Major (1.0.0): Breaking changes

📚 Writing Developer-Focused Documentation

Good documentation is everything for open source. I learned to:

  • Write clear, copy-pasteable examples
  • Anticipate common questions and answer them proactively
  • Structure documentation for both quick-start and deep-dive usage
  • Include TypeScript examples alongside regular JavaScript

🛠 Maintaining Open Source Projects

Open source is more than just code. It’s about:

  • Creating clear contribution guidelines
  • Being responsive to issues and PRs
  • Building a community around your project
  • Balancing new features with stability

🎯 API Design Principles

Designing a good API means:

  • Making simple things simple and complex things possible
  • Providing sensible defaults while allowing customization
  • Maintaining consistency across similar functionalities
  • Thinking about edge cases and error handling

Performance Considerations

The component is built with performance in mind:

// Use useCallback for handlers to prevent unnecessary re-renders
const handleClose = useCallback(() => {
  setVisible(false);
}, []);

// Memoize heavy content
const modalContent = useMemo(() => <HeavyComponent />, []);

// Avoid inline styles
<ModalWrapper
  visible={visible}
  onClose={handleClose}
  containerStyle={styles.customContainer}
>
  {modalContent}
</ModalWrapper>

Get Involved!

I’d love for you to try out React Native Versatile Modal and share your feedback:

  • 🐛 Found a bug? Open an issue
  • 💡 Have a feature request? Let’s discuss it!
  • Like the package? Star the repo to show your support
  • 🔧 Want to contribute? PRs are always welcome!

Try It Today!

npm install @nonsobarn/react-native-versatile-modal

Then head over to the documentation to get started!

Final Thoughts

Building this package has been an incredible journey into the world of open source, API design, and developer experience. I hope this component saves you as much time and frustration as it’s saved me, and I can’t wait to see what you build with it!

What modal challenges have you faced in your React Native projects? Share your experiences in the comments below! 👇

Resources:

ReactNative #JavaScript #TypeScript #OpenSource #MobileDevelopment #WebDevelopment #Programming #NPM #ReactNativeDevelopment

Similar Posts