JSPM

rn-variant

0.1.1
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 7
  • Score
    100M100P100Q48701F
  • License MIT

Light-weight, type-safe style variants for React Native.

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