Package Exports
- rn-variant
- rn-variant/dist/index.js
- rn-variant/dist/index.mjs
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (rn-variant) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
rn-variant
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.
⸻
Features
• 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' }).
⸻
📦 Installation
npm install rn-variant
# or
yarn add rn-variant
⸻
⚡ Quick start
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>
);
};
⸻
API
createVariantStyles(options)
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 };
}
useVariants(input)
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={...} />
.
InferVariant
Utility type that extracts the props shape expected by useVariants, handy for declaring component props.
⸻
📄 License
MIT © 2025 Simon Boisset