Таблица данных
Data table строит таблицу из ваших строк и описаний столбцов: с сортировкой, изменением ширины столбцов, выбором строк, раскрывающимися строками и страницами.
<tk-data-table label="Quarterly revenue by region" hover></tk-data-table>
<tk-data-table id="revenue" label="Quarterly revenue by region" hover></tk-data-table>
<script>
const table = document.getElementById('revenue');
table.columns = [
{ key: 'region', header: 'Region', sortable: true },
{ key: 'lead', header: 'Lead', resizable: true, width: 220 },
{ key: 'revenue', header: 'Revenue', numeric: true, sortable: true },
];
table.data = [
{ id: 'emea', region: 'EMEA', lead: 'Alice Chen', revenue: 1204 },
{ id: 'apac', region: 'APAC', lead: 'Bo Nguyen', revenue: 987 },
{ id: 'amer', region: 'Americas', lead: 'Carla Diaz', revenue: 2130 },
];
</script>Анатомия
| Часть | Что это |
|---|---|
tk-data-table |
сам элемент; data и columns получает как JS-свойства |
| подпись | скрыта; в ней label, она называет таблицу |
| кнопка сортировки | заголовок сортируемого столбца |
| ручка ширины | край столбца, ширину которого можно менять; тянется мышью или стрелками |
| столбец выбора | чекбокс «выбрать всё» в шапке и по чекбоксу в каждой строке |
| кнопка раскрытия | шеврон в первой ячейке строки с дочерними строками |
part scroll |
контейнер прокрутки |
Столбцы
Каждый столбец — объект:
{
key: string; // the field on each row, and the column id
header: string; // the header text
align?: 'start' | 'center' | 'end';
numeric?: boolean; // end-aligned, tabular figures
sortable?: boolean;
resizable?: boolean;
width?: number; // initial width in px; unset shares the free space
minWidth?: number; // resize limit, default 48
maxWidth?: number; // resize limit, default 800
}Оставьте хотя бы один столбец без width, чтобы таблица заполняла контейнер. Если ширина
задана у всех столбцов, таблица будет ровно шириной их суммы.
Сортировка
Задайте столбцу sortable: true. Нажатие на заголовок переключает сортировку по
возрастанию, по убыванию и без сортировки. Текущая сортировка — в sort.
Каждое нажатие сначала вызывает tk-sort. preventDefault() на нём отменяет сортировку,
и заголовок сохраняет прежний значок.
table.addEventListener('tk-sort', (e) => {
console.log(e.detail); // { key: 'revenue', direction: 'asc' }
});Ширина столбцов
Задайте столбцу resizable: true. Тяните ручку на его краю или наведите на неё фокус и
используйте стрелки: ← и → меняют ширину на 8px, Home и End ставят minWidth и
maxWidth. Пока ручка под курсором, в фокусе или её тянут, по краю столбца через всю
таблицу идёт линия.
Каждое завершённое изменение вызывает tk-column-resize. Ширины — в columnSizing.
Выбор строк
selectable добавляет чекбокс в каждую строку и чекбокс «выбрать всё» в шапку. «Выбрать
всё» выбирает все строки на всех страницах. Выбор родительской строки выбирает и её
дочерние.
Задайте row-key — поле, уникальное и неизменное у каждой строки: по нему хранятся выбор
и раскрытые строки. Выбор читается из selectedKeys, изменения приходят в
tk-selection-change.
Раскрывающиеся строки
Задайте expandable и положите дочерние строки в children или в поле, указанное в
children-key. У строк с дочерними появляется кнопка раскрытия, дочерние идут с отступом.
Дочерние строки сортируются внутри своего родителя.
table.expandable = true;
table.data = [
{ id: 'emea', name: 'EMEA', headcount: 120, children: [
{ id: 'uk', name: 'United Kingdom', headcount: 45 },
]},
{ id: 'amer', name: 'Americas', headcount: 200 },
];Страницы
Задайте page-size, и отрисуется только текущая страница. Переключатель страниц — это
pageCount выводите по пункту на страницу, а при выборе пункта задаёте page (счёт с 0).
<tk-data-table id="records" label="Records" page-size="10"></tk-data-table>
<tk-pagination id="pages" label="Records pages"></tk-pagination>
<script>
const table = document.getElementById('records');
const pages = document.getElementById('pages');
const renderPages = () => {
pages.innerHTML = Array.from({ length: table.pageCount }, (_, i) =>
`<tk-pagination-item value="${i + 1}" ${i === table.page ? 'current' : ''}>${i + 1}</tk-pagination-item>`,
).join('');
};
pages.addEventListener('tk-page-select', (e) => {
table.page = Number(e.detail.value) - 1;
renderPages();
});
renderPages();
</script>Порядок столбцов
Чтобы переставить столбцы, задайте columnOrder — массив ключей столбцов. Перетаскивать
столбцы мышью нельзя.
Когда использовать
- Таблица данных — когда таблица что-то делает: сортирует, выбирает, раскрывает строки или листает страницы.
- Для статичной таблицы, написанной вручную, берите
Table . Выглядит она так же. - Для иерархии без столбцов, например файлового браузера, берите
Tree . Если столбцы есть — таблица данных сexpandable. - Данные остаются за приложением. Таблица хранит только состояние вида (сортировку, выбор, раскрытые строки, ширины, страницу) и никогда не загружает и не меняет ваши строки.
Можно / нельзя
| ✅ Можно | ❌ Нельзя |
|---|---|
| Таблица данных, когда строки сортируются, выбираются, раскрываются или листаются | Она же для статичной таблицы; берите |
Один столбец без width |
Фиксировать все ширины, если таблица не должна быть фиксированной ширины |
row-key с неизменным id |
Опознавать строки по позиции, когда данные меняются |
Заменять data новым массивом |
Менять строки внутри массива на месте |
expandable с вложенными дочерними строками |
Отдельная таблица-дерево |
Связанные
Table : тот же вид для таблицы, написанной вручную.Pagination : переключатель страниц для таблицы со страницами.Tree : иерархия без столбцов.Checkbox : контрол в столбце выбора.
API
Свойства
| Свойство | Тип | Что делает |
|---|---|---|
data |
object[] |
строки; таблица их не меняет. Чтобы обновить, замените массив |
columns |
ColumnDef[] |
описания столбцов; см. |
columnOrder |
string[] |
порядок столбцов в виде ключей |
Атрибуты
| Атрибут | Тип | По умолчанию | Что делает |
|---|---|---|---|
label |
string | название таблицы, обязательно | |
density |
comfortable | compact |
comfortable |
отступы ячеек, как в |
zebra |
boolean | false |
закрашивает каждую вторую строку |
hover |
boolean | false |
подсвечивает строку под курсором |
header-fill |
boolean | false |
заливает шапку |
sort-shape |
rect | round |
rect |
углы кнопки сортировки: скруглённые или полностью круглые |
selectable |
boolean | false |
добавляет столбец выбора |
expandable |
boolean | false |
у строк с дочерними появляется кнопка раскрытия |
children-key |
string | children |
поле с дочерними строками |
row-key |
string | id |
поле, которое опознаёт строку |
select-row-label |
string | Select {row} |
имя чекбокса строки; {row} — первая ячейка |
select-all-label |
string | Select all rows |
имя чекбокса в шапке |
resize-column-label |
string | Resize column: {column} |
имя ручки ширины; {column} — заголовок |
page-size |
number | строк на странице; без него видны все строки | |
page |
number | 0 |
текущая страница, счёт с 0 |
Свойства только для чтения
| Свойство | Тип | Что содержит |
|---|---|---|
sort |
{ key, direction } | null |
текущая сортировка |
selectedKeys |
string[] |
ключи выбранных строк |
expandedKeys |
string[] |
ключи раскрытых строк |
pageCount |
number | число страниц; без page-size — 1 |
columnSizing |
Record<string, number> |
ширины столбцов в px после изменения |
События
| Событие | Detail | Отменяемое | Когда |
|---|---|---|---|
tk-sort |
{ key, direction }; direction — asc, desc или null |
да | нажата кнопка сортировки |
tk-selection-change |
{ selectedKeys, key, selected }; у шапки key равен all |
да | переключён чекбокс |
tk-row-toggle |
{ key, expanded } |
да | нажата кнопка раскрытия |
tk-column-resize |
{ key, width } |
нет | изменение ширины закончено или нажата стрелка |
Все события всплывают из элемента. preventDefault() на отменяемом событии отменяет
изменение.
CSS
::part(scroll): контейнер прокрутки. Задайте емуmax-height, чтобы ограничить высоту таблицы.
Токены
Таблица данных берёт токены
| Элемент | Токены |
|---|---|
| кнопка сортировки | наведение state/hover, нажатие state/press |
| стрелка сортировки | icon/secondary; у отсортированного столбца icon/default |
| линия ширины | border/default; при наведении, фокусе и перетаскивании border/accent |
| выбранная строка | state/on; под курсором state/on-hover |
| кнопка раскрытия | icon/secondary; при наведении state/hover + icon/default |
| отступ дочерней строки | space-24 на уровень |
Рамки фокуса — border/accent/focus. Значения по темам:
Доступность
Встроено:
- Нативная таблица: скринридер получает настоящие строки, заголовки столбцов и ячейки, а
labelназывает таблицу. - Кнопка сортировки — настоящая кнопка с именем из заголовка; у отсортированного столбца
есть
aria-sort. - Ручка ширины — разделитель в фокусе с именем «Resize column: {header}» и шириной в качестве значения.
- Чекбоксы называются «Select all rows» и «Select {row}». Чекбокс в шапке показывает смешанное состояние, когда выбрана часть строк.
- Кнопка раскрытия названа по своей строке и имеет
aria-expanded. У строк естьaria-level, а свёрнутые дочерние строки не отрисовываются. - Если таблица шире контейнера, контейнер прокрутки становится остановкой Tab и областью с именем.
На вашей стороне:
- Всегда задавайте
label. - Дайте каждой строке поле
row-key(по умолчаниюid). Строки без него опознаются по позиции, и при смене данных выбор переезжает на другие строки. - Переводите
select-row-label,select-all-labelиresize-column-labelна другие языки. - Не передавайте смысл цветом строки. Выбор несёт чекбокс.
| Клавиша | Действие |
|---|---|
Tab |
переходит по кнопкам сортировки, ручкам ширины, чекбоксам и кнопкам раскрытия |
Enter / Space |
нажимает кнопку сортировки или раскрытия; Space переключает чекбокс |
← / → |
на ручке ширины сужает или расширяет столбец на 8px |
Home / End |
на ручке ширины ставит наименьшую или наибольшую ширину |