Package Exports
- react-native-styled.macro
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (react-native-styled.macro) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Disclaimer: This library is still in Beta. Use with caution. The Roadmap for v1.0.0 is available here.
💅 styled.macro
A Utility-first Styling Library for React Native.
Features
- ⚡ Zero-overhead: Styles get injected via the StyleSheet API during compilation.
- 🍂 Minimal footprint: Styles that are never used won't make it to the final App bundle.
- 🎲 Variants support: Conditionally style based on Platform, Layout or Screen size ... etc.
- 💅 Style props: Supports common style-related Component props e.g.
numberOfLines
. - 🔌 Customizable (Coming soon): Optionally override the default theme by adding
styled.config.js
file
Table of Contents
Getting started
Compatible with React Native v0.62.0 or later
yarn add react-native-styled.macro babel-plugin-macros
Add babel-plugin-macros
to your Babel config (if you haven't already)
// babel.config.js
module.exports = function (api) {
return {
plugins: ['macros'],
// ... other stuff
};
};
To use the library simply import the macro as follows:
import styled from 'react-native-styled.macro';
const Heading = ({ text }) => (
<Text
{...styled([
'my-4',
'text-2xl',
'text-gray-900',
'font-semibold',
'letter-wide',
])}
>
{text}
</Text>
);
The compiled output for the above code will look something like the following:
import { Text } from 'react-native';
+import { StyleSheet } from 'react-native';
+import { rem } from 'react-native-styled.macro/path/not/relevant';
-import styled from 'react-native-styled.macro';
+const styles = StyleSheet.create({
+ _default: {
+ marginVertical: rem(1),
+ fontSize: rem(1.5),
+ color: '#1a202c',
+ fontWeight: '600',
+ letterSpacing: rem(0.025),
+ },
+});
const Heading = ({ text }) => (
<Text
- {...styled([
- 'my-4',
- 'text-2xl',
- 'text-gray-900',
- 'font-semibold',
- 'letter-wide',
- ])}
+ {...{
+ style: styles._default,
+ }}
>
{text}
</Text>
);
How does it work?
styled
(you can name it anything) is a Babel Macro which means it will be executed during compilation.- It will map the given styles and resolve the necessary style attributes/props.
- It will try to merge styles of the same variant if possible so we don't end up creating an object for every style e.g.
text-2xl
. - For the best performance, it will then use the good/old
StyleSheet.create
to create the styles as you should normally do by yourself in a React Native app.
The output for any code you write will look more or less the same as above. The only exception is a style with multiple variants because we need to add logic to switch styles at runtime (same as you would do e.g. using Platform.select()
)
Available Styles
See docs/styles.md
Variants
Platform (Built-in)
Enables Platform-specific style. Based on the value of Platform.OS.
Possible values: android
, ios
, web
or whatever the value of Platform.OS
.
Example:
styled([
'bg-white',
'web:bg-purple-600',
'android:bg-green-600',
'ios:bg-blue-600',
]);
Layout (Built-in)
Enables Layout-specific style. Based on the value of I18nManager.isRTL
.
Possible keys: ltr
or rtl
.
Example:
styled(['text-auto', 'rtl:text-right', 'ltr:text-left']);
Responsive
Built on the top of React Native's useWindowDimensions hook. Possible keys: sm
, md
, lg
, xl
or custom values (see below).
Example
import styled from 'react-native-styled.macro';
import { useWindowVariant } from 'react-native-styled.macro/lib';
const MyComponent = () => {
const windowVariant = useWindowVariant();
return (
<Text
{...styled(['w-full', 'md:w-64'], {
...windowVariant /* other variants */,
})}
>
My text
</Text>
);
};
You can also pass custom breakpoints as follows:
// Note: passing a custom object will remove the default breakpoints e.g. `sm`.
useWindowVariant({
tablet: 640,
laptop: 768,
// .. anything really
});
// use it later
styled(['tablet:w-full', 'laptop:w-64']);
Dark mode
Since styled
accepts arbitrary keys as variants supporting Dark mode can be easily acheived as follows:
import { useColorScheme } from 'react-native';
import styled from 'react-native-styled.macro';
const MyComponent = () => {
// Can either be 'dark' or 'light'
const colorScheme = useColorScheme();
return (
<Text
{...styled(['text-black', 'dark:text-white'], {
dark: colorScheme === 'dark',
})}
>
My text
</Text>
);
};
Best Practices
Group variant styles together
Do NOT
styled(['web:bg-gray-100', 'bg-white', 'text-black', 'web:rounded']);
Do
styled(['bg-white', 'text-black', 'web:rounded', 'web:bg-gray-100']);
In addition to the readability concern, it also enables some compile-time optimizations.
Prior Art
- Tailwind CSS (website): Tailwind is a great utility-first CSS framework. We borrowed the utility-first approach from there and re-imagined how it can be used in React Native apps to build user interfaces faster without additional Runtime overhead.
Alternatives
- tailwind-react-native (github): A very promising Tailwind-like library made with React Native in mind.
License
MIT © Ahmed T. Ali