Light-weight, type-safe style variants for React Native. Inspired by Class Variance Authority and Unistyle, rn-variant lets you declare, combine and re-use complex styling options—with zero runtime dependencies.
⸻
• Tiny & dependency-free – just TypeScript + StyleSheet. • Multi-variant syntax – compose size, color, state, etc. • Compound variants – attach styles to specific variant combos. • Boolean flags – declare rounded, disabled, etc. as simple booleans. • Strict typings – variant values are autocompleted and type-checked. • Hook-based API – const { style } = useVariants({ size: 'md', color: 'primary' }).
⸻
npm install rn-variant
# or
yarn add rn-variant
⸻
import { createVariantStyles } from "rn-variant";
/* 1. Declare your variants */
const buttonVariants = createVariantStyles({
base: {
borderRadius: 6,
alignItems: "center",
justifyContent: "center",
paddingVertical: 12,
paddingHorizontal: 24,
},
variants: {
size: {
sm: { paddingVertical: 8, paddingHorizontal: 16 },
md: { paddingVertical: 12, paddingHorizontal: 24 },
lg: { paddingVertical: 16, paddingHorizontal: 32 },
},
color: {
primary: { backgroundColor: "#007bff" },
secondary: { backgroundColor: "#6c757d" },
outline: {
backgroundColor: "transparent",
borderWidth: 1,
borderColor: "#007bff",
},
},
rounded: {
// boolean flag
true: { borderRadius: 9999 },
false: {},
},
},
/* optional */
compoundVariants: [
{
variants: { color: "primary", size: "lg" },
style: { shadowOpacity: 0.25, shadowRadius: 4 },
},
],
});
/* 2. Extract prop types (optional) */
import type { InferVariant } from "rn-variant";
export type ButtonVariantProps = InferVariant<typeof buttonVariants>;
/* 3. Use in a component */
export const Button = ({
title,
...variant
}: ButtonVariantProps & { title: string; onPress?: () => void }) => {
const { style } = buttonVariants.useVariants(variant);
return (
<TouchableOpacity style={style} onPress={variant.onPress}>
<Text style={{ color: variant.color === "outline" ? "#007bff" : "#fff" }}>
{title}
</Text>
</TouchableOpacity>
);
};
⸻
option | type | default | description |
---|---|---|---|
base |
Partial<ViewStyle | TextStyle | ImageStyle> |
{} |
style applied to all variants |
variants |
Record<group, Record<key, Partial<RNStyle>>> |
— | top-level variant groups (e.g. size, color) |
compoundVariants |
Array<{ variants: Partial<variants>; style: Partial<RNStyle>; }> |
[] |
extra style when all matching keys are present |
Returns:
{
styles: { [Group in keyof variants]: { [Key in keyof variants[Group]]: { style: RNStyle } } };
useVariants(input: VariantInput): { style: RNStyle };
}
Accepts an object where keys are variant groups and values are: • a variant key ('lg', 'primary', …), or • boolean when the group defines { true, false }.
It merges base → individual variants → matching compoundVariants and returns { style } ready for <View style={...} />
.
Utility type that extracts the props shape expected by useVariants, handy for declaring component props.
⸻
MIT © 2025 Simon Boisset