Created
October 21, 2022 13:57
-
-
Save younes0/ef98d32b95988227bf70d6e42141ca8b to your computer and use it in GitHub Desktop.
Styling React Native wirth NativeWind + Emotion
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ========================================================================= | |
// tailwind.config.js | |
// ========================================================================= | |
const { platformSelect } = require("nativewind"); | |
module.exports = { | |
theme: { | |
// see: https://www.nativewind.dev/guides/theme-values | |
// see: https://tailwindcss.com/docs/configuration | |
extend: { | |
colors: { | |
blue: "#1fb6ff", | |
purple: "#7e5bef", | |
pink: "#ff49db", | |
orange: "#ff7849", | |
green: "#13ce66", | |
yellow: "#ffc82c", | |
"gray-dark": "#273444", | |
gray: "#8492a6", | |
"gray-light": "#d3dce6", | |
}, | |
spacing: { | |
// see: https://tailwindcss.com/docs/customizing-spacing#default-spacing-scale | |
1: "5px", | |
2: "10px", | |
3: "15px", | |
4: "20px", | |
5: "30px", | |
6: "40px", | |
7: "50px", | |
}, | |
borderRadius: { | |
md: "5px", | |
lg: "10px", | |
}, | |
}, | |
}, | |
}; | |
// ========================================================================= | |
// React Component | |
// ========================================================================= | |
import React from "react"; | |
import { withExpoSnack } from "nativewind"; | |
import { Text, View } from "react-native"; | |
import { styled } from "nativewind"; | |
// ------------------------------------------------------------------------- | |
// NativeWind basics | |
// ------------------------------------------------------------------------- | |
// nativewind allows you to add "classname" prop to your React Native components (doesn't exist in React Native) | |
// styled() | |
// ------------------------------------------------------------------------- | |
// is a Higher-Order Component which allows your component to accept either the tw or className props. These props are compiled into StyleSheet objects and passed to your component via the style prop.There are no differences between tw and className. | |
const StyledText = styled(Text, "font-bold"); // with default style | |
const Box = ({ className, ...props }) => ( | |
<Text | |
className={`flex h-14 justify-center items-center text-white bg-fuchsia-500 ${className}`} | |
{...props} | |
/> | |
); | |
// semi-full example | |
const App = () => ( | |
<> | |
<StyledText tw="font-normal">Hello world.</StyledText> | |
<Text className="font-bold">Hello world.</Text> | |
<View className="flex flex-row h-screen items-center space-x-2"> | |
<Box className="basis-1/4">01</Box> | |
<Box className="basis-1/4">02</Box> | |
<Box className="basis-1/2">03</Box> | |
</View> | |
</> | |
); | |
// merging styles | |
// ------------------------------------------------------------------------- | |
const variantStyles = { | |
default: "rounded", | |
primary: "bg-blue-500 text-white", | |
secondary: "bg-white-500 text-black", | |
}; | |
const StrongText = ({ variant }) => ( | |
<Text | |
className={` | |
font-bold | |
${variantStyles.default} | |
${variantStyles[variant]} | |
`} | |
/> | |
); | |
const StrongButton = ({ rounded, className }) => ( | |
<Button | |
className={clsx( | |
"font-bold", | |
{ rounded }, | |
variant === "primary" && "bg-blue-500 text-white", | |
variant === "secondary" && "bg-blue-500 text-white", | |
className | |
)} | |
/> | |
); | |
// Styling multiple properties | |
// ------------------------------------------------------------------------- | |
// styled() can optionally accept a list of additional props to parse into runtime styles. | |
const Wrapper = ({ innerStyle, children, ...props }) => ( | |
<View {...props}> | |
<View style={innerStyle}>{children}</View> | |
</View> | |
); | |
const App = () => { | |
const StyledWrapper = styled(Wrapper, { | |
props: { | |
innerStyle: true, | |
}, | |
}); | |
return ( | |
<StyledWrapper className="h-4" innerStyle="p-4"> | |
<Text>Hello, World!</Text> | |
</StyledWrapper> | |
); | |
}; | |
// ------------------------------------------------------------------------- | |
// Emotion.css | |
// ------------------------------------------------------------------------- | |
// with NativeWind | |
// ------------------------------------------------------------------------- | |
const Container = styled.View` | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
margin: 50px; | |
background-color: red; | |
// doesn't work: | |
> * { | |
background-color: blue; | |
} | |
`; | |
const App = () => ( | |
<Container | |
// className takes precedence over style | |
className="bg-green-600" | |
> | |
<Text className=" text-fuchsia-70-">Hello, World!</Text> | |
</Container> | |
); | |
// with Theme | |
// ------------------------------------------------------------------------- | |
import React from "react"; | |
import styled, { css } from "@emotion/native"; | |
import { ThemeProvider } from "@emotion/react"; | |
const theme = { | |
color: "hotpink", | |
backgroundColor: "purple", | |
}; | |
const Container = styled.View` | |
background-color: ${(props) => props.theme.backgroundColor}; | |
display: flex; | |
margin: 50px; | |
`; | |
const Image = styled.Image` | |
padding: 40px; | |
`; | |
const App = () => ( | |
<ThemeProvider theme={theme}> | |
<Container> | |
<Image | |
style={css` | |
padding: 40px 60px; | |
`} | |
source={{ | |
uri: "https://cdn.rawgit.com/emotion-js/emotion/main/emotion.png", | |
height: 150, | |
width: 150, | |
}} | |
/> | |
</Container> | |
</ThemeProvider> | |
); | |
// ------------------------------------------------------------------------- | |
// NativeWind advanced | |
// ------------------------------------------------------------------------- | |
// Platform Prefixes | |
// ------------------------------------------------------------------------- | |
const App = () => ( | |
<View className="flex-1 items-center justify-center"> | |
<Text | |
className={` | |
ios:text-red-500 | |
android:text-blue-500 | |
web:text-green-600 | |
`} | |
> | |
Text color changes per Platform | |
</Text> | |
</View> | |
); | |
// Hover, focus, and active | |
// ------------------------------------------------------------------------- | |
const App = () => ( | |
<Pressable | |
className={` | |
hover:bg-slate-300 | |
active:bg-slate-500 | |
`} | |
> | |
<Text selectable={false} className="text-slate-800"> | |
Hover and click me | |
</Text> | |
</Pressable> | |
); | |
// Viewport Units | |
// ------------------------------------------------------------------------- | |
// NativeWind supports the vw and vh viewport units. | |
const App = () => ( | |
<View | |
className={` | |
m-auto | |
h-[25vh] | |
w-[50vh] | |
`} | |
> | |
<Text selectable={false} className="text-slate-800"> | |
Rotate me! | |
</Text> | |
</View> | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment