Typescript

Native Variants provides typing out of the box, but this page contains some further utilities and tips.

Extract variants from a component

You can use the VariantProps utility to extract variants from a component.

import { nv } from 'native-variants'

const buttonVariants = nv({
    slots: ["root", "text"],
    base: {
      root: { paddingHorizontal: 16, paddingVertical: 12 },
      text: { color: "#ffffff", textAlign: "center" },
    },
    variants: {
      variant: {
        solid: {
          root: { backgroundColor: "#ff0006" },
          text: { color: "#ffffff" },
        },
        ghost: {
          root: { backgroundColor: "transparent" },
          text: { color: "#ff0006" },
        },
      },
      size: {
        sm: {
          root: {
            paddingHorizontal: 8,
            paddingVertical: 12
          }
          text: {
            fontSize: 14
          }
        },
        md: {
          root: {
            paddingHorizontal: 12,
            paddingVertical: 16
          },
           text: {
            fontSize: 16
          }
        },
      }
    },
});

type ButtonVariants = VariantProps<typeof buttonVariants>

interface ButtonProps extends ButtonVariants {
  children: React.ReactNode;
}

export const Button = (props: ButtonProps) => {
  const { root, text } = buttonVarints(props)

  return
  <TouchableOpacity style={root}>
    <Text style={text}>
     {props.children}
    </Text>
  </TouchableOpacity>;
};

Required variants

Native Variants doesn't offer a way to make variants required yet, but you can use TypeScript's Utility Types to achieve this.

import { nv } from 'native-variants'

const buttonVariants = nv({
  slots: ['root', 'text'],
  base: "px-4 py-1.5 rounded-full hover:opacity-80",
  variants: {
    color: {
      primary: {
        root: {
          backgroundColor: 'blue'
        },
        text: {
          color: 'white'
        }
      },
      neutral: {
        root: {
          backgroundColor: 'gray'
        },
        text: {
          color: 'white'
        }
      }
    },
    requiredFlat: {
      true: {
        root: {
          backgroundColor: 'transparent'
        }
      },
      false: {
        backgroundColor: 'black'
      },
    },
  },
  defaultVariants: {
    color: "primary",
  },
  compoundVariants: [...],
});

type ButtonVariants = VariantProps<typeof buttonVariants>

export interface ButtonProps
  extends Omit<ButtonVariants, "requiredFlat">,
    Required<Pick<ButtonVariants, "requiredFlat">> {}

export const button = (props: ButtonProps) => buttonVariants(props);

// ❌ TypeScript Error:
// Argument of type "{}": is not assignable to parameter of type "ButtonProps".
// Property "requiredFlat" is missing in type "{}" but required in type "ButtonProps".
button({});

// ✅
button({ requiredFlat: true });