Skip to content

Instantly share code, notes, and snippets.

@younes0
Created October 21, 2022 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save younes0/ef98d32b95988227bf70d6e42141ca8b to your computer and use it in GitHub Desktop.
Save younes0/ef98d32b95988227bf70d6e42141ca8b to your computer and use it in GitHub Desktop.
Styling React Native wirth NativeWind + Emotion
// =========================================================================
// 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