Accordion
Allows you to display content in a collapsible manner, making it easy for users to access information while conserving screen space.
Installation
Install the following dependencies:
npm install @radix-ui/react-accordionCreate a accordion.tsx file and paste the following code into it.
// CoreUI Accordion v0.0.0'use client';import * as React from 'react';import * as AccordionPrimitive from '@radix-ui/react-accordion';import { RiAddLine, RiSubtractLine } from '@remixicon/react';import { cn } from '@/utils/cn';import type { PolymorphicComponentProps } from '@/utils/polymorphic';const ACCORDION_ITEM_NAME = 'AccordionItem';const ACCORDION_ICON_NAME = 'AccordionIcon';const ACCORDION_ARROW_NAME = 'AccordionArrow';const ACCORDION_TRIGGER_NAME = 'AccordionTrigger';const ACCORDION_CONTENT_NAME = 'AccordionContent';const AccordionRoot = AccordionPrimitive.Root;const AccordionHeader = AccordionPrimitive.Header;const AccordionItem = React.forwardRef< React.ComponentRef<typeof AccordionPrimitive.Item>, React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>>(({ className, ...rest }, forwardedRef) => { return ( <AccordionPrimitive.Item ref={forwardedRef} className={cn( // base 'group/accordion', 'rounded-10 bg-bg-white-0 p-3.5 ring-1 ring-inset ring-stroke-soft-200', 'transition duration-200 ease-out', // hover 'hover:bg-bg-weak-50 hover:ring-transparent', // has-focus-visible 'has-[:focus-visible]:bg-bg-weak-50 has-[:focus-visible]:ring-transparent', // open 'data-[state=open]:bg-bg-weak-50 data-[state=open]:ring-transparent', className, )} {...rest} /> );});AccordionItem.displayName = ACCORDION_ITEM_NAME;const AccordionTrigger = React.forwardRef< React.ComponentRef<typeof AccordionPrimitive.Trigger>, React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>>(({ children, className, ...rest }, forwardedRef) => { return ( <AccordionPrimitive.Trigger ref={forwardedRef} className={cn( // base 'w-[calc(100%+theme(space.7))] text-left text-label-sm text-text-strong-950', 'grid auto-cols-auto grid-flow-col grid-cols-[auto_minmax(0,1fr)] items-center gap-2.5', '-m-3.5 p-3.5 outline-none', // focus 'focus:outline-none', className, )} {...rest} > {children} </AccordionPrimitive.Trigger> );});AccordionTrigger.displayName = ACCORDION_TRIGGER_NAME;function AccordionIcon<T extends React.ElementType>({ className, as, ...rest}: PolymorphicComponentProps<T>) { const Component = as || 'div'; return ( <Component className={cn('size-5 text-text-sub-600', className)} {...rest} /> );}AccordionIcon.displayName = ACCORDION_ICON_NAME;type AccordionArrowProps = React.HTMLAttributes<HTMLDivElement> & { openIcon?: React.ElementType; closeIcon?: React.ElementType;};// open/closefunction AccordionArrow({ className, openIcon: OpenIcon = RiAddLine, closeIcon: CloseIcon = RiSubtractLine, ...rest}: AccordionArrowProps) { return ( <> <OpenIcon className={cn( 'size-5 text-text-soft-400', 'transition duration-200 ease-out', // hover 'group-hover/accordion:text-text-sub-600', // open 'group-data-[state=open]/accordion:hidden', className, )} {...rest} /> <CloseIcon className={cn( 'size-5 text-text-sub-600', // close 'hidden group-data-[state=open]/accordion:block', className, )} {...rest} /> </> );}AccordionArrow.displayName = ACCORDION_ARROW_NAME;const AccordionContent = React.forwardRef< React.ComponentRef<typeof AccordionPrimitive.Content>, React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>>(({ children, className, ...rest }, forwardedRef) => { return ( <AccordionPrimitive.Content ref={forwardedRef} className='overflow-hidden data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down' {...rest} > <div className={cn('pt-1.5 text-paragraph-sm text-text-sub-600', className)} > {children} </div> </AccordionPrimitive.Content> );});AccordionContent.displayName = ACCORDION_CONTENT_NAME;export { AccordionRoot as Root, AccordionHeader as Header, AccordionItem as Item, AccordionTrigger as Trigger, AccordionIcon as Icon, AccordionArrow as Arrow, AccordionContent as Content,};Examples
Arrow Position
API Reference
This component is based on the Radix UI Accordion primitives. Refer to their documentation for the API reference.
Accordion.Root
This component is based on the Accordion.Root primitive.
Accordion.Item
This component is based on the Accordion.Item primitive.
Accordion.Header
This component is based on the Accordion.Header primitive.
Accordion.Trigger
This component is based on the Accordion.Trigger primitive.
Accordion.Content
This component is based on the Accordion.Content primitive.
Accordion.Icon
This component is polymorphic, allowing you to change the underlying HTML element using the as prop.
| Prop | Type | Default |
|---|---|---|
as | React.ElementType | div |
Accordion.Arrow
The Accordion.Arrow component displays an icon that toggles between an open and closed state based on the accordion's state.
| Prop | Type | Default |
|---|---|---|
openIcon | React.ElementType | RiAddLine |
closeIcon | React.ElementType | RiSubtractLine |