Quick start
Unwind aims to be framework-agnostic. You can use React, Vue, Solid, Svelte or whatever you like, however…
- In this guide, we will cover how to unwind the
classNameprop of a typicalButtoncomponent built with React. - Our goal is to enhance the
classNameprop with@unwind/class-nameso that it changes color when active state is set totrue.
Prerequisites
1. Combining class selectors
We will use Array.join() to get resulting className as string.
You could be also using clsx, classname, template literals... you name it.
2. Example component
We will use a Button component bellow styled with Tailwind classes.
Tailwind is already running in your browser
to play with and provides style on demand while you edit the live previews.
CSS stylesheet in your case might be coming from elsewhere but it should not matter for the sake of this guide.
Go ahead, play with the code. Unless you remove the App declaration, the live preview should work.
1. Installation
Add package to package.json
- pnpm
- yarn
- npm
pnpm add @unwind/class-name
yarn add @unwind/class-name
npm install @unwind/class-name
2. Rewriting the className prop
- Import from
@unwind/class-name - Replace base component styles with
defineClassName() - Replace
classNameprop type withClassNameProp<...> - Replace
Array.join()withresolveClassName()
import React, { PropsWithChildren } from 'react'
const buttonClassName = [
'bg-gray-50 hover:bg-white active:bg-gray-200',
'border border-gray-300 rounded',
'text-black font-bold',
'py-2 px-4',
]
type ButtonProps = PropsWithChildren<{
className?: string
}>
const Button = ({ children, className }: ButtonProps) => (
<button
className={[
...buttonClassName,
className,
].join(' ')}
>
{children}
</button>
)
import type { ClassNameProp } from '@unwind/class-name'
import { defineClassName, resolveClassName } from '@unwind/class-name'
import React, { PropsWithChildren } from 'react'
const buttonClassName = defineClassName([
'bg-gray-50 hover:bg-white active:bg-gray-200',
'border border-gray-300 rounded',
'text-black font-bold',
'py-2 px-4',
])
type ButtonProps = PropsWithChildren<{
className?: ClassNameProp<typeof buttonClassName>
}>
const Button = ({ children, className }: ButtonProps) => (
<button
className={resolveClassName(
{},
buttonClassName,
className,
)}
>
{children}
</button>
)
3. Add the active state
Unwind lets you define how components should render className according to state with a callback.
Lets add toggle state change to the Button.
import type { ClassNameProp } from '@unwind/class-name'
import { defineClassName, resolveClassName } from '@unwind/class-name'
import React, { PropsWithChildren } from 'react'
const buttonClassName = defineClassName([
'bg-gray-50 hover:bg-white active:bg-gray-200',
'border border-gray-300 rounded',
'text-black font-bold',
'py-2 px-4',
])
type ButtonProps = PropsWithChildren<{
className?: ClassNameProp<typeof buttonClassName>
}>
const Button = ({ children, className }: ButtonProps) => {
return (
<button
className={resolveClassName(
{},
buttonClassName,
className,
)}
>
{children}
</button>
)
}
import type { ClassNameProp } from '@unwind/class-name'
import { defineClassName, resolveClassName } from '@unwind/class-name'
import React, { PropsWithChildren, useCallback, useState } from 'react'
const buttonClassName = defineClassName(({ active }: { active: boolean }, previous) => [
...previous,
active
? 'bg-green-500 shadow-inner active:bg-green-600'
: 'bg-gray-50 hover:bg-white active:bg-gray-200',
active ? 'border-green-600' : 'border-gray-300', 'border rounded',
active ? 'text-white' : 'text-black', 'font-bold',
'py-2 px-4',
])
type ButtonProps = PropsWithChildren<{
className?: ClassNameProp<typeof buttonClassName>
}>
const Button = ({ children, className }: ButtonProps) => {
const [active, setActive] = useState(false)
return (
<button
className={resolveClassName(
{ active },
buttonClassName,
className,
)}
onClick={useCallback(() => { setActive(state => !state) }, [])}
>
{children}
</button>
)
}
4. The final code
We updated className prop to accept various types of values:
- Append class
- Append string[]
- Redefine colors altogether