We offer a 30-day money-back guarantee. If you are not satisfied with our product, you can request a refund within 30 days of purchase.

You can contact our support team by sending an email

Yes, you can upgrade your plan at any time. Just contact our support team, and they will help you with the upgrade process.

Yes, we offer a 14-day free trial. You can sign up for the free trial on our website.

You can cancel your subscription at any time. Just log in to your account and go to the subscription page to cancel your subscription.

Installation
npm i framer-motion lucide-react
import { Plus, Minus } from "lucide-react";
import { useState, useRef, useEffect } from "react";

function AccordionItem({ title, content, isActive, onClick }) {
    const contentRef = useRef(null);
    const [height, setHeight] = useState(0);

    useEffect(() => {
        setHeight(isActive ? contentRef.current.scrollHeight : 0);
    }, [isActive]);

    return (
        <div className="border-b">
            <button
                className="w-full p-4 text-left bg-secondary focus:outline-none transition-colors duration-300"
                onClick={onClick}
            >
                <div className="flex items-center justify-between">
                    <span className="text-sm">{title}</span>
                    {isActive ? <Minus size={14} /> : <Plus size={14} />}
                </div>
            </button>
            <div
                style={{ height }}
                className="overflow-hidden transition-[height] duration-300 ease-in-out"
            >
                <div ref={contentRef} className="p-4 ">
                    <p className="text-sm">{content}</p>
                </div>
            </div>
        </div>
    );
};

export default function Accordion({ items }) {
    const [activeIndex, setActiveIndex] = useState(null);

    const toggleAccordion = (index) => {
        setActiveIndex(activeIndex === index ? null : index);
    };

    return (
        <div className="w-full border rounded-lg overflow-hidden">
            {items.map((item, index) => (
                <AccordionItem
                    key={index}
                    title={item.title}
                    content={item.content}
                    isActive={activeIndex= index}
                    onClick={()=> toggleAccordion(index)}
                />
            ))}
        </div>
    );
};
With Border

We offer a 30-day money-back guarantee. If you are not satisfied with our product, you can request a refund within 30 days of purchase.

You can contact our support team by sending an email

Yes, you can upgrade your plan at any time. Just contact our support team, and they will help you with the upgrade process.

Yes, we offer a 14-day free trial. You can sign up for the free trial on our website.

You can cancel your subscription at any time. Just log in to your account and go to the subscription page to cancel your subscription.

import { Plus, Minus } from "lucide-react";
import { useState, useRef, useEffect } from "react";

function AccordionBorderItem({ title, content, isActive, onClick }) {
    const contentRef = useRef(null);
    const [height, setHeight] = useState(0);

    useEffect(() => {
        setHeight(isActive ? contentRef.current.scrollHeight : 0);
    }, [isActive]);

    return (
        <div className="border-b">
            <button
                className="w-full p-4 text-left bg-secondary focus:outline-none transition-colors duration-300"
                onClick={onClick}
            >
                <div className="flex items-center justify-between">
                    <span className="text-sm">{title}</span>
                    {isActive ? <Minus size={14} /> : <Plus size={14} />}
                </div>
            </button>
            <div
                style={{ height }}
                className="overflow-hidden transition-[height] duration-300 ease-in-out"
            >
                <div ref={contentRef} className="p-4 ">
                    <p className="text-sm">{content}</p>
                </div>
            </div>
        </div>
    );
};

export default function AccordionBorder({ items }) {
    const [activeIndex, setActiveIndex] = useState(null);

    const toggleAccordion = (index) => {
        setActiveIndex(activeIndex === index ? null : index);
    };

    return (
        <div className="w-full border rounded-lg overflow-hidden">
            {items.map((item, index) => (
                <AccordionBorderItem
                    key={index}
                    title={item.title}
                    content={item.content}
                    isActive={activeIndex= index}
                    onClick={()=> toggleAccordion(index)}
                />
            ))}
        </div>
    );
};

Accordion with border and simple animation and transition effect.