Dripsy
Unstyled, responsive UI primitives for React Native + Web.
Style once, run anywhere.
<Text sx={{ fontSize: [14, 16, 20], // 14 on mobile, 16 on tablet, 20 on desktop color: ['$primary', null, 'accent'], // `primary` on mobile & tablet, `accent` on desktop }}> Responsive font size?? 🤯</Text>
🦦 Features
- (New in 1.4.x!) Custom fonts, edited globally
- (New in v3!) Full TypeScript support
- Responsive styles
- Universal (Android, iOS, Web, & more)
- Works with Expo
- Works with Vanilla React Native
- Works with Next.js
- Full theme support
- Custom theme variants
- Insanely simple API (themed, responsive designs in one line!)
- Works with Animated/Reanimated/Moti
- Dark mode / custom color modes
- Memoized styles, even when written inline
- Atomic CSS classes, with
StyleSheet.create
under the hood - Use with
@expo/vector-icons
(example) - Linear Gradient
- Performant:
sx
prop is memoized under the hood (even if you write it in render)
🤔 Why?
Build once, deploy everywhere, is a great philosophy made possible by Expo Web/React Native Web. A large impediment is responsive design.
React Native doesn't have media queries for styles, and trying to micmick it with JS turns into useState
hell with a ton of conditionals (as you'll see below.)
While React Native has some great component libraries, it lacks a good design system that is responsive and themed.
No longer. The goal of Dripsy is to let you go from idea to universal, themed styles without much effort.
There is no shortage of discussion about what responsive design should look like in React Native.
After trying many, many different ways, I'm convinced this approach is the answer. I'm curious to see if you'll think the same.
🏆 Before & After
Before Dripsy 😢
This is what it took to make one responsive style without Dripsy...
import { useState } from 'react'import { View } from 'react-native'const ResponsiveBox = () => { const [screenWidth, setScreenWidth] = useState(Dimensions.get('window').width) useEffect(() => { const onResize = (event) => { setScreenWidth(event.window.width) } Dimensions.addEventListener('change', onResize) return () => Dimensions.removeEventListener('change', onResize) }, []) let width = '100%' if (screenWidth > 700) { width = '50%' } return <View style={{ width }} />}
With Dripsy 🤩
import { View } from 'dripsy'const ResponsiveBox = () => { return <View sx={{ width: ['100%', '50%'] }} />}
In the future, I may also add support for responsive objects (rather than just arrays):
import { View } from 'dripsy'const ResponsiveBox = () => { return ( <View sx={{ width: { '@base': 100, '@md': 200, }, }} /> )}
But this is not implemented yet.
Next.js Conf
I spoke at at Next.js Conf 2021 on October 26 about React Native + Next.js. Watch the video to see how we do it.