Accordion
blode-ui/accordionFreeComponent
A vertically stacked set of interactive headings that reveal or hide associated content.
Install it
npx shadcn@latest add https://raw.githubusercontent.com/mblode/blode-ui/main/public/r/accordion.jsonSource
1"use client";23import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion";4import { AnimatePresence, motion } from "motion/react";5import type { HTMLMotionProps, Transition } from "motion/react";6import {7 createContext,8 useCallback,9 useContext,10 useEffect,11 useImperativeHandle,12 useMemo,13 useRef,14 useState,15} from "react";16import type { ComponentProps } from "react";1718import { cn } from "@/lib/utils";1920interface AccordionItemContextType {21 canAnimate: boolean;22 isOpen: boolean;23 setCanAnimate: (canAnimate: boolean) => void;24 setIsOpen: (open: boolean) => void;25}2627const AccordionItemContext = createContext<AccordionItemContextType | undefined>(undefined);2829const useAccordionItem = (): AccordionItemContextType => {30 const context = useContext(AccordionItemContext);31 if (!context) {32 throw new Error("useAccordionItem must be used within an AccordionItem");33 }34 return context;35};3637type AccordionValue = string | string[];3839type AccordionProps = Omit<40 ComponentProps<typeof AccordionPrimitive.Root>,41 "defaultValue" | "multiple" | "onValueChange" | "value"42> & {43 type?: "single" | "multiple";44 collapsible?: boolean;45 value?: AccordionValue;46 defaultValue?: AccordionValue;47 onValueChange?: (value: AccordionValue) => void;48};4950const normalizeAccordionValue = (value: AccordionValue | undefined): string[] | undefined => {51 if (value === undefined) {52 return undefined;53 }5455 if (Array.isArray(value)) {56 return value;57 }5859 return value === "" ? [] : [value];60};6162const Accordion = ({63 type = "single",64 collapsible = false,65 value,66 defaultValue,67 onValueChange,68 ...props69}: AccordionProps) => {70 const multiple = type === "multiple";7172 const handleValueChange = useCallback(73 (nextValue: (unknown | null)[]) => {74 if (!onValueChange) {75 return;76 }7778 const nextStringValues = nextValue.filter((item): item is string => typeof item === "string");7980 if (multiple) {81 onValueChange(nextStringValues);82 return;83 }8485 const [firstValue] = nextStringValues;86 if (firstValue !== undefined) {87 onValueChange(firstValue);88 return;89 }9091 if (collapsible) {92 onValueChange("");93 }94 },95 [collapsible, multiple, onValueChange],96 );9798 return (99 <AccordionPrimitive.Root100 data-slot="accordion"101 defaultValue={normalizeAccordionValue(defaultValue)}102 multiple={multiple}103// … truncated
What it pulls in
npm packages
Files it writes
More from blode/ui
All 85 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Alertalert | blode/ui | Components | Free | no deps | |
| Alert Dialogalert-dialog | blode/ui | Components | Free | 1 dep | |
| Ask User Questionsask-user-questions | blode/ui | Components | Free | 1 dep | |
| Aspect Ratioaspect-ratio | blode/ui | Components | Free | 1 dep | |
| Attachmentattachment | blode/ui | Components | Free | 1 dep | |
| Autocompleteautocomplete | blode/ui | Components | Free | 1 dep | |
| Avataravatar | blode/ui | Components | Free | 1 dep | |
| Badgebadge | blode/ui | Components | Free | 1 dep |
