Animating icons in Radix Components based on state

I’ve often found myself wanting to animate icons inside Radix components.

Take the accordion below for example:

Notice how the plus icon rotates when the accordion opens or closes? That’s powered by Radix’s built-in state attributes. Most interactive Radix components expose a [data-state] attribute, which you can hook into directly using Tailwind.

Here’s the implementation:

<AccordionItem value="item-1" className="group">
  <AccordionTrigger>
    What is Astro?
    <PlusIcon className="group-data-[state=open]:rotate-45" />
  </AccordionTrigger>
  <AccordionContent />
</AccordionItem>

In this case, I’m using Tailwind’s group utility to let the icon react to the parent’s state. When the accordion is open, the [data-state=open] selector applies, and the icon animates.

Similarly, you can animate the icon through the trigger itself using Tailwind:

<AccordionTrigger className="data-[state=open]:[&_.icon]:rotate-45">
  <PlusIcon className="icon" />
</AccordionTrigger>

Here, Tailwind’s &_ selector is doing the heavy lifting. It targets child elements within the current component, in this case, the .icon class inside AccordionTrigger.

So when the trigger’s [data-state=open] attribute becomes active, Tailwind applies the rotation to any element matching .icon inside it.

184 words

© 2023. All rights reserved.