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
className
prop of a typicalButton
component built with React. - Our goal is to enhance the
className
prop with@unwind/class-name
so 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
className
prop 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