Collapsible
100% RSC0kb
Example
This section provides a brief overview of the Collapsible Component, illustrating how it can be utilized to create expandable and collapsible sections within your application. Ideal for organizing content or hiding detailed information until requested by the user.
Requirements
pnpm add react-icons class-variance-authoritybun add react-icons class-variance-authorityyarn add react-icons class-variance-authoritynpm install react-icons class-variance-authorityCode
import cn from '@/utils/cn'
import { applyPropsToChildrenOfType } from '@/utils/manipulateReactComponents'
import React, { useId } from 'react'
import { HiChevronRight } from 'react-icons/hi2'
import { type VariantProps, cva } from 'class-variance-authority'
const Collapsible: React.FC<
VariantProps<typeof cvaCollapsibleContent> & {
children: React.ReactNode
className?: string
openByDefault?: boolean
duration?: number
accordionId?: string
}
> = ({ children, className, openByDefault = false, duration = 300, animation, accordionId }) => {
const id = useId()
children = applyPropsToChildrenOfType(children, { id, openByDefault, animation, accordionId }, [CollapsibleContent, CollapsibleTrigger])
return (
<div className={cn('relative', className)} style={{ '--animation-duration': `${duration}ms` } as React.CSSProperties}>
{children}
</div>
)
}
Collapsible.displayName = 'Collapsible'
const CollapsibleTrigger: React.FC<{
id?: string
children: React.ReactNode
openByDefault?: boolean
className?: string
classNames?: { icon?: string }
accordionId?: string
}> = ({ id, classNames = {}, children, className, openByDefault, accordionId }) => (
<>
<input type={accordionId ? 'radio' : 'checkbox'} name={accordionId || undefined} id={id} className="peer hidden" defaultChecked={openByDefault} />
<label htmlFor={id} className={cn('collapsible group grid cursor-pointer select-none grid-flow-col grid-cols-[minmax(0,_1fr)_auto] items-center', className)}>
{children}
<span
className={cn(
'h-8 w-8 justify-self-end p-1 text-white outline-none transition-transform duration-[var(--animation-duration)] peer-checked:group-[.collapsible]:rotate-90',
classNames?.icon
)}>
<HiChevronRight className="h-full w-full" />
</span>
</label>
</>
)
CollapsibleTrigger.displayName = 'CollapsibleTrigger'
const cvaCollapsibleContent = cva(
[
'group',
'grid',
'origin-top',
'transform-gpu',
'overflow-hidden',
'transition-all',
'duration-[--animation-duration]',
'ease-in-out',
'peer-checked:grid-rows-[1fr]',
'grid-rows-[0fr]',
'peer-[:not(:checked)]:!py-0'
],
{
variants: {
animation: {
fade: '[&>*]:invisible opacity-0 [&>*]:opacity-0 [&>*]:transition-all peer-checked:opacity-100 [&>*]:duration-300 peer-checked:[&>*]:visible peer-checked:[&>*]:opacity-100',
'slide-down':
'origin-top -translate-y-2 peer-checked:translate-y-0 [&>*]:invisible opacity-0 peer-checked:opacity-100 [&>*]:opacity-0 [&>*]:transition-all [&>*]:ease-in-out peer-checked:[&>*]:visible peer-checked:[&>*]:opacity-100',
'scale-fade':
'origin-top [&>*]:invisible scale-95 peer-checked:scale-100 opacity-0 peer-checked:opacity-100 [&>*]:opacity-0 [&>*]:transition-all [&>*]:duration-[--animation-duration] [&>*]:ease-in-out peer-checked:[&>*]:visible peer-checked:[&>*]:opacity-100',
none: '[&>*]:visible'
}
}
}
)
const CollapsibleContent: React.FC<
VariantProps<typeof cvaCollapsibleContent> & {
id?: string
className?: string
innerClassName?: string
children: React.ReactNode
accordionId?: string
}
> = ({ children, className, innerClassName, animation = 'scale-fade' }) => (
<div
className={cn(
cvaCollapsibleContent({
animation
}),
className
)}>
<div className={cn('min-h-0', innerClassName)}>{children}</div>
</div>
)
CollapsibleContent.displayName = 'CollapsibleContent'
export { Collapsible, CollapsibleContent, CollapsibleTrigger }
Usage
<Collapsible openByDefault={true} animation="scale-fade">
<CollapsibleTrigger className="p-3">
Introduction to Collapsible Component
</CollapsibleTrigger>
<CollapsibleContent className="p-3">
This section provides a brief overview of the Collapsible Component, illustrating how it can be utilized to create expandable and collapsible sections within your application. Ideal for organizing content or hiding detailed information until requested by the user.
</CollapsibleContent>
</Collapsible>