React
Strict components

Strict components

By default TW-Classed components are not strict, meaning that all variants are optional when rendering a component. This is a good default as it allows you to use the component without having to pass any variant. However, sometimes you want to force the user to pass a variant. For example, if you have a button component, you might want to force the user to pass a variant to specify the button's color.

To do so, you can use the makeStrict utility function to wrap your component. This tells the TypeScript compiler to throw an error if a component has not received a required variant.

Automatic strict mode

Automatic strict mode will look at a component's defaultVariants and make sure that variants without a default will be required.

import { makeStrict, classed } from "@tw-classed/react";
 
const Button = classed.button({
  base: "px-4 py-2 rounded-md",
  variants: {
    color: {
      primary: "bg-blue-500 text-white",
      secondary: "bg-gray-500 text-white",
    },
    size: {
      sm: "text-sm",
      lg: "text-lg",
    },
  },
  defaultVariants: {
    color: "primary",
  },
});
 
export default makeStrict(Button);
 
// In your app:
 
() => <Button />; // ❌ TypeError - size is required here

In the above example, TypeScript will show a TypeError on the size variant as it is required but not passed. The color variant is not required as it has a default value.

Manual strict mode

Manual strict mode allows you to specify which variants are required. This is useful if you have many variants, no defaults and only want a single variant to be required. Lets add a loading variant to our button component and make it required, we will also require the size variant.

import { makeStrict, classed } from "@tw-classed/react";
 
const Button = classed.button({
  base: "px-4 py-2 rounded-md",
  variants: {
    color: {
      primary: "bg-blue-500 text-white",
      secondary: "bg-gray-500 text-white",
    },
    size: {
      sm: "text-sm",
      lg: "text-lg",
    },
    loading: {
      true: "opacity-50 cursor-progress",
    },
  },
});
 
export default makeStrict(Button, "loading", "size");
 
// In your app:
 
() => <Button />;
// ❌ TypeError - "size" is required here
// ❌ TypeError - "loading" is required here

In the above example, TypeScript will show a TypeError on the size and loading variants as they are required but not passed. The color variant is not required as it has a default value.

Using the TypeScript casting API

A third option is to use the TypeScript casting API to cast the component to a strict component.

See the TypeScript casting API for more information.