DataTable
@vincisys/eyeson
NomeFunçãoStatus
Ana SouzaPilotoAtivo
Bruno LimaCopilotoAtivo
Carla DiasComissáriaInativo
Visualizar
import { DataTable } from "@vincisys/eyeson";

export function DataTableBasicDemo() {
	return (
		<div className="w-full max-w-2xl">
			<DataTable columns={columns} data={ALL_WORKERS.slice(0, 3)} />
		</div>
	);
}

Instalação

import { DataTable } from '@vincisys/eyeson';

Uso

Construído sobre o Table (compound component) e @tanstack/react-table. Você só define columns — busca, paginação server-side, loading e empty state são resolvidos internamente a partir de props de comportamento.

import { DataTable } from '@vincisys/eyeson';
import type { ColumnDef } from '@tanstack/react-table';

type Worker = { id: string; name: string; role: string };

const columns: ColumnDef<Worker>[] = [
{ accessorKey: 'name', header: 'Nome' },
{ accessorKey: 'role', header: 'Função' },
];

export function Example() {
return <DataTable columns={columns} data={workers} />;
}

Exemplos

Básico

columns + data.

NomeFunçãoStatus
Ana SouzaPilotoAtivo
Bruno LimaCopilotoAtivo
Carla DiasComissáriaInativo
Visualizar
import { DataTable } from "@vincisys/eyeson";

export function DataTableBasicDemo() {
	return (
		<div className="w-full max-w-2xl">
			<DataTable columns={columns} data={ALL_WORKERS.slice(0, 3)} />
		</div>
	);
}

Loading

Passe isLoading — a tabela renderiza um skeleton no lugar das linhas.

Carregando...
NomeFunçãoStatus
Visualizar
import { DataTable } from "@vincisys/eyeson";

export function DataTableLoadingDemo() {
	return (
		<div className="w-full max-w-2xl">
			<DataTable columns={columns} data={[]} isLoading />
		</div>
	);
}

Empty state

Quando data está vazio, o DataTable renderiza o componente Empty internamente. Personalize com emptyStateTitle/emptyStateDescription.

Nenhum tripulante encontrado

Ajuste os filtros e tente novamente.

Visualizar
import { DataTable } from "@vincisys/eyeson";

export function DataTableEmptyDemo() {
	return (
		<div className="w-full max-w-2xl">
			<DataTable
				columns={columns}
				data={[]}
				emptyStateTitle="Nenhum tripulante encontrado"
				emptyStateDescription="Ajuste os filtros e tente novamente."
			/>
		</div>
	);
}

Dividers

dividers controla as linhas divisórias entre linhas e/ou colunas ("none", "row" — padrão, "column" ou "both"), repassado direto para o Table interno.

dividers="row" (padrão)

NomeFunçãoStatus
Ana SouzaPilotoAtivo
Bruno LimaCopilotoAtivo
Carla DiasComissáriaInativo

dividers="column"

NomeFunçãoStatus
Ana SouzaPilotoAtivo
Bruno LimaCopilotoAtivo
Carla DiasComissáriaInativo

dividers="both"

NomeFunçãoStatus
Ana SouzaPilotoAtivo
Bruno LimaCopilotoAtivo
Carla DiasComissáriaInativo

dividers="none"

NomeFunçãoStatus
Ana SouzaPilotoAtivo
Bruno LimaCopilotoAtivo
Carla DiasComissáriaInativo
Visualizar
import { DataTable } from "@vincisys/eyeson";

export function DataTableDividersDemo() {
	return (
		<div className="flex w-full max-w-2xl flex-col gap-6">
			<div>
				<p className="mb-2 text-eds-neutral-elements text-sm">
					dividers="row" (padrão)
				</p>
				<DataTable
					columns={columns}
					data={ALL_WORKERS.slice(0, 3)}
					dividers="row"
				/>
			</div>
			<div>
				<p className="mb-2 text-eds-neutral-elements text-sm">
					dividers="column"
				</p>
				<DataTable
					columns={columns}
					data={ALL_WORKERS.slice(0, 3)}
					dividers="column"
				/>
			</div>
			<div>
				<p className="mb-2 text-eds-neutral-elements text-sm">
					dividers="both"
				</p>
				<DataTable
					columns={columns}
					data={ALL_WORKERS.slice(0, 3)}
					dividers="both"
				/>
			</div>
			<div>
				<p className="mb-2 text-eds-neutral-elements text-sm">
					dividers="none"
				</p>
				<DataTable
					columns={columns}
					data={ALL_WORKERS.slice(0, 3)}
					dividers="none"
				/>
			</div>
		</div>
	);
}

Ordenação (manual)

sorting + onSortingChange tornam os cabeçalhos das colunas clicáveis (ícone indica a direção atual). A ordenação é sempre manual/controlada pelo consumidor: o DataTable nunca reordena data sozinho — use o SortingState recebido para produzir os dados já ordenados, seja refazendo uma busca remota (server-side) ou ordenando localmente. Desabilite em uma coluna específica com enableSorting: false no columnDef.

Ana SouzaPilotoAtivo
Bruno LimaCopilotoAtivo
Carla DiasComissáriaInativo
Diego AlvesPilotoAtivo
Elena RochaComissáriaAtivo
Felipe CruzCopilotoInativo
Gabriela MeloPilotoAtivo
Henrique NunesComissárioAtivo
Isabela PradoCopilotoInativo
João VitorPilotoAtivo
Visualizar
import { DataTable } from "@vincisys/eyeson";
import { SortingState } from "@tanstack/react-table";
import { useMemo, useState } from "react";

export function DataTableSortingDemo() {
	const [sorting, setSorting] = useState<SortingState>([]);

	const sorted = useMemo(() => {
		const sort = sorting[0];
		if (!sort) return ALL_WORKERS;
		const copy = [...ALL_WORKERS];
		copy.sort((a, b) => {
			const key = sort.id as keyof Worker;
			const result = String(a[key]).localeCompare(String(b[key]));
			return sort.desc ? -result : result;
		});
		return copy;
	}, [sorting]);

	return (
		<div className="w-full max-w-2xl">
			<DataTable
				columns={columns}
				data={sorted}
				sorting={sorting}
				onSortingChange={setSorting}
			/>
		</div>
	);
}
const [sorting, setSorting] = useState<SortingState>([]);
const { data } = useListWorkers({ ordering: sorting[0] });

<DataTable
columns={columns}
data={data}
sorting={sorting}
onSortingChange={setSorting}
/>

Busca e paginação (server-side)

search renderiza um campo de busca acima da tabela (só aparece se você passar essa prop). pagination + onPageChange controlam a paginação — a paginação é sempre server-side: o DataTable não pagina data sozinho, ele só mostra os controles e avisa quando a página muda. Os controles de paginação só aparecem quando há mais de uma página.

Buscar
NomeFunçãoStatus
Ana SouzaPilotoAtivo
Bruno LimaCopilotoAtivo
1 / 5
Visualizar
import { DataTable } from "@vincisys/eyeson";
import { useMemo, useState } from "react";

export function DataTableSearchAndPaginationDemo() {
	const [search, setSearch] = useState('');
	const [page, setPage] = useState(1);
	const limit = 2;

	const filtered = useMemo(
		() =>
			ALL_WORKERS.filter((worker) =>
				worker.name.toLowerCase().includes(search.toLowerCase()),
			),
		[search],
	);

	const paged = useMemo(
		() => filtered.slice((page - 1) * limit, page * limit),
		[filtered, page],
	);

	return (
		<div className="w-full max-w-2xl">
			<DataTable
				columns={columns}
				data={paged}
				search={{
					value: search,
					onChange: (value) => {
						setSearch(value);
						setPage(1);
					},
					placeholder: 'Buscar tripulante...',
				}}
				pagination={{ page, limit, total: filtered.length }}
				onPageChange={setPage}
				emptyStateTitle="Nenhum tripulante encontrado"
			/>
		</div>
	);
}
const [search, setSearch] = useState('');
const [page, setPage] = useState(1);
const { data, total } = useListWorkers({ search, page });

<DataTable
columns={columns}
data={data}
search={{ value: search, onChange: setSearch, placeholder: 'Buscar...' }}
pagination={{ page, limit: 10, total }}
onPageChange={setPage}
emptyStateTitle="Nenhum resultado encontrado"
/>

Itens por página

pageSize renderiza um seletor à esquerda dos controles de paginação, permitindo o usuário escolher quantos itens ver por página. Requer pagination — o valor exibido no seletor é sempre pagination.limit (única fonte de verdade, evita o seletor e a paginação desincronizarem). Assim como pagination, o DataTable não corta data sozinho — cabe ao consumidor usar o novo valor para buscar/fatiar os dados. É comum resetar pagination.page para 1 dentro de onChange, para evitar cair numa página que deixou de existir.

NomeFunçãoStatus
Ana SouzaPilotoAtivo
Bruno LimaCopilotoAtivo
Carla DiasComissáriaInativo
Itens por página
1 / 4
Visualizar
import { DataTable } from "@vincisys/eyeson";
import { useMemo, useState } from "react";

export function DataTablePageSizeDemo() {
	const [page, setPage] = useState(1);
	const [limit, setLimit] = useState(3);

	const paged = useMemo(
		() => ALL_WORKERS.slice((page - 1) * limit, page * limit),
		[page, limit],
	);

	return (
		<div className="w-full max-w-2xl">
			<DataTable
				columns={columns}
				data={paged}
				pagination={{ page, limit, total: ALL_WORKERS.length }}
				onPageChange={setPage}
				pageSize={{
					options: [3, 5, 10],
					onChange: (value) => {
						setLimit(value);
						setPage(1);
					},
				}}
			/>
		</div>
	);
}