Tabela

Podaj columns i rows, a tabela zbuduje się sama, razem z nagłówkiem. Jest owinięta w kontener z poziomym przewijaniem, więc tabela z większą liczbą kolumn, niż zmieści telefon, przewija się sama, zamiast rozciągać stronę. Eksportowana i jako table, i jako dataTable.

Podstawowa tabela

StronaRozmiarCzas renderu
/4,1 kB12 ms
/docs12,7 kB31 ms
/examples9,4 kB24 ms
table({
  columns: [
    { key: 'page', header: 'Strona' },
    { key: 'size', header: 'Rozmiar' },
    { key: 'time', header: 'Czas renderu' },
  ],
  rows: [
    { page: '/', size: '4,1 kB', time: '12 ms' },
    { page: '/docs', size: '12,7 kB', time: '31 ms' },
    { page: '/examples', size: '9,4 kB', time: '24 ms' },
  ],
})

Wyrównanie

Liczby lepiej czyta się wyrównane do końca swojej kolumny.

StronaBajtyGzip
/41121204
/docs12 7043910
/examples93882744
table({
  columns: [
    { key: 'page', header: 'Strona' },
    { key: 'bytes', header: 'Bajty', align: 'end' },
    { key: 'gzip', header: 'Gzip', align: 'end' },
  ],
  rows: [
    { page: '/', bytes: '4112', gzip: '1204' },
    { page: '/docs', bytes: '12 704', gzip: '3910' },
    { page: '/examples', bytes: '9388', gzip: '2744' },
  ],
})

Własne komórki

Kolumna z funkcją render dostaje cały wiersz i zwraca to, co ma być w komórce — żeton, odnośnik, sformatowaną liczbę.

StronaRozmiarStatus
/docs/routing18,2 kBok
/docs/data21,7 kBok
/docs/islands24,1 kBbłąd
table({
  columns: [
    { header: 'Strona', render: (row) => link({ href: row.href }, row.page) },
    { key: 'size', header: 'Rozmiar', align: 'end' },
    { header: 'Status', align: 'end', render: (row) =>
      chip({ size: 'sm', dot: true, color: row.ok ? 'success' : 'danger' }, row.ok ? 'ok' : 'błąd') },
  ],
  rows: [
    { page: '/docs/routing', href: '/docs/routing', size: '18,2 kB', ok: true },
    { page: '/docs/data', href: '/docs/data', size: '21,7 kB', ok: true },
    { page: '/docs/islands', href: '/docs/islands', size: '24,1 kB', ok: false },
  ],
})

Style

striped barwi co drugi wiersz, hover podświetla wiersz pod wskaźnikiem, a dense ściska odstępy dla tabeli z wieloma wierszami.

striped
NazwaWartość
strony169
zasoby208
razem9,5 MB
hover i dense
NazwaWartość
strony169
zasoby208
razem9,5 MB
stack({ gap: 'lg' },
  table({
    striped: true,
    caption: 'striped',
    columns: [{ key: 'name', header: 'Nazwa' }, { key: 'value', header: 'Wartość', align: 'end' }],
    rows: [{ name: 'strony', value: '169' }, { name: 'zasoby', value: '208' }, { name: 'razem', value: '9,5 MB' }],
  }),
  table({
    hover: true,
    dense: true,
    caption: 'hover i dense',
    columns: [{ key: 'name', header: 'Nazwa' }, { key: 'value', header: 'Wartość', align: 'end' }],
    rows: [{ name: 'strony', value: '169' }, { name: 'zasoby', value: '208' }, { name: 'razem', value: '9,5 MB' }],
  }),
)

Podpis

Podpis nazywa tabelę dla kogoś, kto trafia na nią bez otaczającego tekstu — warto go dodać zawsze, gdy tabela nie stoi bezpośrednio pod nagłówkiem mówiącym już, czym jest.

Wynik buildu, od najnowszego
CommitKiedyStrony
94a837a4 minuty temu169
dcfaaae2 godziny temu161
table({
  caption: 'Wynik buildu, od najnowszego',
  columns: [
    { key: 'commit', header: 'Commit' },
    { key: 'when', header: 'Kiedy' },
    { key: 'pages', header: 'Strony', align: 'end' },
  ],
  rows: [
    { commit: '94a837a', when: '4 minuty temu', pages: '169' },
    { commit: 'dcfaaae', when: '2 godziny temu', pages: '161' },
  ],
})

Z danych

Wiersze to zwykła tablica, więc zwykle są dokładnie tym, co data() już wczytało — bez żadnego adaptera po drodze.

WpisOpublikowanoOdsłony
Witaj świecie2026-01-141204
Najpierw statyczne2026-02-02890
Bez runtime’u2026-03-192317
return (() => {
  const posts = [
    { title: 'Witaj świecie', date: '2026-01-14', reads: 1204 },
    { title: 'Najpierw statyczne', date: '2026-02-02', reads: 890 },
    { title: 'Bez runtime’u', date: '2026-03-19', reads: 2317 },
  ]

  return table({
    hover: true,
    columns: [
      { key: 'title', header: 'Wpis' },
      { key: 'date', header: 'Opublikowano' },
      { header: 'Odsłony', align: 'end', render: (post) => post.reads.toLocaleString('pl') },
    ],
    rows: posts,
  })
})()

Pisanie znaczników samodzielnie

Pomiń columns, a tabela wyrenderuje zamiast tego swoje dzieci, więc tabelę z wierszem stopki albo pogrupowanymi nagłówkami można zbudować ręcznie i wciąż dostać style oraz przewijany kontener.

Propsy

PropTypDomyślnieOpis
columnsTableColumn[]—{ key, header, align, render } na kolumnę. Pomiń, żeby pisać wiersze ręcznie.
rowsobject[][]Jeden obiekt na wiersz.
captionChild—Podpis nad tabelą.
stripedbooleanfalseBarwi co drugi wiersz.
hoverbooleanfalsePodświetla wiersz pod wskaźnikiem.
densebooleanfalseCiaśniejszy odstęp w komórkach.