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

Tree

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

Рендер плоский: дерево розгортається у список видимих рядків (вузол, глибина, стан), тож у шаблоні один v-for без рекурсивних компонентів. ARIA-геометрія тримається атрибутами aria-level, aria-expanded.

Приклад

example.com
Головна
Про нас
Кошик (порожній)

Вибрано: home · відкриті: example · клік: —

API

Props

НазваТипТиповоОпис
items*TreeNode[]—Дерево. Джерело правди — масив коренів.
modelValuestringnullВибраний вузол. Використовуйте через `v-model`.
expandedstring[][]Відкриті вузли. Використовуйте через `v-model:expanded`.
expandOnClickbooleantrueКлік по рядку з дітьми тогглить гілку.
selectablebooleantrueКлік по рядку обирає вузол.

Події

НазваPayloadОпис
update:modelValue[id: string]Вибраний вузол або `null`. Використовуйте через `v-model`.
update:expanded[ids: string[]]Набір відкритих вузлів. Використовуйте через `v-model:expanded`.
itemClick[{ node: TreeNode; depth: number; }]Активація рядка кліком або Enter.

Слоти

НазваОпис
itemВласний рендер рядка.
toggleВласна іконка тоггла замість шеврона.

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

Ієрархічні структури: дерево сторінок сайту, файлів, категорій. Розгортання керується згори через v-model:expanded — можна відкривати гілки з URL або синхронізувати дві панелі.

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

Для плоских списків із заголовками — Tree надлишковий, потрібен простий список або Menu.

Для маленьких вкладених фільтрів (2 рівні, 5 пунктів) — чекбокси з відступами простіші за дерево.

Доступність

role="tree" → treeitem з aria-level, aria-expanded, aria-selected. Roving tabindex: Tab — лише активний рядок, ↑↓ рухають виділення, → розгортає, ← згортає або підіймається до батька. Тоггл-кнопка окрема від рядка: розгортання не провокує вибір.

Tab завжди має куди потрапити. Якщо вибраний вузол сховано в згорнутій гілці (v-model вказує на дитину, або гілку згорнули ззовні), точкою входу стає його найближчий видимий предок, інакше — перший рядок. Раніше тоді жоден рядок не мав tabindex="0", і дерево з клавіатури було недосяжне. Зміна v-model ззовні переносить точку входу на новий вибір.

Шеврон на дотику має невидиму зону 45px завширшки на всю висоту рядка: з expandOnClick: false він єдиний спосіб розгорнути гілку пальцем. Вище за рядок зона не росте — інакше зони сусідніх шевронів перекривались би.

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

Відступ — padding-left: depth * 1.25rem через :style, а не класи: глибина довільна, JIT не може її передбачити.