uniwind
Tailwind CSS v4 styling for React Native with build-time compilation and zero runtime overhead.
Works with
3
total installs
3
this week
1.5K
GitHub stars
0
upvotes
Install Skill
Run in your terminal
3
installs
3
this week
1.5K
stars
What it does
Supports all core React Native components with native className prop; third-party components wrapped via withUniwind or resolved with useResolveClassNames
Includes 40+ component bindings with dedicated props for non-style color attributes (e.g., colorClassName , tintColorClassName with accent- prefix)
Offers scalable theming via CSS variables, custom themes, platform selectors ( ios: , and
Installation Guide
How to use uniwind on Cursor
AI-first code editor with Composer
Prerequisites
Before installing skills in Cursor, ensure your development environment meets these requirements:
- ›Cursor installed and configured on your machine
- ›Node.js 16+ with npm — verify with
node --version - ›Active project directory where you want to add
uniwind
Run the install command
Execute the skills CLI command in your project's root directory to begin installation:
Fetches uniwind from uni-stack/uniwind and configures it for Cursor.
Select Cursor when prompted
The CLI shows a list of agents. Use arrow keys and space to select Cursor:
Verify installation
Confirm successful installation by checking the skill directory location:
Restart Cursor to activate uniwind. Access via /uniwind in your agent's command palette.
Security Notice
We perform automated surface-level scans (Gen AI Scanner, Socket, Snyk) during installation. These checks detect common vulnerabilities but do not guarantee complete security. Always review skill source code and verify the publisher's reputation before production use.
Skills execute code in your environment. Always review source, verify the publisher, and test in isolation before production.
Documentation
Uniwind — Complete Reference
Uniwind 1.5.0+ / Tailwind CSS v4 / React Native 0.81+ / Expo SDK 54+
If user has lower version, recommend updating to 1.5.0+ for best experience.
Uniwind brings Tailwind CSS v4 to React Native. All core React Native components support the className prop out of the box. Styles are compiled at build time — no runtime overhead.
Critical Rules
- Tailwind v4 only — Use
@import 'tailwindcss'not@tailwind base. Tailwind v3 is not supported. - Never construct classNames dynamically — Tailwind scans at build time.
bg-${color}-500will NOT work. Use complete string literals, mapping objects, or ternaries. - Never use
cssInteroporremapProps— Those are NativeWind APIs. Uniwind does not override global components. - No
tailwind.config.js— All config goes inglobal.cssvia@themeand@layer theme. - No ThemeProvider required — Use
Uniwind.setTheme()directly. withUniwindConfigmust be the outermost Metro config wrapper.- NEVER wrap
react-nativeorreact-native-reanimatedcomponents withwithUniwind—View,Text,Pressable,Image,TextInput,ScrollView,FlatList,Switch,Modal,Animated.View,Animated.Text, etc. already have fullclassNamesupport built in. Wrapping them withwithUniwindwill break behavior. Only usewithUniwindfor third-party components (e.g.,expo-image,expo-blur,moti). - Font families: single font only — React Native doesn't support fallbacks. Use
--font-sans: 'Roboto-Regular'not'Roboto', sans-serif. - All theme variants must define the same set of CSS variables — If
lightdefines--color-primary, thendarkand every custom theme must too. Mismatched variables cause runtime errors. accent-prefix is REQUIRED for non-style color props — This is crucial. Props likecolor(Button, ActivityIndicator),tintColor(Image),thumbColor(Switch),placeholderTextColor(TextInput) are NOT part of thestyleobject. You MUST use the corresponding{propName}ClassNameprop withaccent-prefixed classes. Example:<ActivityIndicator colorClassName="accent-blue-500" />NOT<ActivityIndicator className="text-blue-500" />. Regular Tailwind color classes (liketext-blue-500) only work onclassName(which maps tostyle). For non-style color props, always useaccent-.- rem default is 16px — NativeWind used 14px. Set
polyfills: { rem: 14 }in metro config if migrating. cssEntryFilemust be a relative path string — Use'./global.css'notpath.resolve(__dirname, 'global.css').- Deduplicate with
cn()when mixing custom CSS classes and Tailwind — Uniwind does NOT auto-deduplicate. If a custom CSS class (.card { padding: 16px }) and a Tailwind utility (p-6) set the same property, both apply with unpredictable results. Always wrap withcn('card', 'p-6')when there's overlap.
Setup
Installation
# or other package manager
bun install uniwind tailwindcss
Requires Tailwind CSS v4+.
global.css
Create a CSS entry file:
@import 'tailwindcss';
@import 'uniwind';
Import in your App component (e.g., App.tsx or app/_layout.tsx), NOT in index.ts/index.js — importing there breaks hot reload:
// app/_layout.tsx or App.tsx
import './global.css';
The directory containing global.css is the app root — Tailwind scans for classNames starting from this directory.
Metro Configuration
const { getDefaultConfig } = require('expo/metro-config');
// Bare RN: const { getDefaultConfig } = require('@react-native/metro-config');
const { withUniwindConfig } = require('uniwind/metro');
const config = getDefaultConfig(__dirname);
// withUniwindConfig MUST be the OUTERMOST wrapper
module.exports = withUniwindConfig(config, {
cssEntryFile: './global.css', // Required — relative path from project root
polyfills: { rem: 16 }, // Optional — base rem value (default 16)
extraThemes: ['ocean', 'sunset'], // Optional — custom themes beyond light/dark
dtsFile: './uniwind-types.d.ts', // Optional — TypeScript types output path
debug: true, // Optional — log unsupported CSS in dev
isTV: false, // Optional — enable TV platform support
});
For most flows, keep defaults, only provide cssEntryFile.
Wrapper order — Uniwind must wrap everything else:
// CORRECT
module.exports = withUniwindConfig(withOtherConfig(config, opts), { cssEntryFile: './global.css' });
// WRONG — Uniwind is NOT outermost
module.exports = withOtherConfig(withUniwindConfig(config, { cssEntryFile: './global.css' }), opts);
Vite Configuration (v1.2.0+)
If user has storybook setup, add extra vite config:
import tailwindcss from '@tailwindcss/vite';
import { uniwind } from 'uniwind/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [
tailwindcss(),
uniwind({
cssEntryFile: './src/global.css',
dtsFile: './src/uniwind-types.d.ts',
}),
],
});
TypeScript
Uniwind auto-generates a .d.ts file (default: ./uniwind-types.d.ts) after running Metro. Place it in src/ or app/ for auto-inclusion, or add to tsconfig.json:
{ "include": ["./uniwind-types.d.ts"] }
If user has some typescript errors related to classNames, just run metro server to build the d.ts file.
Expo Router Placement
project/
├── app/_layout.tsx ← import '../global.css' here
├── components/
├── global.css ← project root (best location)
└── metro.config.js ← cssEntryFile: './global.css'
If global.css is in app/ dir, add @source for sibling directories:
@import 'tailwindcss';
@import 'uniwind';
@source '../components';
Tailwind IntelliSense (VS Code / Cursor / Windsurf)
{
"tailwindCSS.classAttributes": [
"class", "className", "headerClassName",
"contentContainerClassName", "columnWrapperClassName",
"endFillColorClassName", "imageClassName", "tintColorClassName",
"ios_backgroundColorClassName", "thumbColorClassName",
"trackColorOnClassName", "trackColorOffClassName",
"selectionColorClassName", "cursorColorClassName",
"underlineColorAndroidClassName", "placeholderTextColorClassName",
"selectionHandleColorClassName", "colorsClassName",
"progressBackgroundColorClassName", "titleColorClassName",
"underlayColorClassName", "colorClassName",
"backdropColorClassName", "backgroundColorClassName",
"statusBarBackgroundColorClassName", "drawerBackgroundColorClassName",
"ListFooterComponentClassName", "ListHeaderComponentClassName"
],
"tailwindCSS.classFunctions": ["useResolveClassNames"]
}
Monorepo Support
Add @source directives in global.css for packages outside the CSS entry file's directory:
@import 'tailwindcss';
@import 'uniwind';
@source "../../packages/ui/src";
@source "../../packages/shared/src";
Also needed for node_modules packages that contain Uniwind classes (e.g., shared UI libraries).
Component Bindings
All core React Native components support className out of the box. Some have additional className props for sub-styles (like contentContainerClassName) and non-style color props (requiring accent- prefix).
Complete Reference
Legend: Props marked with ⚡ require the accent- prefix. Props in parentheses are platform-specific.
View
| Prop | Maps to | Prefix |
|---|---|---|
className |
style |
— |
Text
| Prop | Maps to | Prefix |
|---|---|---|
className |
style |
— |
selectionColorClassName |
selectionColor |
⚡ accent- |
Pressable
| Prop | Maps to | Prefix |
|---|---|---|
className |
style |
— |
Supports active:, disabled:, focus: state selectors.
Image
| Prop | Maps to | Prefix |
|---|---|---|
className |
style |
— |
tintColorClassName |
tintColor |
⚡ accent- |
TextInput
| Prop | Maps to | Prefix |
|---|---|---|
className |
style |
— |
cursorColorClassName |
cursorColor |
⚡ accent- |
selectionColorClassName |
selectionColor |
⚡ accent- |
placeholderTextColorClassName |
placeholderTextColor |
⚡ accent- |
selectionHandleColorClassName |
selectionHandleColor |
⚡ accent- |
underlineColorAndroidClassName |
underlineColorAndroid (Android) |
⚡ accent- |