Компоненты/Аккордеон со стеклянными иконками

Аккордеон со стеклянными иконками

29 сентября 2026

Аккордеон со стеклянными иконками: пункт раскрывается на пружине, отделяется зазорами и скругляет соседние углы.

Установка

npm install clsx lucide-react motion tailwind-merge
pnpm add clsx lucide-react motion tailwind-merge
yarn add clsx lucide-react motion tailwind-merge
bun add clsx lucide-react motion tailwind-merge

Файлы

bouncy-accordion-web.tsx
НазадУпругий аккордеонДалееПрелоадер из ячеек

Список пунктов, собранный в единый блок со стеклянными иконками. По нажатию пункт на пружине вырастает, отодвигается от соседей зазорами и становится отдельной скруглённой карточкой, а под заголовком из размытия проявляется описание.

Соседние пункты тоже реагируют: их углы, примыкающие к раскрытому, скругляются, поэтому список распадается на аккуратные группы. Повторное нажатие или клик мимо сворачивает пункт, и блок снова смыкается.

Вручную

Скопируйте эти файлы в components/bouncy-accordion-web/:

Общие помощники положите в lib/ проекта:

Проверьте алиас путей. Импорты в коде выше записаны как @/components/... и @/lib/.... Нужен алиас "@/*" на папку, где лежат components/ и lib/, в tsconfig.json — или поправьте импорты под свои пути.

Использование

import { Calendar, CreditCard, Star } from "lucide-react";

import { BouncyAccordion } from "@/components/bouncy-accordion-web/bouncy-accordion-web";

const ITEMS = [
{ icon: <Calendar className="size-5" />, title: "Расписание", description: "Планируйте задачи с напоминаниями." },
{ icon: <CreditCard className="size-5" />, title: "Покупки", description: "Быстрая покупка и безопасная оплата." },
{ icon: <Star className="size-5" />, title: "Избранное", description: "Отмечайте избранное и ставьте оценки." },
];

export function Features() {
return <BouncyAccordion items={ITEMS} defaultActiveIndex={0} width={320} />;
}

Пропсы

Пропс
Описание
items

Пункты: иконка, заголовок и описание

Тип BouncyAccordionItem[]

activeIndex?

Открытый пункт в управляемом режиме

Тип number | null

defaultActiveIndex?

Пункт, открытый при загрузке

Тип number | null·По умолчанию 2

onActiveChange?

Вызывается при смене открытого пункта

Тип (index: number | null) => void

width?

Ширина списка в пикселях

Тип number·По умолчанию 300

itemHeight?

Высота свёрнутого пункта

Тип number·По умолчанию 45

openHeight?

Высота раскрытого пункта

Тип number·По умолчанию 93

gap?

Зазор вокруг раскрытого пункта

Тип number·По умолчанию 10

radius?

Скругление углов

Тип number·По умолчанию 20

stiffness?

Жёсткость пружины

Тип number·По умолчанию 300

damping?

Затухание пружины

Тип number·По умолчанию 20

itemColor?

Цвет фона пунктов

Тип string

className?

Классы списка

Тип string