DataTable
Tabla con API progresiva de 3 capas. Usa solo lo que necesitas: desde JSON puro hasta compound components con render functions completas.
pnpm dlx nuvo-ui add data-tableCapa 1 — JSON puro
El 90% de las tablas. Define columnas con key + label. Sin JSX adicional.
| Nombre | Rol | |
|---|---|---|
| Ana García | ana@empresa.com | Admin |
| Carlos López | carlos@empresa.com | Editor |
| María Torres | maria@empresa.com | Viewer |
| Luis Martínez | luis@empresa.com | Editor |
| Sara Ruiz | sara@empresa.com | Viewer |
| Pedro Sanz | pedro@empresa.com | Admin |
<DataTable
data={users}
columns={[
{ key: "name", label: "Nombre" },
{ key: "email", label: "Email" },
{ key: "role", label: "Rol" },
]}
/>Capa 2 — JSON + render()
Añade render functions solo donde necesitas personalizar una celda. Sorting y búsqueda incluidos.
| Nombre | Rol | Estado | ||
|---|---|---|---|---|
| Ana García | ana@empresa.com | Admin | Activo | |
| Carlos López | carlos@empresa.com | Editor | Inactivo | |
| María Torres | maria@empresa.com | Viewer | Activo | |
| Luis Martínez | luis@empresa.com | Editor | Activo | |
| Sara Ruiz | sara@empresa.com | Viewer | Activo | |
| Pedro Sanz | pedro@empresa.com | Admin | Inactivo |
<DataTable
data={users}
searchable
columns={[
{ key: "name", label: "Nombre", sortable: true },
{ key: "email", label: "Email" },
{
key: "status",
label: "Estado",
render: (value) => (
<Badge variant={value === "active" ? "success" : "muted"} dot size="sm">
{value === "active" ? "Activo" : "Inactivo"}
</Badge>
),
},
{
key: "id",
label: "",
render: (_, row) => (
<Button variant="ghost" size="sm" onClick={() => handleView(row)}>
Ver
</Button>
),
},
]}
/>Capa 3 — Compound components
Control total. DataTable.Column acepta una función render como children. Soporta paginación.
| Nombre | Rol | Estado |
|---|---|---|
Ana Garcíaana@empresa.com | Admin | Activo |
Carlos Lópezcarlos@empresa.com | Editor | Inactivo |
María Torresmaria@empresa.com | Viewer | Activo |
Página 1 de 2
<DataTable data={users} paginate pageSize={10}>
<DataTable.Column columnKey="name" label="Nombre" sortable>
{({ value, row }) => (
<div className="flex flex-col">
<span className="font-medium">{row.name}</span>
<span className="text-xs text-muted-foreground">{row.email}</span>
</div>
)}
</DataTable.Column>
<DataTable.Column columnKey="status" label="Estado">
{({ value }) => (
<Badge variant={value === "active" ? "success" : "muted"} dot size="sm">
{value}
</Badge>
)}
</DataTable.Column>
</DataTable>Nota: La paginación, el sorting y la búsqueda global son opcionales y se pueden combinar en cualquier capa.
Props
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
| data | T[] | — | Array de datos a mostrar |
| columns | ColumnDef<T>[] | — | Definición de columnas (Capas 1 y 2) |
| children | ReactNode | — | DataTable.Column para Capa 3 |
| searchable | boolean | false | Muestra input de búsqueda global |
| paginate | boolean | false | Activa paginación con controles |
| pageSize | number | 10 | Filas por página |
| loading | boolean | false | Muestra skeleton de carga |
| emptyText | string | "Sin datos." | Texto cuando no hay resultados |
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
| key | string | — | Campo del objeto de datos |
| label | string | — | Título de la columna |
| sortable | boolean | false | Permite ordenar al hacer click |
| render | (value, row, index) => ReactNode | — | Render function de la celda (Capa 2) |