Unfold List
loomui/unfold-listFreeComponent
A disclosure list whose panels turn down onto the page from their top edge.
Live preview
live · rendered by the registry
Rendered by loomui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://loomui.design/r/unfold-list.jsonSource
1"use client"23import * as React from "react"45import { cn } from "@/lib/utils"67interface UnfoldState {8 open: string[]9 toggle: (value: string) => void10 duration: number11}1213const UnfoldContext = React.createContext<UnfoldState | null>(null)1415function useUnfold() {16 const context = React.useContext(UnfoldContext)17 if (!context) {18 throw new Error("UnfoldItem must be rendered inside an UnfoldList.")19 }20 return context21}2223export interface UnfoldListProps extends Omit<24 React.ComponentProps<"div">,25 "defaultValue" | "onChange"26> {27 /** One panel open at a time, or as many as the reader wants. */28 type?: "single" | "multiple"29 /** Panels open before anyone has touched the list. */30 defaultValue?: string | string[]31 /** Open panels, if you are holding the state yourself. */32 value?: string | string[]33 /** Called with the open panels whenever they change. */34 onValueChange?: (value: string[]) => void35 /** In `single` mode, allow the open panel to be closed again. */36 collapsible?: boolean37 /** Milliseconds one panel takes to unfold. */38 duration?: number39}4041const toArray = (value: string | string[] | undefined) =>42 value === undefined ? [] : Array.isArray(value) ? value : [value]4344export function UnfoldList({45 children,46 className,47 type = "single",48 defaultValue,49 value,50 onValueChange,51 collapsible = true,52 duration = 320,53 ...props54}: UnfoldListProps) {55 const [ownOpen, setOwnOpen] = React.useState(() => toArray(defaultValue))56 const isControlled = value !== undefined57 const open = isControlled ? toArray(value) : ownOpen5859 const toggle = React.useCallback(60 (item: string) => {61 const isOpen = open.includes(item)62 const next =63 type === "single"64 ? isOpen65 ? collapsible66 ? []67 : open68 : [item]69 : isOpen70 ? open.filter((entry) => entry !== item)71 : [...open, item]7273 if (!isControlled) {74 setOwnOpen(next)75 }76 onValueChange?.(next)77 },78 [open, type, collapsible, isControlled, onValueChange]79 )8081 const state = React.useMemo(82 () => ({ open, toggle, duration }),83 [open, toggle, duration]84 )8586 return (87 <UnfoldContext.Provider value={state}>88 <div89 data-slot="unfold-list"90 className={cn(91 "divide-border border-border divide-y border-y",92 className93 )}94 {...props}95 >96 {children}97 </div>98 </UnfoldContext.Provider>99// … truncated
What it pulls in
Other registry items
Files it writes
More from loomui
All 91 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Aurora Backdropaurora-backdrop | loomui | Components | Free | no deps | |
| Bento Gridbento-grid | loomui | Components | Free | no deps | |
| Card Stackcard-stack | loomui | Components | Free | no deps | |
| Compare Slidercompare-slider | loomui | Components | Free | no deps | |
| Confetti Buttonconfetti-button | loomui | Components | Free | no deps | |
| Count Upcount-up | loomui | Components | Free | no deps | |
| Credit Cardcredit-card | loomui | Components | Free | no deps | |
| Drawerdrawer | loomui | Components | Free | 1 dep |
