Skip to main content

Stateful class names

As oppose to stateless, anyclassName define to be dependent on props or state is considered statefull. It exposes component's state to any callback that would want to derive it's CSS classes based on the passed state.

Type: ClassNameCallback

Defining stateful className value

Use functions or closures to define a stateful className value callback. It is not required to wrap callbacks with defineClassName() but that would require you to define both types of arguments manually.

Arguments

State object

The first argument of the callback class name is an object representing the state of the component.

type MyComponentClassNameState = {
active: boolean
}

Previously generated selectors parameter

The second argument of the callback class name is a list of selectors that were generated by the class names passed to the resolving method before your callback class name. You might decide to discard all previous styles and start from scratch by omitting the second parameter altogether, filter selectors or add extra selectors depending on your use-case.

If you only add selectors that are not directly tied to the state, you should consider creating a stateless class name instead.

Defining manually

Manually 1: With type for the argument
import type { ClassNamePrimitive } from '@unwind/class-name'

type MyComponentClassNameState = {
active: boolean
}

const myComponentClassName = (state: MyComponentClassNameState, previous: ClassNamePrimitive[]) => [
...previous,
...[
`active:${active}`,
]
]

or

Manually 2: With type for the variable
import type { ClassNameCallback } from '@unwind/class-name'

type MyComponentClassNameState = {
active: boolean
}

const myComponentClassName: ClassNameCallback = (state: MyComponentClassNameState, previous) => [
...previous,
...[
`active:${active}`,
]
]
Unwind prefixes falsy selectors with not: prefix. See config to opt out.

Resulting HTML markup:

<a href="not:active">This will work</a>

Use \ to escape : when declaring CSS class that should include colon, e.g.:

.not\:active {
color: grey;
}

Defining with a method

Using a method
import { defineClassName } from '@unwind/class-name'

type MyComponentClassNameState = {
active: boolean
}

const myComponentClassName = defineClassName((state: MyComponentClassNameState, previous) => [
...previous,
...[
active ? 'my-component-is-active' : null,
]
])

When you use defineClassName() it turns your value into a nested object under the hood.

Definition
const className = defineClassName(
(
state: MyComponentClassNameState,
previous
) => [ ...previous, 'my-component' ]
)
Resulting value
const className = {
[HOST_KEY]: [(
state: MyComponentClassNameState,
previous
) => [ ...previous, 'my-component' ]]
}