Using UnoCSS in a React Native project
Uno With React Native
Using UnoCSS in a React Native project Demo
Setup
yarn add unonative
Basic setup
- Uno Config for vscode plugin auto completion
// uno.config.ts
import { defineConfig } from 'unocss';
import { preset } from 'unonative';
export default defineConfig({
presets: [...preset],
});
- Transform JsxElement with className to Wrapper
// babel.config.js
// npm i babel-plugin-jsx-classlist
const unocssBabel = require('unonative/babel');
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: [unocssBabel.default],
};
};
- Due to Babel Visitor not supporting asynchronous processing of source code, we have moved the processing of style collection/Icon to Metro transformer.
// metro.config.js
// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require('expo/metro-config');
const config = getDefaultConfig(__dirname);
const babelTransformerPath = require.resolve('unonative/transformer');
config.transformer.babelTransformerPath = babelTransformerPath;
module.exports = config;
Enable SVG icon support (optional)
expo install react-native-svg
yarn add @iconify/json
After importing the dependencies, you can use them in your project.
import { Icon } from 'unonative';
export function App() {
return <View>
<Icon icon="cib-addthis" className="w-32px h-32px text-red-100" />
</View>
}
Icons can be sourced from icones using the format “collection-(icon)”.
How it works
Source Code
import { Icon } from 'unonative';
function App() {
return (
<View className='bg-red-100'>
<Text className='text-lg'>Hello</Text>
<Text className='text-lg'>Word</Text>
<Icon icon='cib-addthis' className='h-8 w-8' />
</View>
);
}
In the Metro Transform phase, the source code will be processed into
import __unonative__ from 'unonative';
import { Icon } from 'unonative';
function App() {
return (
<View className='bg-red-100'>
<Text className='text-lg'>Hello</Text>
<Text className='text-lg'>Word</Text>
<Icon
icon='<svg viewBox="0 0 32 32" width="1em" height="1em" ><path fill="currentColor" d="M24 17.995h-6v5.979h-4v-5.979H8v-3.984h6V8.027h4v5.984h6zM28 .052H4a4.008 4.008 0 0 0-4 3.99v23.922a4.007 4.007 0 0 0 4 3.984h24a4.007 4.007 0 0 0 4-3.984V4.042a4.01 4.01 0 0 0-4-3.99z"/></svg>'
className='h-8 w-8'
/>
</View>
);
}
__unonative__.register({
'bg-red-100': { backgroundColor: 'rgba(254,226,226,1)' },
'text-lg': { fontSize: 18 },
'h-8': { height: 32 },
'w-8': { width: 32 },
});
In the Babel transpile phase, any jsxElement containing className will be transpiled into a higher-order component
import { UnoStyled as _UnoStyled } from "unonative";
import __unonative__ from "unonative";
import { Icon } from 'unonative';
function App() {
return <_UnoStyled className='bg-red-100' component={View}>
<_UnoStyled className='text-lg' component={Text}>Hello</_UnoStyled>
<_UnoStyled className='text-lg' component={Text}>Word</_UnoStyled>
<_UnoStyled icon='<svg viewBox="0 0 32 32" width="1em" height="1em" ><path fill="currentColor" d="M24 17.995h-6v5.979h-4v-5.979H8v-3.984h6V8.027h4v5.984h6zM28 .052H4a4.008 4.008 0 0 0-4 3.99v23.922a4.007 4.007 0 0 0 4 3.984h24a4.007 4.007 0 0 0 4-3.984V4.042a4.01 4.01 0 0 0-4-3.99z"/></svg>' className='h-8 w-8' component={Icon} />
</_UnoStyled>;
}
__unonative__.register({
"bg-red-100": {
"backgroundColor": "rgba(254,226,226,1)"
},
"text-lg": {
"fontSize": 18
},
"h-8": {
"height": 32
},
"w-8": {
"width": 32
}
});
Demo
Roadmap
- Exporting type definitions
- Adding a VW preset to convert PX units to VW units
- Generating CSS using uno.config.ts at the project root path