Skip to main content
Version: v4

How to write custom components

Passing styles to components

Pass the className prop down to your custom component

function MyComponent({ className }) {
const defaultStyles = "text-black dark:text-white";
return <Text className={`${defaultStyles} ${className}`} />;
}

<MyComponent className="font-bold" />;

This pattern is very useful for creating components with variants

const variantStyles = {
default: "rounded",
primary: "bg-blue-500 text-white",
secondary: "bg-white-500 text-black",
};

function MyComponent({ variant }) {
return (
<Text
className={`
font-bold
${variantStyles.default}
${variantStyles[variant]}
`}
/>
);
}

Creating your own variants and quickly become complex. We recommend using a class name management library to simplify the process

NativeWind previously exported a styled() helper function, but it has been removed in favor of these libraries.

Each of these library has multiple "component" variants, so you can choose the one that best fits your needs.

Merging with inline styles

NativeWind will automatically merge with inline-styles. Inline styles have a higher priority.

<Text className="text-white" style={{ color: "black" }} /> // Will be black

Handling components with multiple style props

In React Native, some components may require style props for their internal child components. If you're designing such a component using NativeWind, we have a couple of recommended simply creating multiple class name props

Copy code
function MyComponent({ outerClass, innerClass }) {
return (
<View className={outerClass}>
<Text className={innerClass}>Hello, NativeWind!</Text>
</View>
);
}

If you're working with a third-party component that you can't modify directly, NativeWind provides a utility, remapProps. This function allows you to create and map className props for the component.

import { remapProps } from "nativewind";

const CustomizedButton = remapProps(ThirdPartyButton, {
buttonClass: "nativeButtonClass",
labelClass: "nativeLabelClass",
});

// Usage
<CustomizedButton buttonClass="bg-blue-500" labelClass="text-white" />;

See the remapProps documentation for more information.

Handling components with style attribute props

Some components may require style attributes to be passed as props. For example, React Native's <StatusBar /> component accepts a backgroundColor prop.

NativeWind can automatically move style attributes to props, but it requires the styles to be resolved. You will need to "tag" your component using cssInterop and create a mapping configuration

See the cssInterop documentation for more information.

TypeScript

Both remapProps and cssInterop will return a typed version of your component. However, you can globally defined the types in a new declaration file.

declare module "<3rd party package>" {
interface 3rdPartyComponentProps {
customClassName?: string;
}
}

Example

Setting global types requires in-depth knowledge of TypeScript. Your interface declaration needs to exactly match the 3rd party declaration (including extends and generics).

For example, NativeWind uses the follow types for React Native's <FlatList />, which uses multiple interfaces for its props, across multiple packages.

import {
ScrollViewProps,
ScrollViewPropsAndroid,
ScrollViewPropsIOS,
Touchable,
VirtualizedListProps,
} from "react-native";

declare module "@react-native/virtualized-lists" {
export interface VirtualizedListWithoutRenderItemProps<ItemT>
extends ScrollViewProps {
ListFooterComponentClassName?: string;
ListHeaderComponentClassName?: string;
}
}

declare module "react-native" {
interface ScrollViewProps
extends ViewProps,
ScrollViewPropsIOS,
ScrollViewPropsAndroid,
Touchable {
contentContainerClassName?: string;
indicatorClassName?: string;
}
interface FlatListProps<ItemT> extends VirtualizedListProps<ItemT> {
columnWrapperClassName?: string;
}
interface ViewProps {
className?: string;
}
}