DataTable
DataTable adiciona comportamento operacional a um conjunto de registros. Escolha-o quando as pessoas precisarem ordenar, selecionar ou agir sobre linhas; escolha Table quando os registros só precisarem de uma apresentação tabular simples e comparável.
Exemplos
Registros operacionais
Start with stable column keys and row id values. Put a named native action in its own cell;
hover remains an optional scanning affordance.
| Project | Owner | Status | Actions |
|---|---|---|---|
| Atlas | Maya Chen | Healthy | |
| Orbit | Jon Bell | At risk | |
| Nova | Priya Shah | Planning |
Choose a project action to view its details.
Ordenação e seleção de linhas
Marque como sortable apenas os campos com uma ordem útil e forneça labels.selectRow como
função quando cada checkbox precisar anunciar a pessoa ou o registro que seleciona.
| Maya Chen | Design | 4 | |
|---|---|---|---|
| Jon Bell | Engineering | 12 | |
| Priya Shah | Operations | 7 |
Linhas em carregamento
Passe um número para loading quando o resultado esperado tiver uma densidade conhecida. Isso
mantém a forma da tabela enquanto os registros carregam, em vez de trocar a região de dados por um
spinner.
| Project | Owner | Updated | |
|---|---|---|---|
Quando usar
Use DataTable para conjuntos operacionais de registros que as pessoas precisam ordenar, selecionar, percorrer em uma área fixa ou abrir a partir de uma linha.
Prefira outro componente quando:
- Os registros só precisam de campos alinhados para comparação — use Table, a tabela estática mais simples.
- Os registros são arquivos que alguém precisa navegar e manipular — use FileManager.
- Não há registros para mostrar após o carregamento — use EmptyState para uma ausência de página
inteira, ou o conteúdo
emptyde DataTable quando a tabela ainda for um contexto útil.
Acessibilidade
-
DataTable renderiza uma
<table>real, com cabeçalhos e células. Um cabeçalho ordenável é um botão, e o cabeçalho ativo informaaria-sortcomo crescente ou decrescente. -
Com
selectable, ela renderiza checkboxes nativos para cada linha e um checkbox de selecionar todos. O checkbox geral fica indeterminado quando apenas parte do conjunto está selecionada. -
labels.selectRowusa por padrão o nome repetido em inglês "Select row". Passe uma string ou uma função como(row) => 'Select ' + row.namepara dar a cada checkbox um nome acessível traduzido e distinguível. -
O
idda linha é usado como chave React e para seleção. Se uma linha não tiveridstring ou numérico, seu fallback vem da posição original de entrada, então a seleção continua nessa linha depois da ordenação. -
DataTable owns table layout, sorting, and selection. A command belongs to the React consumer in a cell: use a native button for an operation and a native link for navigation. Plain cells and rows are not commands.
-
Set
hovertotrueonly when a visual scanning affordance is useful. It is not implied by a consumer action. -
Dê a cada tabela um
captiondescritivo (usecaptionHiddenquando ele deve aparecer apenas para tecnologias assistivas).aria-labelearia-labelledbysão encaminhados à tabela. -
Marque a coluna de identificação com
rowHeader: true; as células do corpo serão<th scope="row">. Os cabeçalhos de coluna usamscope="col". -
A área de rolagem é uma região focável e nomeada. O nome vem do caption, ou pode ser definido com
scrollLabel. Durante o carregamento, a tabela expõearia-busyelabels.loadingfornece um anúncio oculto.
React cell actions
Move each former row command into an explicit action cell during manual migration. The old
onRowClick contract is removed under the project's pre-1.0 compatibility exception for unsafe
contracts; the earliest correction is 0.6.0 before stable release, or stable 1.0.0. Keep the
action's stable domain identity in the consumer, and keep selection and sorting callbacks separate.
Styles and the static Alpine contract are unchanged.
import { useState } from 'react';
import { Badge, Button, DataTable, type DataTableColumn } from '@lyra-ds/react';
const columns: DataTableColumn[] = [
{ key: 'project', label: 'Project', rowHeader: true },
{ key: 'owner', label: 'Owner' },
{ key: 'status', label: 'Status' },
{ key: 'actions', label: 'Actions' },
];
const projects = [
{
id: 'atlas',
project: 'Atlas',
owner: 'Maya Chen',
status: <Badge tone="success">Healthy</Badge>,
},
{
id: 'orbit',
project: 'Orbit',
owner: 'Jon Bell',
status: <Badge tone="warning">At risk</Badge>,
},
{
id: 'nova',
project: 'Nova',
owner: 'Priya Shah',
status: <Badge tone="neutral">Planning</Badge>,
},
];
export function ProjectTable() {
const [openedProject, setOpenedProject] = useState<string | null>(null);
const rows = projects.map((project) => ({
...project,
actions: (
<Button
type="button"
size="sm"
variant="secondary"
onClick={() => setOpenedProject(project.id)}
tabIndex={0}
>
Open {project.project}
</Button>
),
}));
const opened = projects.find((project) => project.id === openedProject);
return (
<div>
<DataTable caption="Projetos" columns={columns} rows={rows} hover />
<p aria-live="polite">
{opened
? `Showing details for ${opened.project}. Owner: ${opened.owner}.`
: 'Choose a project action to view its details.'}
</p>
</div>
);
}API e código
| Nome | Tipo | Obrigatória | Descrição |
|---|---|---|---|
columns | DataTableColumn[] | Obrigatória | Columns rendered in the supplied order. |
rows | RowShape[] | Obrigatória | Row records whose values may be any renderable React node. An `id` value is used for keys and selection. |
caption | ReactNode | — | Table caption. Supply a meaningful name for each data set. |
captionHidden | boolean | — | Visually hide the caption while keeping it available to assistive technology. |
scrollLabel | string | — | Accessible name for the focusable scroll region when it differs from the table name. |
sorting | DataTableSorting | null | — | Controlled sorting state. Pass `null` for unsorted rows. |
defaultSorting | DataTableSorting | null | — | Initial sorting state when uncontrolled. Default: `null`. |
onSortChange | (sorting: DataTableSorting | null) => void | — | Called after sorting changes. |
selectable | boolean | — | Whether to render row and select-all checkboxes. |
selected | Array<string | number> | — | Controlled selected row identifiers. |
defaultSelected | Array<string | number> | — | Initial selected row identifiers when uncontrolled. |
onSelectionChange | (selected: Array<string | number>) => void | — | Called after the selected row identifiers change. |
stickyHeader | boolean | — | Whether the header remains visible while the table scrolls. |
maxHeight | number | string | — | Maximum height for the scrollable table area. |
density | 'comfortable' | 'compact' | — | Row density. Default: `"comfortable"`. |
loading | boolean | number | — | Whether to render loading placeholders, or the number of placeholder rows. |
empty | ReactNode | — | Content shown instead of the default empty-state label. |
footer | ReactNode | — | Content rendered below the scrollable table area. |
hover | boolean | — | Whether rows highlight on hover. |
labels | DataTableLabels | — | Labels for controls and the default empty state. Merged over the English defaults. |
x-data="lyraDataTable({ … })"
| Opção | Tipo | Obrigatória | Descrição |
|---|---|---|---|
sorting | LyraDataTableSorting | null | — | Controlled sort state. Modelable with `x-modelable="sorting"`. Default: `null`. |
selected | string[] | — | Controlled selected served row ids. Modelable with `x-modelable="selected"`. Default: `[]`. |
clientSort | boolean | — | Reorder served rows in the browser after sorting. Default: `false`. |
scrollLabel | string | — | Accessible name for the focusable scroll region; defaults to the table caption or label. |
Com o binding Alpine, sirva um <caption> e <th scope="row"> para cada célula de identificação. Adicione x-bind="header" aos <th> de colunas ordenáveis, x-bind="rowHeader" aos <th> de linhas e x-bind="scrollRegion" a .lyra-table-scroll; use lyraDataTable({ scrollLabel: "…" }) para alterar o nome da região. Cabeçalhos de colunas não ordenáveis precisam de scope="col" no HTML servido.
Sem React, componha as classes da tabela — estado de ordenação e seleção, rótulos dos checkboxes e a transição de carregamento ficam com você:
<div class="lyra-table-wrap">
<div class="lyra-table-scroll" role="region" tabindex="0" aria-label="Projetos">
<table class="lyra-table lyra-table--hover">
<caption>
Projetos
</caption>
<thead>
<tr>
<th scope="col" class="lyra-table__check">
<input class="lyra-checkbox" type="checkbox" aria-label="Selecionar todos" />
</th>
<th scope="col" aria-sort="ascending">
<button class="lyra-table__sortbtn lyra-table__sortbtn--active" type="button">
Projeto
</button>
</th>
<th scope="col">Status</th>
</tr>
</thead>
<tbody>
<tr class="lyra-table__row--selected">
<td class="lyra-table__check">
<input class="lyra-checkbox" type="checkbox" aria-label="Selecionar Atlas" checked />
</td>
<th scope="row" class="lyra-table__primary">Atlas</th>
<td>Saudável</td>
</tr>
</tbody>
</table>
</div>
</div><lyra:data-table> Gerado do lyra-ds/blade v0.10.0.
O comportamento vem de lyraDataTable() — instale @lyra-ds/alpine e veja a aba HTML + Alpine.
| Prop | Padrão | Obrigatória | Valores de exemplo |
|---|---|---|---|
columns | — | Obrigatória | — |
rows | — | Obrigatória | — |
sorting | null | — | — |
selectable | false | — | — |
selected | [] | — | — |
clientSort | false | — | — |
stickyHeader | false | — | — |
maxHeight | null | — | — |
density | 'comfortable' | — | compact |
loading | false | — | — |
empty | null | — | — |
hover | false | — | — |
labels | [] | — | — |
<lyra:data-table
:columns="[
['key' => 'name', 'label' => 'Project', 'sortable' => true],
['key' => 'owner', 'label' => 'Owner'],
['key' => 'issues', 'label' => 'Open issues', 'align' => 'end'],
]"
:rows="[
['id' => '1', 'name' => 'Website redesign', 'owner' => 'Ana Ribeiro', 'issues' => 12],
['id' => '2', 'name' => 'Mobile app', 'owner' => 'João Martins', 'issues' => 4],
]"
density="comfortable"
hover
/>