react-classname-variants
TypeScript icon, indicating that this package has built-in type declarations

1.0.0 • Public • Published

React styled helper for classname-variants

npm package Build Status Downloads Issues Commitizen Friendly Semantic Release

This package replaces the classname-variants/react styled helper.

Main differences:

  • @radix-ui/react-slot is used instead of polymorphic (as prop) components.
  • Correct implementation of VariantPropsOf utility type that only returns variant props of react component
  • Ability to extract the classname-variants configuration from a react component using the extractVariantsConfig function

Install

npm install react-classname-variants

Usage

Things can be taken even a step further, resulting in a styled-components like way of defining reusable components. Under the hood, this does basically the same as the example above, but also handles refs correctly:

import { styled, tw } from 'react-classname-variants';
const Button = styled('button', {
  variants: {
    size: {
      small: tw`text-xs px-4`,
      large: tw`text-base px-6`,
    },
  },
});

Again, this is not limited to tailwind, so you could do the same with CSS modules:

import { styled } from 'react-classname-variants';
import styles from './styles.module.css';
const Button = styled('button', {
  variants: {
    size: {
      small: styles.small,
      large: styles.large,
    },
  },
});

You can also use the VariantPropsOf utility type to get the prop type for variants only:

import { VariantPropsOf, styled, tw } from 'react-classname-variants';

const Button = styled('button', {
  base: tw`px-5 py-2 text-white disabled:bg-gray-400 disabled:text-gray-300`,
  variants: {
    color: {
      neutral: tw`bg-slate-500 hover:bg-slate-400`,
      accent: tw`bg-teal-500 hover:bg-teal-400`,
    },
    outlined: {
      true: tw`border-2`,
    },
    size: {
      small: tw`text-xs px-4`,
      large: tw`text-base px-6`,
    },
  },
  compoundVariants: [
    {
      variants: { color: 'accent', outlined: true },
      className: tw`border-teal-600`,
    },
  ],
  defaultVariants: {
    size: 'small',
  },
});

type ButtonProps = VariantPropsOf<typeof Button>;
// is equivalent to this:
type ButtonProps = {
  color: 'neutral' | 'accent';
  outlined: boolean | undefined; // boolean properties can be undefined
  size: 'small' | 'large' | undefined; // can be undefined because it has a default variant
};

Note You can also style other custom React components as long as they accept a className prop.

Styled components without variants

You can also use the styled function to create styled components without any variants at all:

import { styled } from 'react-classname-variants';
const Button = styled(
  'button',
  'border-none rounded px-3 font-sans bg-green-600 text-white hover:bg-green-500'
);

Polymorphic components with "asChild"

If you want to keep all the variants you have defined for a component but want to render a different HTML tag or a different custom component, you can use the "asChild" prop to do so:

import { styled } from 'react-classname-variants';
const Button = styled('button', {
  variants: {
    //...
  },
});
function App() {
  return (
    <div>
      <Button>I'm a button</Button>
      <Button asChild>
        <a href="/">I'm a link!</a>
      </Button>
    </div>
  );
}

Tailwind IntelliSense

In order to get auto-completion for the CSS classes themselves, you can use the Tailwind CSS IntelliSense plugin for VS Code. In order to make it recognize the strings inside your variants-config, you have to somehow mark them and configure the plugin accordingly.

One way of doing so is by using tagged template literals:

import { variants, tw } from 'cvariants';
const Button = styled('button', {
  base: tw`px-5 py-2 text-white`,
  variants: {
    color: {
      neutral: tw`bg-slate-500 hover:bg-slate-400`,
      accent: tw`bg-teal-500 hover:bg-teal-400`,
    },
  },
});

You can then add the following line to your settings.json:

"tailwindCSS.experimental.classRegex": ["tw`(\\`|[^`]+?)`"]

Note The tw helper function is just an alias for String.raw. In order to get type coverage even for your Tailwind classes you can use a tool like tailwind-ts.

License

MIT

Package Sidebar

Install

npm i react-classname-variants

Weekly Downloads

0

Version

1.0.0

License

MIT

Unpacked Size

17.7 kB

Total Files

5

Last publish

Collaborators

  • jackardios