react-classname-variants
v1.0.0
Published
React helper for classname-variants
Downloads
12
Maintainers
Readme
React styled
helper for classname-variants
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 theextractVariantsConfig
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 forString.raw
. In order to get type coverage even for your Tailwind classes you can use a tool like tailwind-ts.
License
MIT