Moodinary/UI

Data table

Comparar muchos elementos con varias columnas. Ordenar, filtrar, paginar y seleccionar filas.

Primitiva disponible en la biblioteca, sin uso directo en la app actual. Tabla con búsqueda, filtro, orden, selección y paginación, armada sobre Table.

Instalación

shadcn
npx shadcn@latest add https://design.moodinary.com/r/data-table.json
import
import { DataTable, type DataTableColumn } from "@moodinary/ui/components/data-table";

Ejemplos

Completa

Ordená tocando el encabezado, filtrá por tipo y seleccioná para exportar.

Datos ilustrativos.

0 seleccionados
1.º ABien41
2.º BNeutral27
3.º ABien33
4.º ANeutral6
5.º BBien19
Código
teams.tsx
import {
	DataTable,
	type DataTableColumn,
} from "@moodinary/ui/components/data-table";
import { MoodWord } from "@moodinary/ui/components/mood-dot";

interface Team {
	id: string;
	kind: string;
	mood: number;
	name: string;
	pulses: number;
}
const rows: Team[] = [
	{ id: "1a", kind: "escuela", mood: 3.8, name: "1.º A", pulses: 41 },
	{ id: "2b", kind: "escuela", mood: 3.1, name: "2.º B", pulses: 27 },
	{ id: "3a", kind: "escuela", mood: 4.3, name: "3.º A", pulses: 33 },
	{ id: "4a", kind: "escuela", mood: 2.7, name: "4.º A", pulses: 6 },
	{ id: "5b", kind: "escuela", mood: 3.5, name: "5.º B", pulses: 19 },
	{
		id: "ventas",
		kind: "empresa",
		mood: 3.4,
		name: "Equipo Ventas",
		pulses: 22,
	},
	{
		id: "soporte",
		kind: "empresa",
		mood: 2.9,
		name: "Equipo Soporte",
		pulses: 15,
	},
	{
		id: "producto",
		kind: "empresa",
		mood: 4.0,
		name: "Equipo Producto",
		pulses: 12,
	},
];
const level = (v: number) =>
	Math.min(5, Math.max(1, Math.round(v))) as 1 | 2 | 3 | 4 | 5;
const columns: DataTableColumn<Team>[] = [
	{ header: "Equipo", id: "name", sortable: true, value: (r) => r.name },
	{
		cell: (r) => <MoodWord level={level(r.mood)} />,
		header: "Ánimo",
		id: "mood",
		sortable: true,
		value: (r) => r.mood,
	},
	{
		header: "Pulsos (7 días)",
		id: "pulses",
		sortable: true,
		value: (r) => r.pulses,
	},
];

export default function DataTableTeams() {
	return (
		<div className="w-full">
			<p className="mb-2 text-ink-3 text-xs">Datos ilustrativos.</p>
			<DataTable
				bulkAction={{ label: "Exportar CSV", onAction: () => undefined }}
				columns={columns}
				defaultSort={{ column: "name", direction: "ascending" }}
				filter={{
					label: "Tipo",
					options: [
						{ label: "Escuela", value: "escuela" },
						{ label: "Empresa", value: "empresa" },
					],
					value: (r) => r.kind,
				}}
				getRowId={(r) => r.id}
				getRowLabel={(r) => r.name}
				label="Equipos"
				rows={rows}
				searchPlaceholder="Filtrar equipos…"
				searchText={(r) => r.name}
			/>
		</div>
	);
}

Sin resultados

Cuando no hay filas muestra un estado vacío.

Equipo

Ningún resultado coincide

Probá con otro filtro.

Código
empty.tsx
import { DataTable } from "@moodinary/ui/components/data-table";

export default function DataTableEmpty() {
	return (
		<div className="w-full">
			<DataTable
				columns={[
					{
						header: "Equipo",
						id: "name",
						value: (r: { id: string; name: string }) => r.name,
					},
				]}
				getRowId={(r) => r.id}
				getRowLabel={(r) => r.name}
				label="Equipos sin resultados"
				rows={[]}
				searchText={(r) => r.name}
				selectable={false}
			/>
		</div>
	);
}

Props

DataTable

PropTipoDefaultDescripción
labelstring-Nombre de la tabla.
rowsRow[]-Filas.
columnsDataTableColumn<Row>[]-id, header, value, cell y sortable.
getRowId(row) => string-Clave estable.
getRowLabel(row) => string-Nombre para el checkbox.
searchText(row) => string-Texto donde busca el filtro.
searchPlaceholderstring"Filtrar…"Placeholder del buscador.
pageSizenumber5Filas por página.
defaultSort{ column, direction }-Orden inicial.
selectablebooleantrueMuestra checkboxes.
filter{ label, options, value }-Filtro por una columna.
bulkAction{ label, onAction }-Acción sobre las seleccionadas.
emptyTitlestring"Ningún resultado coincide"Título vacío.
classNamestring-Clases extra.

Cuándo sí y cuándo no

Hacé
  • Ordená por la columna más útil.
  • Mostrá cuántas filas hay seleccionadas.
  • Usá estados vacíos con una salida.
Evitá
  • No muestres datos de personas en un lugar anónimo.
  • No pongas más de 6 columnas.
  • No pagines tablas cortas.

Accesibilidad

  • Los encabezados ordenables son botones con aria-sort.
  • Cada checkbox nombra su fila.