react-native-2026-nativewind-setup

star 0

Set up and configure NativeWind v4 with Expo for Tailwind CSS styling in React Native apps

FutureAtoms By FutureAtoms schedule Updated 3/11/2026

name: react-native-2026-nativewind-setup description: Set up and configure NativeWind v4 with Expo for Tailwind CSS styling in React Native apps argument-hint: "[project name or configuration requirements]" allowed-tools: Read, Glob, Grep, WebSearch, Bash

NativeWind v4 Setup with Expo (2026)

Configure NativeWind for: $ARGUMENTS

Expert Knowledge

You are a NativeWind specialist with expertise in:

  • NativeWind v4 compile-time optimization
  • Tailwind CSS configuration
  • Expo integration
  • Dark mode and theming
  • Custom utilities and plugins

Installation

# Core packages
npx expo install nativewind tailwindcss

# Initialize Tailwind config
npx tailwindcss init

Configuration

tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  // Use NativeWind preset
  presets: [require('nativewind/preset')],

  // Content paths
  content: [
    './src/**/*.{js,jsx,ts,tsx}',
    './src/app/**/*.{js,jsx,ts,tsx}',
    './src/components/**/*.{js,jsx,ts,tsx}',
  ],

  // Dark mode support
  darkMode: 'class',

  theme: {
    extend: {
      // Custom colors
      colors: {
        primary: {
          50: '#EEF2FF',
          100: '#E0E7FF',
          200: '#C7D2FE',
          300: '#A5B4FC',
          400: '#818CF8',
          500: '#6366F1',
          600: '#4F46E5',
          700: '#4338CA',
          800: '#3730A3',
          900: '#312E81',
        },
        success: '#10B981',
        warning: '#F59E0B',
        error: '#EF4444',
      },

      // Custom font families
      fontFamily: {
        sans: ['Inter', 'system-ui', 'sans-serif'],
        mono: ['JetBrains Mono', 'monospace'],
      },

      // Custom spacing
      spacing: {
        '18': '4.5rem',
        '88': '22rem',
      },

      // Custom border radius
      borderRadius: {
        '4xl': '2rem',
      },

      // Custom shadows
      boxShadow: {
        'soft': '0 2px 15px -3px rgba(0, 0, 0, 0.07), 0 10px 20px -2px rgba(0, 0, 0, 0.04)',
        'card': '0 0 0 1px rgba(0, 0, 0, 0.05), 0 2px 4px rgba(0, 0, 0, 0.1)',
      },

      // Custom animations
      animation: {
        'fade-in': 'fadeIn 0.3s ease-out',
        'slide-up': 'slideUp 0.3s ease-out',
        'bounce-soft': 'bounceSoft 0.5s ease-in-out',
      },
      keyframes: {
        fadeIn: {
          '0%': { opacity: '0' },
          '100%': { opacity: '1' },
        },
        slideUp: {
          '0%': { opacity: '0', transform: 'translateY(10px)' },
          '100%': { opacity: '1', transform: 'translateY(0)' },
        },
        bounceSoft: {
          '0%, 100%': { transform: 'scale(1)' },
          '50%': { transform: 'scale(1.05)' },
        },
      },
    },
  },

  plugins: [],
}

babel.config.js

module.exports = function (api) {
  api.cache(true)
  return {
    presets: [
      ['babel-preset-expo', { jsxImportSource: 'nativewind' }],
      'nativewind/babel',
    ],
    plugins: [
      // If using Reanimated
      'react-native-reanimated/plugin',
    ],
  }
}

metro.config.js

const { getDefaultConfig } = require('expo/metro-config')
const { withNativeWind } = require('nativewind/metro')

const config = getDefaultConfig(__dirname)

module.exports = withNativeWind(config, { input: './global.css' })

global.css

@tailwind base;
@tailwind components;
@tailwind utilities;

/* Custom base styles */
@layer base {
  /* Default body styles */
  * {
    @apply border-border;
  }
}

/* Custom component classes */
@layer components {
  .btn-primary {
    @apply bg-primary-500 text-white px-4 py-2 rounded-lg font-medium active:bg-primary-600;
  }

  .card {
    @apply bg-white dark:bg-gray-800 rounded-xl p-4 shadow-card;
  }

  .input {
    @apply bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg px-4 py-3 text-base;
  }
}

/* Custom utilities */
@layer utilities {
  .text-balance {
    text-wrap: balance;
  }
}

App Setup

// src/app/_layout.tsx
import '../global.css'
import { Stack } from 'expo-router'
import { useColorScheme } from 'nativewind'

export default function RootLayout() {
  const { colorScheme, setColorScheme } = useColorScheme()

  return (
    <Stack
      screenOptions={{
        headerShown: false,
        contentStyle: {
          backgroundColor: colorScheme === 'dark' ? '#0F172A' : '#FFFFFF',
        },
      }}
    />
  )
}

Component Patterns

Basic Components

import { View, Text, Pressable } from 'react-native'

export function Button({ title, onPress, variant = 'primary' }) {
  const variants = {
    primary: 'bg-primary-500 active:bg-primary-600',
    secondary: 'bg-gray-100 dark:bg-gray-800 active:bg-gray-200',
    outline: 'border-2 border-primary-500 bg-transparent',
  }

  const textVariants = {
    primary: 'text-white',
    secondary: 'text-gray-900 dark:text-white',
    outline: 'text-primary-500',
  }

  return (
    <Pressable
      className={`px-6 py-3 rounded-xl items-center justify-center ${variants[variant]}`}
      onPress={onPress}
    >
      <Text className={`font-semibold text-base ${textVariants[variant]}`}>
        {title}
      </Text>
    </Pressable>
  )
}

Card Component

import { View, Text, Image, Pressable } from 'react-native'
import { Ionicons } from '@expo/vector-icons'

interface LessonCardProps {
  title: string
  duration: string
  completed: boolean
  onPress: () => void
}

export function LessonCard({ title, duration, completed, onPress }: LessonCardProps) {
  return (
    <Pressable
      className="flex-row items-center p-4 bg-white dark:bg-gray-800 rounded-2xl shadow-soft active:scale-[0.98] transition-transform"
      onPress={onPress}
    >
      <View className="w-14 h-14 rounded-xl bg-primary-100 dark:bg-primary-900 items-center justify-center">
        <Ionicons
          name="book"
          size={24}
          className="text-primary-500"
        />
      </View>

      <View className="flex-1 ml-4">
        <Text className="text-base font-semibold text-gray-900 dark:text-white">
          {title}
        </Text>
        <Text className="text-sm text-gray-500 dark:text-gray-400 mt-1">
          {duration}
        </Text>
      </View>

      {completed && (
        <View className="w-8 h-8 rounded-full bg-success items-center justify-center">
          <Ionicons name="checkmark" size={18} color="white" />
        </View>
      )}
    </Pressable>
  )
}

Dark Mode Toggle

import { Pressable } from 'react-native'
import { useColorScheme } from 'nativewind'
import { Ionicons } from '@expo/vector-icons'

export function ThemeToggle() {
  const { colorScheme, toggleColorScheme } = useColorScheme()

  return (
    <Pressable
      className="w-10 h-10 rounded-full bg-gray-100 dark:bg-gray-800 items-center justify-center"
      onPress={toggleColorScheme}
    >
      <Ionicons
        name={colorScheme === 'dark' ? 'sunny' : 'moon'}
        size={20}
        className="text-gray-600 dark:text-gray-300"
      />
    </Pressable>
  )
}

Responsive Design

import { View, Text } from 'react-native'

export function ResponsiveGrid({ items }) {
  return (
    <View className="flex-row flex-wrap -mx-2">
      {items.map((item) => (
        <View
          key={item.id}
          // Responsive width: full on mobile, half on tablet, third on desktop
          className="w-full sm:w-1/2 lg:w-1/3 px-2 mb-4"
        >
          <View className="bg-white dark:bg-gray-800 rounded-xl p-4">
            <Text className="font-semibold">{item.title}</Text>
          </View>
        </View>
      ))}
    </View>
  )
}

Conditional Styling with clsx

npm install clsx
import { View, Text, Pressable } from 'react-native'
import clsx from 'clsx'

interface ChipProps {
  label: string
  selected: boolean
  onPress: () => void
}

export function Chip({ label, selected, onPress }: ChipProps) {
  return (
    <Pressable
      className={clsx(
        'px-4 py-2 rounded-full border-2 transition-colors',
        selected
          ? 'bg-primary-500 border-primary-500'
          : 'bg-transparent border-gray-300 dark:border-gray-600'
      )}
      onPress={onPress}
    >
      <Text
        className={clsx(
          'font-medium',
          selected ? 'text-white' : 'text-gray-700 dark:text-gray-300'
        )}
      >
        {label}
      </Text>
    </Pressable>
  )
}

Custom Utilities with CVA

npm install class-variance-authority
import { cva, type VariantProps } from 'class-variance-authority'
import { Pressable, Text } from 'react-native'

const buttonVariants = cva(
  'flex-row items-center justify-center rounded-xl font-semibold',
  {
    variants: {
      variant: {
        primary: 'bg-primary-500 active:bg-primary-600',
        secondary: 'bg-gray-100 dark:bg-gray-800',
        outline: 'border-2 border-primary-500 bg-transparent',
        ghost: 'bg-transparent',
      },
      size: {
        sm: 'px-3 py-2 text-sm',
        md: 'px-4 py-3 text-base',
        lg: 'px-6 py-4 text-lg',
      },
    },
    defaultVariants: {
      variant: 'primary',
      size: 'md',
    },
  }
)

interface ButtonProps extends VariantProps<typeof buttonVariants> {
  title: string
  onPress: () => void
}

export function Button({ title, variant, size, onPress }: ButtonProps) {
  return (
    <Pressable className={buttonVariants({ variant, size })} onPress={onPress}>
      <Text
        className={clsx(
          'font-semibold',
          variant === 'primary' ? 'text-white' : 'text-gray-900 dark:text-white'
        )}
      >
        {title}
      </Text>
    </Pressable>
  )
}

TypeScript Support

types.d.ts

/// <reference types="nativewind/types" />

declare module 'nativewind' {
  interface NativeWindStyleSheet {
    // Add custom utilities if needed
  }
}

VS Code Setup

.vscode/settings.json

{
  "tailwindCSS.classAttributes": ["className", "class", "tw"],
  "tailwindCSS.experimental.classRegex": [
    ["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
    ["cn\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
  ],
  "editor.quickSuggestions": {
    "strings": true
  }
}

Deliverables

For: $ARGUMENTS

Provide:

  1. Installation commands
  2. Configuration files
  3. Theme customization
  4. Component examples
  5. Dark mode setup
  6. Responsive patterns
  7. TypeScript configuration
Install via CLI
npx skills add https://github.com/FutureAtoms/claude-skills-backup --skill react-native-2026-nativewind-setup
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator