🧱 useUtilityClasses
Make your component's class-names reactive to your component state. Ideally used in conjunction with a utility-CSS framework like Tailwind or Tachyons.
Install
npm install use-utility-classes
oryarn add use-utility-classes
Use
Pass your props to the useUtilityClasses
hook, then pass conditions to the function it returns to conditionally render certain props:
import useUtilityClasses from 'use-utility-classes'
const Component = ({ color }) => {
// Watch the value for the prop `color`
const setClassName = useUtilityClasses({ color })
// Set the class `text-red-500` when the value is `red`
const className = setClassName({
when: { color: 'red' },
use: 'text-red-500'
})
return <span className={className} />
}
<Component color='red' /> // <span class="text-red-500" />
<Component color='blue' /> // <span />
You can add multiple criteria:
import useUtilityClasses from 'use-utility-classes'
const Component = ({ color, isDisabled }) => {
// Watch the value for the following props:
const setClassName = useUtilityClasses({ color, isDisabled })
// Only set the class when the color is red *and* the component is not disabled
const className = setClassName({
when: {
color: 'red',
isDisabled: false
},
use: 'text-red-500'
})
return <span className={className} />
}
<Component color='red' isDisabled={true} /> // <span class="text-red-500" />
<Component color='red' isDisabled={false} /> => <span />
You can also pass more than one condition to the setClassName
function:
import useUtilityClasses from 'use-utility-classes'
const redEnabledVariant = {
when: {
color: 'red',
isDisabled: false
},
use: 'text-red-500'
}
const redDisabledVariant = {
when: {
color: 'red',
isDisabled: true
},
use: 'text-red-300 cursor-not-allowed'
}
const Component = ({ color, isDisabled }) => {
const setClassName = useUtilityClasses({ color, isDisabled })
const className = setClassName(redEnabledVariant, redDisabledVariant)
return <span className={className} />
}
<Component color='red' isDisabled={false} /> // <span class="text-red-500" />
<Component color='red' isDisabled={true} /> // <span class="text-red-300 cursor-not-allowed" />
For class-names that should always display, just pass a string:
import useUtilityClasses from 'use-utility-classes'
const redEnabledVariant = {
when: {
color: 'red',
isDisabled: false
},
use: 'text-red-500'
}
const redDisabledVariant = {
when: {
color: 'red',
isDisabled: true
},
use: 'text-red-300 cursor-not-allowed'
}
const defaultClasses = 'font-semibold text-xs uppercase'
const Component = ({ color, isDisabled }) => {
const setClassName = useUtilityClasses({ color, isDisabled })
const className = setClassName(
redEnabledVariant,
redDisabledVariant,
defaultClasses
)
return <span className={className} />
}
<Component color='red' isDisabled={true} /> // <span class="text-red-300 cursor-not-allowed font-semibold text-xs uppercase" />
<Component color='red' isDisabled={false} /> // <span class="text-red-500 font-semibold text-xs uppercase" />
<Component /> // <span class="font-semibold text-xs uppercase" />
HOC
An HOC helper is also included in this package which will pass the hook via props:
import withSetClassName from 'use-utility-classes/react'
const Component = props => {
const className = props.setClassName({
when: {
color: 'red',
isDisabled: false
},
use: 'text-red-500'
})
return <span className={className} />
}
const WrappedComponent = withSetClassName(Component /*, { debug: true, prefix: 'tw-' } */)
<WrappedComponent color='red' isDisabled={false} /> // <span class="text-red-500"></span>
Prefixes
You can pass a prefix
option if you'd like one appended to your classes:
import useUtilityClasses from 'use-utility-classes'
const Component = props => {
const setClassName = useUtilityClasses(props, { prefix: 'tw-' })
const className = setClassName('border-black bg-black hover:bg-gray-700 text-white')
return <button className={className} />
}
<Component /> // <span class="tw-border-black tw-bg-black hover:tw-bg-gray-700 tw-text-white" />
Debugging
You can pass an option to make the classes more legible while you're doing development:
import useUtilityClasses from 'use-utility-classes'
const Component = props => {
const setClassName = useUtilityClasses(props, { debug: true })
const className = setClassName(
'uppercase text-xs font-semibold tracking-wide',
{ when: { isLoading: true }, use: 'text-gray-300 cursor-not-allowed' },
{ when: { isLoading: false }, use: 'text-black cursor-pointer' }
)
return <span className={className} />
}
The outputs of your conditions will be listed and marked as enabled or disabled:
<Component isLoading={false} />
/*
<span class="
• uppercase text-xs font-semibold tracking-wide
Ă—â €text-gray-300â €cursor-not-allowed
• text-black cursor-pointer"></span>
*/
<Component isLoading={true} />
/*
<span class="
• uppercase text-xs font-semibold tracking-wide
• text-gray-300 cursor-not-allowed
Ă—â €text-blackâ €cursor-pointer"></span>
*/