Перейти до вмісту
tatetUI

Accordion

Розкривні секції з анімацією висоти без JS-вимірювань.

Акордеон для секцій, які мають бути під рукою, але не на виду: розкривні налаштування, FAQ, деревоподібні фільтри. Типово кілька секцій можуть бути відкриті одночасно; single лишає рівно одну — для FAQ і майстрів, де секції взаємовиключні.

Приклад

Назва сайту, мови версій, головна сторінка. Типові поля, які потрібні рідко, але мають бути під рукою.

API

Props

НазваТипТиповоОпис
items*AccordionItem[]—Секції акордеона.
modelValuestring[]undefinedВідкриті секції. Використовуйте через `v-model`. Без `v-model` компонент керує станом сам, починаючи з `defaultOpen`.
defaultOpenstring[][]Початково відкриті id — лише в некерованому режимі.
headingLevel2 | 3 | 4 | 5 | 63Рівень заголовків секцій. Має продовжувати структуру сторінки: акордеон під `h2` — це `3`, у модалці з заголовком `h2` — теж `3`, у секції з `h3` — `4`. Інакше скрінрідер будує хибний зміст.
showTogglebooleantrueПоказувати шеврон праворуч.
singlebooleanfalseЛише одна відкрита секція: відкриття наступної закриває попередню. Для FAQ і майстрів налаштувань, де секції взаємовиключні.

Події

НазваPayloadОпис
update:modelValue[ids: string[]]Набір відкритих секцій змінився. Використовуйте через `v-model`.
open[id: string]Секцію відкрито.
close[id: string]Секцію закрито.

Слоти

НазваОпис
labelВласний рендер заголовка секції.

Коли використовувати

Коли вмісту більше, ніж місця, і він не потрібен одночасно весь.

Керований режим через v-model — коли стан відкритих секцій треба читати або писати згори (фільтри в URL, синхронізація між панелями). У керованому режимі стан приходить лише згори: клік емітить update:modelValue, але секція відкриється тільки тоді, коли батько прийме нове значення. Батько, що відхилив зміну, більше не бачить відкритої секції, якої немає в його modelValue.

Коли НЕ використовувати

Для навігаційних розділів — навігація має бути видимою, а не схованою за кліком.

Не вкладайте акордеон в акордеон: замість ієрархії виходить лабіринт.

Доступність

Кожен заголовок — <button> всередині заголовка рівня headingLevel (типово <h3>), з aria-expanded і aria-controls; панель — role="region" з aria-labelledby. Рівень має продовжувати структуру сторінки: акордеон у секції з <h3> — це heading-level="4", інакше скрінрідер будує хибний зміст. Секція «розкрита» для скрінрідера залишалась би зрозумілою навіть без анімації — анімація тут прикраса, не носій сенсу.

Якщо секцію з фокусом усередині закрили згори (v-model), фокус повертається на її заголовок до того, як inert сховає панель, — а не падає в <body>. На дотику заголовок має щонайменше 44px заввишки.

Заголовки зв'язані клавіатурною навігацією: ↑/↓ переходить до попередньої/наступної секції, Home/End — до першої/останньої (лише фокус; відкриття — Enter/Space або клік, як у вкладках).

Деталі реалізації

Плавне розкриття — через grid-template-rows: 0fr → 1fr: висота анімується без JS-вимірювань і без жорсткої max-height. Глобальний prefers-reduced-motion вимикач зупиняє transition сам.