Таблица

Передайте columns и rows — и таблица соберётся сама, вместе с шапкой. Она обёрнута в контейнер с горизонтальной прокруткой, поэтому таблица, у которой колонок больше, чем помещается на телефоне, прокручивается сама, а не растягивает страницу. Экспортируется и как table, и как dataTable.

Простая таблица

СтраницаРазмерВремя рендера
/4,1 кБ12 мс
/docs12,7 кБ31 мс
/examples9,4 кБ24 мс
table({
  columns: [
    { key: 'page', header: 'Страница' },
    { key: 'size', header: 'Размер' },
    { key: 'time', header: 'Время рендера' },
  ],
  rows: [
    { page: '/', size: '4,1 кБ', time: '12 мс' },
    { page: '/docs', size: '12,7 кБ', time: '31 мс' },
    { page: '/examples', size: '9,4 кБ', time: '24 мс' },
  ],
})

Выравнивание

Числа читаются лучше, когда выровнены по концу своей колонки.

СтраницаБайтыGzip
/4 1121 204
/docs12 7043 910
/examples9 3882 744
table({
  columns: [
    { key: 'page', header: 'Страница' },
    { key: 'bytes', header: 'Байты', align: 'end' },
    { key: 'gzip', header: 'Gzip', align: 'end' },
  ],
  rows: [
    { page: '/', bytes: '4 112', gzip: '1 204' },
    { page: '/docs', bytes: '12 704', gzip: '3 910' },
    { page: '/examples', bytes: '9 388', gzip: '2 744' },
  ],
})

Свои ячейки

Колонка с функцией render получает всю строку и возвращает то, что должно оказаться в ячейке: чип, ссылку, отформатированное число.

СтраницаРазмерСтатус
/docs/routing18,2 кБок
/docs/data21,7 кБок
/docs/islands24,1 кБошибка
table({
  columns: [
    { header: 'Страница', render: (row) => link({ href: row.href }, row.page) },
    { key: 'size', header: 'Размер', align: 'end' },
    { header: 'Статус', align: 'end', render: (row) =>
      chip({ size: 'sm', dot: true, color: row.ok ? 'success' : 'danger' }, row.ok ? 'ок' : 'ошибка') },
  ],
  rows: [
    { page: '/docs/routing', href: '/ru/docs/routing', size: '18,2 кБ', ok: true },
    { page: '/docs/data', href: '/ru/docs/data', size: '21,7 кБ', ok: true },
    { page: '/docs/islands', href: '/ru/docs/islands', size: '24,1 кБ', ok: false },
  ],
})

Стили

striped подкрашивает строки через одну, hover подсвечивает строку под курсором, а dense поджимает отступы для таблицы со множеством строк.

с полосами
ИмяЗначение
страницы169
ресурсы208
всего9,5 МБ
с подсветкой и плотная
ИмяЗначение
страницы169
ресурсы208
всего9,5 МБ
stack({ gap: 'lg' },
  table({
    striped: true,
    caption: 'с полосами',
    columns: [{ key: 'name', header: 'Имя' }, { key: 'value', header: 'Значение', align: 'end' }],
    rows: [{ name: 'страницы', value: '169' }, { name: 'ресурсы', value: '208' }, { name: 'всего', value: '9,5 МБ' }],
  }),
  table({
    hover: true,
    dense: true,
    caption: 'с подсветкой и плотная',
    columns: [{ key: 'name', header: 'Имя' }, { key: 'value', header: 'Значение', align: 'end' }],
    rows: [{ name: 'страницы', value: '169' }, { name: 'ресурсы', value: '208' }, { name: 'всего', value: '9,5 МБ' }],
  }),
)

Подпись таблицы

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

Результаты сборок, свежие сверху
КоммитКогдаСтраниц
94a837a4 минуты назад169
dcfaaae2 часа назад161
table({
  caption: 'Результаты сборок, свежие сверху',
  columns: [
    { key: 'commit', header: 'Коммит' },
    { key: 'when', header: 'Когда' },
    { key: 'pages', header: 'Страниц', align: 'end' },
  ],
  rows: [
    { commit: '94a837a', when: '4 минуты назад', pages: '169' },
    { commit: 'dcfaaae', when: '2 часа назад', pages: '161' },
  ],
})

Из данных

Строки — обычный массив, поэтому обычно это ровно то, что data() уже загрузил, без всякого переходника.

ПостОпубликованПрочтений
Привет, мир2026-01-141 204
Статика прежде всего2026-02-02890
Никакого рантайма2026-03-192 317
return (() => {
  const posts = [
    { title: 'Привет, мир', date: '2026-01-14', reads: 1204 },
    { title: 'Статика прежде всего', date: '2026-02-02', reads: 890 },
    { title: 'Никакого рантайма', date: '2026-03-19', reads: 2317 },
  ]

  return table({
    hover: true,
    columns: [
      { key: 'title', header: 'Пост' },
      { key: 'date', header: 'Опубликован' },
      { header: 'Прочтений', align: 'end', render: (post) => post.reads.toLocaleString('ru') },
    ],
    rows: posts,
  })
})()

Разметка своими руками

Опустите columns, и таблица нарисует вместо этого своих потомков: таблицу с итоговой строкой или сгруппированными заголовками можно собрать вручную и всё равно получить оформление и контейнер с прокруткой.

Пропсы

ПропТипПо умолчаниюОписание
columnsTableColumn[]—{ key, header, align, render } на колонку. Опустите, чтобы писать строки вручную.
rowsobject[][]По объекту на строку.
captionChild—Подпись над таблицей.
stripedbooleanfalseПодкрашивать строки через одну.
hoverbooleanfalseПодсвечивать строку под курсором.
densebooleanfalseБолее плотные отступы в ячейках.