As a web developer, I am always on the lookout for new tools and libraries that can help me create beautiful, responsive, and accessible user interfaces. Radix UI is at the top of my list for personal and client projects. It's a collection of unstyled, accessible, and composable React components. I really appreciate the simplicity and flexibility. Let's make an accordion to get started.
Accordion
The Accordion component allows you to create expandable and collapsible sections of content, perfect for FAQs or nested menus. It is highly customizable, allowing you to add custom styling or behaviour.
Let's build the Accordion
To help you get started with Radix UI, here's a quick tutorial on how to create a basic Accordion component using React and Radix UI.
- Install the '@radix-ui/react-accordion' package using npm or yarn.
npm install @radix-ui/react-accordion
- Import the components and make sure to add 'use client' at the top of the accordion component. We will create reusable components, so we will need forwardRef.
import { forwardRef } from "react"; import * as Accordion from "@radix-ui/react-accordion";
- We create each of the components. We will need an Item, a Trigger and a Content component.
const AccordionItem = forwardRef( ({ children, className, ...props }, forwardedRef) => ( <Accordion.Item className={ "mt-px overflow-hidden focus-within:relative focus-within:z-10 border-b border-b-slate-100 dark:border-b-slate-400 last:border-0 w-full" } {...props} ref={forwardedRef} > {children} </Accordion.Item> ) );
const AccordionTrigger = forwardRef( ({ children, className, ...props }, forwardedRef) => ( <Accordion.Header className="flex"> <Accordion.Trigger className={`accordion__trigger text-dark font-semibold dark:text-light shadow-black group flex flex-1 cursor-pointer items-center justify-between py-5 text-left outline-none hover:underline ${props.className}`} {...props} ref={forwardedRef} > {children} <ChevronDownIcon className="text-violet10 ease-[cubic-bezier(0.87,_0,_0.13,_1)] transition-transform duration-300 group-data-[state=open]:rotate-180" aria-hidden /> </Accordion.Trigger> </Accordion.Header> ) );
const AccordionContent = forwardRef( ({ children, className, ...props }, forwardedRef) => ( <Accordion.Content className={`text-black data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp overflow-hidden text-[15px] ${props.className} dark:text-white`} {...props} ref={forwardedRef} > <div className="py-[15px] px-5">{children}</div> </Accordion.Content> ) );
- Now we must add the animations into the tailwind.config file.
module.exports = { content: ['./App.jsx'], theme: { keyframes: { slideDown: { from: { height: 0 }, to: { height: 'var(--radix-accordion-content-height)' }, }, slideUp: { from: { height: 'var(--radix-accordion-content-height)' }, to: { height: 0 }, }, }, animation: { slideDown: 'slideDown 300ms cubic-bezier(0.87, 0, 0.13, 1)', slideUp: 'slideUp 300ms cubic-bezier(0.87, 0, 0.13, 1)', }, }, }, plugins: [], };
- Now we will put those together to make the full accordion.
const AccordionComp = ({ data }) => { return ( <Accordion.Root className="w-full rounded-md" type="single" defaultValue="1" collapsible > {data.map((item, i) => { return ( <AccordionItem value={i+1} key={item.title}> <AccordionTrigger>{item.title}</AccordionTrigger> <AccordionContent>{item.content}</AccordionContent> </AccordionItem> ); })} </Accordion.Root> ); };
- Now when we use this component, we will need to pass it some data with a title and content.
<AccordionComp data={data}/>
- Create the data as an array.
const data = [ { title: "Title 1", content: "Content 1" }, { title: "Title 2", content: "Content 2" }, ];
There we have it. A beautifully styled accordion that is fully customizable and with clean transitions.