Skip to content

mcntsh/use-utility-classes

Repository files navigation

🧱 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.


  1. Install
  2. Use
  3. HOC
  4. Prefixes
  5. Debugging

Install

  • npm install use-utility-classes or
  • yarn 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> */

About

A hook for making classNames more reactive

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published