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.