> ## Documentation Index
> Fetch the complete documentation index at: https://docs.uniwind.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# withUniwind

> Add `className` support to any React Native component

## Overview

The `withUniwind` higher-order component (HOC) wraps any React Native component to add `className` prop support. This is essential for using third-party components with Uniwind's Tailwind-based styling system.

## Why Use withUniwind?

Many popular React Native libraries export components that don't natively support the `className` prop. Instead, they accept the traditional `style` prop. The `withUniwind` wrapper bridges this gap, allowing you to use Tailwind classes with any component.

<Tip>
  **Some third-party components work out of the box!** Libraries like React Native Reanimated that are built on top of React Native's core components (View, Text, etc.) automatically support `className` without wrapping. You only need `withUniwind` when the underlying implementation uses custom native components or doesn't forward the `style` prop properly.
</Tip>

### Problem

```tsx theme={null}
import { SafeAreaView } from 'react-native-safe-area-context';

// ❌ This won't work - SafeAreaView is a third-party component
<SafeAreaView className="flex-1 bg-background">
  {/* content */}
</SafeAreaView>
```

### Solution

```tsx theme={null}
import { withUniwind } from 'uniwind'
import { SafeAreaView } from 'react-native-safe-area-context';

const StyledSafeAreaView = withUniwind(SafeAreaView);

// ✅ This works - we've wrapped the component with withUniwind
<StyledSafeAreaView className="flex-1 bg-background">
  {/* content */}
</StyledSafeAreaView>
```

## Automatic Prop Mapping

`withUniwind` automatically maps props based on their names. Any prop containing `style` or `color` in its name is automatically mapped.

<Info>
  **No manual mapping needed!** The `style` prop is automatically mapped to `className`, and color-related props get their own `*ClassName` variants.
</Info>

### Automatic Mappings

Here are some examples of how props are automatically mapped:

| Original Prop     | Mapped ClassName Prop      | Example Usage                                              |
| ----------------- | -------------------------- | ---------------------------------------------------------- |
| `style`           | `className`                | `<Component className="p-4" />`                            |
| `color`           | `colorClassName`           | `<Component colorClassName="accent-red-500" />`            |
| `backgroundColor` | `backgroundColorClassName` | `<Component backgroundColorClassName="accent-blue-500" />` |
| `borderColor`     | `borderColorClassName`     | `<Component borderColorClassName="accent-gray-300" />`     |
| `tintColor`       | `tintColorClassName`       | `<Component tintColorClassName="accent-green-500" />`      |

### Example: Using Auto-Mapped Color Props

```tsx theme={null}
import { withUniwind } from 'uniwind'
import { ActivityIndicator } from 'react-native-activity-indicator'

const StyledActivityIndicator = withUniwind(ActivityIndicator)

// Use colorClassName instead of the color prop
<StyledActivityIndicator
  colorClassName="accent-blue-500 dark:accent-blue-300"
  size="large"
/>
```

## Custom Prop Mapping

For advanced use cases, you can define custom mappings to map className props to component props. This is useful for components with non-standard prop names like `width`, `size`, `fill`, or `stroke`.

### How Mapping Works

The mapping object structure is:

```tsx theme={null}
withUniwind(Component, {
  targetProp: {                    // The component's original prop name
    fromClassName: 'myClassName',  // The className prop you'll use in JSX
    styleProperty: 'width',        // (Optional) Which CSS property to extract
  },
})
```

<Info>
  **Understanding the structure:**

  * **Object key** (`targetProp`) → The prop that the component actually receives
  * **`fromClassName`** → The new className prop you'll write in your JSX
  * **`styleProperty`** → Which CSS property value to extract and pass to the target prop
</Info>

### Example: Mapping a Width Prop

Some components accept a `width` prop as a number or string, not a style object. Here's how to map it:

```tsx theme={null}
import { withUniwind } from 'uniwind'
import { ProgressBar } from 'some-library'

const StyledProgressBar = withUniwind(ProgressBar, {
  width: {
    fromClassName: 'widthClassName',
    styleProperty: 'width',
  },
})

// Usage: pass Tailwind width classes via widthClassName
<StyledProgressBar widthClassName="w-64" progress={0.5} />
// The component receives: width={256}
```

### Example: Mapping a Size Prop

```tsx theme={null}
import { withUniwind } from 'uniwind'
import { Avatar } from 'some-library'

const StyledAvatar = withUniwind(Avatar, {
  size: {
    fromClassName: 'sizeClassName',
    styleProperty: 'width',  // Extract width value for the size prop
  },
})

// Usage: use width classes to control size
<StyledAvatar sizeClassName="w-12" source={{ uri: '...' }} />
// The component receives: size={48}
```

### Example: SVG Stroke and Fill

SVG components often use `stroke` and `fill` props that accept color values:

```tsx theme={null}
import { withUniwind } from 'uniwind'
import { Path } from 'react-native-svg'

export const StyledPath = withUniwind(Path, {
  stroke: {
    fromClassName: 'strokeClassName',
    styleProperty: 'accentColor',
  },
  fill: {
    fromClassName: 'fillClassName',
    styleProperty: 'accentColor',
  },
})

// Usage: use accent-* classes to set colors
<StyledPath
  strokeClassName="accent-red-500 dark:accent-blue-100"
  fillClassName="accent-transparent"
  d="M10 10 H 90 V 90 H 10 Z"
/>
```

<Tip>
  Use `accent-*` classes when you need to extract a color value. The `accentColor` style property is specifically designed for this purpose in Uniwind.
</Tip>

### Mapping Entire Style Objects

If you omit `styleProperty`, the entire resolved style object is passed to the target prop:

```tsx theme={null}
import { withUniwind } from 'uniwind'
import { CustomComponent } from 'some-library'

export const StyledCustomComponent = withUniwind(CustomComponent, {
  containerStyle: {
    fromClassName: 'containerClassName',
    // No styleProperty - maps the entire style object
  },
})

// Usage: all styles are passed as an object to containerStyle
<StyledCustomComponent containerClassName="p-4 bg-red-500 rounded-lg" />
// The component receives: containerStyle={{ padding: 16, backgroundColor: '...', borderRadius: 8 }}
```

### Third-Party UI Components

```tsx theme={null}
import { withUniwind } from 'uniwind'
import { Button } from 'react-native-paper'

const StyledButton = withUniwind(Button)

export const MyButton = () => (
  <StyledButton
    className="m-4"
    backgroundColorClassName="accent-blue-500"
    mode="contained"
  >
    Press me
  </StyledButton>
)
```

## API Reference

### Function Signature

```tsx theme={null}
withUniwind<T>(Component: T, mappings?: PropMappings): T
```

### Parameters

<ParamField path="Component" type="React.ComponentType" required>
  The React component to wrap with className support.
</ParamField>

<ParamField path="mappings" type="PropMappings">
  Optional custom prop mappings. Each mapping defines how to convert a className prop to a component prop.

  **Mapping structure:**

  ```tsx theme={null}
  {
    [targetProp: string]: {
      fromClassName: string,      // The className prop name to create
      styleProperty?: string       // Optional CSS property to extract (omit to use entire style)
    }
  }
  ```
</ParamField>

### Return Value

<ParamField path="StyledComponent" type="React.ComponentType">
  A wrapped component that accepts `className` and auto-generated `*ClassName` props, in addition to all original component props.
</ParamField>

## Best Practices

<Tip>
  **Create reusable styled components:** Define your wrapped components in a separate file and export them for reuse throughout your app.
</Tip>

```tsx theme={null}
// components/styled.ts
import { withUniwind } from 'uniwind'
import { SafeAreaView } from 'react-native-safe-area-context'
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'

export const StyledSafeAreaView = withUniwind(SafeAreaView)
export const StyledKeyboardAwareScrollView = withUniwind(KeyboardAwareScrollView)
```

<Warning>
  **Performance consideration:** Wrap components at the module level (outside your component functions) to avoid recreating the wrapper on every render.
</Warning>

## Related

<CardGroup cols={2}>
  <Card title="useResolveClassNames" icon="code" href="/api/use-resolve-class-names">
    Convert classNames to style objects at runtime
  </Card>

  <Card title="Third-Party Components" icon="box" href="/components/other-components">
    Learn about styling third-party component libraries
  </Card>
</CardGroup>
