DataTable
Full-featured data table with header, toolbar, sorting, pagination, row selection, and expandable rows. Responsive card view on mobile.
Basic DataTable
Preview
Users
Manage your team members
| Name | Role | Status | |
|---|---|---|---|
| John Doe | john@example.com | Admin | Active |
| Jane Smith | jane@example.com | Editor | Active |
| Bob Wilson | bob@example.com | Viewer | Pending |
Showing 1-3 of 3
<div class="datatable datatable-bordered">
<div class="datatable-header">
<div>
<h3 class="datatable-title">Users</h3>
<p class="datatable-subtitle">Manage your team members</p>
</div>
<div class="datatable-actions">
<button class="btn btn-sm color-primary">Add User</button>
</div>
</div>
<div class="datatable-body">
<table class="datatable-table">
<thead class="datatable-thead">
<tr>
<th class="datatable-th datatable-th-sortable">Name</th>
<th class="datatable-th datatable-th-sortable">Email</th>
<th class="datatable-th">Role</th>
<th class="datatable-th datatable-th-right">Status</th>
</tr>
</thead>
<tbody class="datatable-tbody">
<tr class="datatable-tr">
<td class="datatable-td">John Doe</td>
<td class="datatable-td">john@example.com</td>
<td class="datatable-td">Admin</td>
<td class="datatable-td datatable-td-right"><span class="badge color-success badge-sm">Active</span></td>
</tr>
<tr class="datatable-tr">
<td class="datatable-td">Jane Smith</td>
<td class="datatable-td">jane@example.com</td>
<td class="datatable-td">Editor</td>
<td class="datatable-td datatable-td-right"><span class="badge color-success badge-sm">Active</span></td>
</tr>
<tr class="datatable-tr">
<td class="datatable-td">Bob Wilson</td>
<td class="datatable-td">bob@example.com</td>
<td class="datatable-td">Viewer</td>
<td class="datatable-td datatable-td-right"><span class="badge color-warning badge-sm">Pending</span></td>
</tr>
</tbody>
</table>
</div>
<div class="datatable-footer">
<span class="datatable-info">Showing 1-3 of 3</span>
<nav class="pagination pagination-sm">
<button class="pagination-btn pagination-prev" disabled><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5" /></svg></button>
<button class="pagination-btn pagination-active">1</button>
<button class="pagination-btn pagination-next" disabled><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" /></svg></button>
</nav>
</div>
</div> Requires: ux.min.css
<div class="flex flex-col w-full rounded-2xl overflow-hidden border border-base-300 bg-base-100">
<!-- Header -->
<div class="flex items-center justify-between px-5 py-3 border-b border-base-300">
<div>
<h3 class="text-lg font-semibold m-0">Users</h3>
<p class="text-xs mt-0.5 opacity-60">Manage your team members</p>
</div>
<div class="flex items-center gap-2">
<button class="btn btn-sm color-primary">Add User</button>
</div>
</div>
<!-- Body -->
<div class="flex-1 overflow-auto">
<table class="w-full" style="border-collapse: collapse;">
<thead class="sticky top-0 z-10">
<tr>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide whitespace-nowrap opacity-60 bg-base-200 border-b-2 border-base-300 cursor-pointer select-none hover:text-primary hover:opacity-100">Name</th>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide whitespace-nowrap opacity-60 bg-base-200 border-b-2 border-base-300 cursor-pointer select-none hover:text-primary hover:opacity-100">Email</th>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide whitespace-nowrap opacity-60 bg-base-200 border-b-2 border-base-300">Role</th>
<th class="px-5 py-3 text-right text-xs font-semibold uppercase tracking-wide whitespace-nowrap opacity-60 bg-base-200 border-b-2 border-base-300">Status</th>
</tr>
</thead>
<tbody class="bg-base-100">
<tr class="transition-colors duration-150 hover:bg-primary/5">
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">John Doe</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">john@example.com</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">Admin</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-right"><span class="badge color-success badge-sm">Active</span></td>
</tr>
<tr class="transition-colors duration-150 hover:bg-primary/5">
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">Jane Smith</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">jane@example.com</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">Editor</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-right"><span class="badge color-success badge-sm">Active</span></td>
</tr>
<tr class="transition-colors duration-150 hover:bg-primary/5">
<td class="px-5 py-3 text-sm align-middle">Bob Wilson</td>
<td class="px-5 py-3 text-sm align-middle">bob@example.com</td>
<td class="px-5 py-3 text-sm align-middle">Viewer</td>
<td class="px-5 py-3 text-sm align-middle text-right"><span class="badge color-warning badge-sm">Pending</span></td>
</tr>
</tbody>
</table>
</div>
<!-- Footer -->
<div class="flex items-center justify-between px-5 py-3 border-t border-base-300">
<span class="text-sm opacity-60">Showing 1-3 of 3</span>
<nav class="pagination pagination-sm">
<button class="pagination-btn pagination-prev" disabled><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5" /></svg></button>
<button class="pagination-btn pagination-active">1</button>
<button class="pagination-btn pagination-next" disabled><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" /></svg></button>
</nav>
</div>
</div> Requires: tw.min.css
// Sorting
document.querySelectorAll('.datatable-th-sortable').forEach(th => {
th.addEventListener('click', () => {
// Toggle sorted class
th.classList.toggle('datatable-th-sorted');
// Your sort logic here
});
}); With Toolbar & Search
Preview
| Name ↑ | Actions | ||
|---|---|---|---|
| Alice Brown | alice@example.com |
|
|
| Charlie Davis | charlie@example.com |
|
1 selected
Rows per page:
<div class="datatable datatable-bordered">
<div class="datatable-toolbar">
<div class="datatable-toolbar-start">
<input class="input input-sm" placeholder="Search..." style="width: 200px" />
</div>
<div class="datatable-toolbar-end">
<button class="btn btn-sm btn-outline">Filter</button>
<button class="btn btn-sm btn-outline">Export</button>
</div>
</div>
<div class="datatable-body">
<table class="datatable-table">
<thead class="datatable-thead">
<tr>
<th class="datatable-th datatable-th-checkbox"><input type="checkbox" class="checkbox checkbox-sm" /></th>
<th class="datatable-th datatable-th-sortable datatable-th-sorted">Name <span class="datatable-sort-icon">↑</span></th>
<th class="datatable-th">Email</th>
<th class="datatable-th datatable-th-actions">Actions</th>
</tr>
</thead>
<tbody class="datatable-tbody">
<tr class="datatable-tr">
<td class="datatable-td datatable-td-checkbox"><input type="checkbox" class="checkbox checkbox-sm" /></td>
<td class="datatable-td">Alice Brown</td>
<td class="datatable-td">alice@example.com</td>
<td class="datatable-td datatable-td-actions">
<div class="datatable-row-actions">
<button class="datatable-row-action"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Z" /></svg></button>
<button class="datatable-row-action datatable-row-action-danger"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg></button>
</div>
</td>
</tr>
<tr class="datatable-tr datatable-tr-selected">
<td class="datatable-td datatable-td-checkbox"><input type="checkbox" class="checkbox checkbox-sm" checked /></td>
<td class="datatable-td">Charlie Davis</td>
<td class="datatable-td">charlie@example.com</td>
<td class="datatable-td datatable-td-actions">
<div class="datatable-row-actions">
<button class="datatable-row-action"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Z" /></svg></button>
<button class="datatable-row-action datatable-row-action-danger"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg></button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="datatable-footer">
<span class="datatable-info">1 selected</span>
<div class="datatable-per-page">
<span>Rows per page:</span>
<select><option>10</option><option>25</option><option>50</option></select>
</div>
</div>
</div> Requires: ux.min.css
<div class="flex flex-col w-full rounded-2xl overflow-hidden border border-base-300 bg-base-100">
<!-- Toolbar -->
<div class="flex items-center justify-between gap-3 px-5 py-2 bg-base-200 border-b border-base-300 flex-wrap">
<div class="flex items-center gap-2">
<input class="input input-sm" placeholder="Search..." style="width: 200px" />
</div>
<div class="flex items-center gap-2">
<button class="btn btn-sm btn-outline">Filter</button>
<button class="btn btn-sm btn-outline">Export</button>
</div>
</div>
<!-- Body -->
<div class="flex-1 overflow-auto">
<table class="w-full" style="border-collapse: collapse;">
<thead class="sticky top-0 z-10">
<tr>
<th class="w-12 pl-3 pr-2 py-3 text-left text-xs font-semibold uppercase tracking-wide bg-base-200 border-b-2 border-base-300"><input type="checkbox" class="checkbox checkbox-sm" /></th>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide bg-base-200 border-b-2 border-base-300 text-primary opacity-100 cursor-pointer select-none">Name <span class="inline-flex ml-1">↑</span></th>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">Email</th>
<th class="w-20 px-5 py-3 text-center text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">Actions</th>
</tr>
</thead>
<tbody class="bg-base-100">
<tr class="transition-colors duration-150 hover:bg-primary/5">
<td class="w-12 pl-3 pr-2 py-3 text-sm align-middle border-b border-base-300"><input type="checkbox" class="checkbox checkbox-sm" /></td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">Alice Brown</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">alice@example.com</td>
<td class="w-20 px-5 py-3 text-sm align-middle border-b border-base-300 text-center">
<div class="flex items-center justify-center gap-1">
<button class="flex items-center justify-center size-8 p-0 bg-transparent border-none rounded-lg cursor-pointer opacity-60 hover:opacity-100 hover:bg-base-200"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Z" /></svg></button>
<button class="flex items-center justify-center size-8 p-0 bg-transparent border-none rounded-lg cursor-pointer opacity-60 hover:opacity-100 hover:bg-error/10 hover:text-error"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg></button>
</div>
</td>
</tr>
<tr class="bg-primary/10 transition-colors duration-150">
<td class="w-12 pl-3 pr-2 py-3 text-sm align-middle border-b border-base-300"><input type="checkbox" class="checkbox checkbox-sm" checked /></td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">Charlie Davis</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">charlie@example.com</td>
<td class="w-20 px-5 py-3 text-sm align-middle border-b border-base-300 text-center">
<div class="flex items-center justify-center gap-1">
<button class="flex items-center justify-center size-8 p-0 bg-transparent border-none rounded-lg cursor-pointer opacity-60 hover:opacity-100 hover:bg-base-200"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Z" /></svg></button>
<button class="flex items-center justify-center size-8 p-0 bg-transparent border-none rounded-lg cursor-pointer opacity-60 hover:opacity-100 hover:bg-error/10 hover:text-error"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg></button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Footer -->
<div class="flex items-center justify-between px-5 py-3 border-t border-base-300">
<span class="text-sm opacity-60">1 selected</span>
<div class="flex items-center gap-2 text-sm opacity-60">
<span>Rows per page:</span>
<select class="px-2 py-1 text-sm rounded-lg border border-base-300 bg-base-100"><option>10</option><option>25</option><option>50</option></select>
</div>
</div>
</div> Requires: tw.min.css
// Row selection
document.querySelectorAll('.datatable-td-checkbox input').forEach(cb => {
cb.addEventListener('change', () => {
cb.closest('.datatable-tr')?.classList.toggle('datatable-tr-selected', cb.checked);
});
}); Empty & Loading States
No data found
Try adjusting your search or filters.
<!-- Empty State -->
<div class="datatable datatable-bordered">
<div class="datatable-empty">
<svg class="datatable-empty-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M20.25 7.5l-.625 10.632a2.25 2.25 0 01-2.247 2.118H6.622a2.25 2.25 0 01-2.247-2.118L3.75 7.5m6 4.125l2.25 2.25m0 0l2.25 2.25M12 13.875l2.25-2.25M12 13.875l-2.25 2.25M3.375 7.5h17.25c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125z" /></svg>
<h3 class="datatable-empty-title">No data found</h3>
<p class="datatable-empty-text">Try adjusting your search or filters.</p>
</div>
</div>
<!-- Loading State -->
<div class="datatable datatable-bordered is-loading" style="margin-top: 1rem;">
<div class="datatable-loading">
<span class="loading loading-spinner loading-md"></span>
</div>
</div> Requires: ux.min.css
<!-- Empty State -->
<div class="flex flex-col w-full rounded-2xl overflow-hidden border border-base-300 bg-base-100">
<div class="flex flex-col items-center justify-center py-16 px-4 text-center">
<svg class="size-16 mb-4 opacity-30" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M20.25 7.5l-.625 10.632a2.25 2.25 0 01-2.247 2.118H6.622a2.25 2.25 0 01-2.247-2.118L3.75 7.5m6 4.125l2.25 2.25m0 0l2.25 2.25M12 13.875l2.25-2.25M12 13.875l-2.25 2.25M3.375 7.5h17.25c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125z" /></svg>
<h3 class="text-lg font-semibold m-0 mb-1">No data found</h3>
<p class="text-sm m-0 opacity-60">Try adjusting your search or filters.</p>
</div>
</div>
<!-- Loading State -->
<div class="flex flex-col w-full rounded-2xl overflow-hidden border border-base-300 bg-base-100" style="margin-top: 1rem;">
<div class="flex items-center justify-center py-16">
<span class="loading loading-spinner loading-md"></span>
</div>
</div> Requires: tw.min.css
// Toggle loading state
datatable.classList.add('is-loading');
datatable.classList.remove('is-loading'); View Toggle: Table / Cards
Preview
Productos
12 productos encontrados
| Nombre | SKU | Precio | Estado | Acciones | |
|---|---|---|---|---|---|
| Monitor ERPlora 27" | MON-2701 | €349.00 | Activo |
|
|
| Teclado ERPlora Pro | KBD-0042 | €89.00 | Bajo stock |
|
Mostrando 1-2 de 12
<div class="datatable datatable-bordered">
<div class="datatable-header">
<div>
<h3 class="datatable-title">Productos</h3>
<p class="datatable-subtitle">12 productos encontrados</p>
</div>
<div class="datatable-actions">
<!-- View toggle: table or cards -->
<div class="datatable-view-toggle">
<button class="datatable-view-btn datatable-view-btn-active" title="Table view">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 12h16.5m-16.5 3.75h16.5M3.75 19.5h16.5M5.625 4.5h12.75a1.875 1.875 0 0 1 0 3.75H5.625a1.875 1.875 0 0 1 0-3.75Z" /></svg>
</button>
<button class="datatable-view-btn" title="Cards view">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6A2.25 2.25 0 0 1 6 3.75h2.25A2.25 2.25 0 0 1 10.5 6v2.25a2.25 2.25 0 0 1-2.25 2.25H6a2.25 2.25 0 0 1-2.25-2.25V6ZM3.75 15.75A2.25 2.25 0 0 1 6 13.5h2.25a2.25 2.25 0 0 1 2.25 2.25V18a2.25 2.25 0 0 1-2.25 2.25H6A2.25 2.25 0 0 1 3.75 18v-2.25ZM13.5 6a2.25 2.25 0 0 1 2.25-2.25H18A2.25 2.25 0 0 1 20.25 6v2.25A2.25 2.25 0 0 1 18 10.5h-2.25a2.25 2.25 0 0 1-2.25-2.25V6ZM13.5 15.75a2.25 2.25 0 0 1 2.25-2.25H18a2.25 2.25 0 0 1 2.25 2.25V18A2.25 2.25 0 0 1 18 20.25h-2.25a2.25 2.25 0 0 1-2.25-2.25v-2.25Z" /></svg>
</button>
</div>
<button class="btn btn-sm color-primary">Nuevo</button>
</div>
</div>
<div class="datatable-toolbar">
<div class="datatable-toolbar-start">
<input class="input input-sm" placeholder="Buscar..." style="width: 200px" />
</div>
<div class="datatable-toolbar-end">
<button class="datatable-export-btn">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" /></svg>
Export
</button>
</div>
</div>
<div class="datatable-body">
<table class="datatable-table">
<thead class="datatable-thead">
<tr>
<th class="datatable-th datatable-th-checkbox"><input type="checkbox" class="checkbox checkbox-sm" /></th>
<th class="datatable-th datatable-th-sortable datatable-th-sorted">Nombre</th>
<th class="datatable-th">SKU</th>
<th class="datatable-th datatable-th-right">Precio</th>
<th class="datatable-th datatable-th-center">Estado</th>
<th class="datatable-th datatable-th-actions">Acciones</th>
</tr>
</thead>
<tbody class="datatable-tbody">
<tr class="datatable-tr">
<td class="datatable-td datatable-td-checkbox"><input type="checkbox" class="checkbox checkbox-sm" /></td>
<td class="datatable-td">Monitor ERPlora 27"</td>
<td class="datatable-td">MON-2701</td>
<td class="datatable-td datatable-td-right">€349.00</td>
<td class="datatable-td datatable-td-center"><span class="badge color-success badge-sm">Activo</span></td>
<td class="datatable-td datatable-td-actions">
<div class="datatable-row-actions">
<button class="datatable-row-action"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Z" /></svg></button>
<button class="datatable-row-action datatable-row-action-danger"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg></button>
</div>
</td>
</tr>
<tr class="datatable-tr">
<td class="datatable-td datatable-td-checkbox"><input type="checkbox" class="checkbox checkbox-sm" /></td>
<td class="datatable-td">Teclado ERPlora Pro</td>
<td class="datatable-td">KBD-0042</td>
<td class="datatable-td datatable-td-right">€89.00</td>
<td class="datatable-td datatable-td-center"><span class="badge color-warning badge-sm">Bajo stock</span></td>
<td class="datatable-td datatable-td-actions">
<div class="datatable-row-actions">
<button class="datatable-row-action"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Z" /></svg></button>
<button class="datatable-row-action datatable-row-action-danger"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg></button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="datatable-footer">
<span class="datatable-info">Mostrando 1-2 de 12</span>
<nav class="pagination pagination-sm">
<button class="pagination-btn pagination-prev" disabled><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5" /></svg></button>
<button class="pagination-btn pagination-active">1</button>
<button class="pagination-btn">2</button>
<button class="pagination-btn">3</button>
<button class="pagination-btn pagination-next"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" /></svg></button>
</nav>
</div>
</div> Requires: ux.min.css
<div class="flex flex-col w-full rounded-2xl overflow-hidden border border-base-300 bg-base-100">
<!-- Header -->
<div class="flex items-center justify-between px-5 py-3 border-b border-base-300">
<div>
<h3 class="text-lg font-semibold m-0">Productos</h3>
<p class="text-xs mt-0.5 opacity-60">12 productos encontrados</p>
</div>
<div class="flex items-center gap-2">
<!-- View toggle -->
<div class="inline-flex items-center gap-0 p-0.5 bg-base-200 rounded border border-base-300">
<button class="inline-flex items-center justify-center size-8 border-none bg-base-100 text-primary rounded shadow-sm cursor-pointer" title="Table view"><svg class="size-4.5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 12h16.5m-16.5 3.75h16.5M3.75 19.5h16.5M5.625 4.5h12.75a1.875 1.875 0 0 1 0 3.75H5.625a1.875 1.875 0 0 1 0-3.75Z" /></svg></button>
<button class="inline-flex items-center justify-center size-8 border-none bg-transparent opacity-50 rounded cursor-pointer hover:opacity-100 hover:bg-base-100" title="Cards view"><svg class="size-4.5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6A2.25 2.25 0 0 1 6 3.75h2.25A2.25 2.25 0 0 1 10.5 6v2.25a2.25 2.25 0 0 1-2.25 2.25H6a2.25 2.25 0 0 1-2.25-2.25V6ZM3.75 15.75A2.25 2.25 0 0 1 6 13.5h2.25a2.25 2.25 0 0 1 2.25 2.25V18a2.25 2.25 0 0 1-2.25 2.25H6A2.25 2.25 0 0 1 3.75 18v-2.25ZM13.5 6a2.25 2.25 0 0 1 2.25-2.25H18A2.25 2.25 0 0 1 20.25 6v2.25A2.25 2.25 0 0 1 18 10.5h-2.25a2.25 2.25 0 0 1-2.25-2.25V6ZM13.5 15.75a2.25 2.25 0 0 1 2.25-2.25H18a2.25 2.25 0 0 1 2.25 2.25V18A2.25 2.25 0 0 1 18 20.25h-2.25a2.25 2.25 0 0 1-2.25-2.25v-2.25Z" /></svg></button>
</div>
<button class="btn btn-sm color-primary">Nuevo</button>
</div>
</div>
<!-- Toolbar -->
<div class="flex items-center justify-between gap-3 px-5 py-2 bg-base-200 border-b border-base-300 flex-wrap">
<div class="flex items-center gap-2">
<input class="input input-sm" placeholder="Buscar..." style="width: 200px" />
</div>
<div class="flex items-center gap-2">
<button class="inline-flex items-center gap-1 px-2 py-1 text-sm cursor-pointer bg-base-100 border border-base-300 rounded hover:bg-base-200 hover:border-primary">
<svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" /></svg>
Export
</button>
</div>
</div>
<!-- Body -->
<div class="flex-1 overflow-auto">
<table class="w-full" style="border-collapse: collapse;">
<thead class="sticky top-0 z-10">
<tr>
<th class="w-12 pl-3 pr-2 py-3 text-left text-xs font-semibold uppercase tracking-wide bg-base-200 border-b-2 border-base-300"><input type="checkbox" class="checkbox checkbox-sm" /></th>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide bg-base-200 border-b-2 border-base-300 text-primary opacity-100 cursor-pointer select-none">Nombre</th>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">SKU</th>
<th class="px-5 py-3 text-right text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">Precio</th>
<th class="px-5 py-3 text-center text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">Estado</th>
<th class="w-20 px-5 py-3 text-center text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">Acciones</th>
</tr>
</thead>
<tbody class="bg-base-100">
<tr class="transition-colors duration-150 hover:bg-primary/5">
<td class="w-12 pl-3 pr-2 py-3 text-sm align-middle border-b border-base-300"><input type="checkbox" class="checkbox checkbox-sm" /></td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">Monitor ERPlora 27"</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">MON-2701</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-right">€349.00</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-center"><span class="badge color-success badge-sm">Activo</span></td>
<td class="w-20 px-5 py-3 text-sm align-middle border-b border-base-300 text-center">
<div class="flex items-center justify-center gap-1">
<button class="flex items-center justify-center size-8 p-0 bg-transparent border-none rounded-lg cursor-pointer opacity-60 hover:opacity-100 hover:bg-base-200"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Z" /></svg></button>
<button class="flex items-center justify-center size-8 p-0 bg-transparent border-none rounded-lg cursor-pointer opacity-60 hover:opacity-100 hover:bg-error/10 hover:text-error"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg></button>
</div>
</td>
</tr>
<tr class="transition-colors duration-150 hover:bg-primary/5">
<td class="w-12 pl-3 pr-2 py-3 text-sm align-middle border-b border-base-300"><input type="checkbox" class="checkbox checkbox-sm" /></td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">Teclado ERPlora Pro</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">KBD-0042</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-right">€89.00</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-center"><span class="badge color-warning badge-sm">Bajo stock</span></td>
<td class="w-20 px-5 py-3 text-sm align-middle border-b border-base-300 text-center">
<div class="flex items-center justify-center gap-1">
<button class="flex items-center justify-center size-8 p-0 bg-transparent border-none rounded-lg cursor-pointer opacity-60 hover:opacity-100 hover:bg-base-200"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Z" /></svg></button>
<button class="flex items-center justify-center size-8 p-0 bg-transparent border-none rounded-lg cursor-pointer opacity-60 hover:opacity-100 hover:bg-error/10 hover:text-error"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg></button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Footer -->
<div class="flex items-center justify-between px-5 py-3 border-t border-base-300 flex-wrap gap-3">
<span class="text-sm opacity-60">Mostrando 1-2 de 12</span>
<nav class="pagination pagination-sm">
<button class="pagination-btn pagination-prev" disabled><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5" /></svg></button>
<button class="pagination-btn pagination-active">1</button>
<button class="pagination-btn">2</button>
<button class="pagination-btn">3</button>
<button class="pagination-btn pagination-next"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" /></svg></button>
</nav>
</div>
</div> Requires: tw.min.css
// Toggle between table and cards view
const toggle = document.querySelector('.datatable-view-toggle');
toggle.addEventListener('click', (e) => {
const btn = e.target.closest('.datatable-view-btn');
if (!btn) return;
toggle.querySelectorAll('.datatable-view-btn').forEach(b =>
b.classList.remove('datatable-view-btn-active'));
btn.classList.add('datatable-view-btn-active');
const table = btn.closest('.datatable');
// Toggle cards class
if (btn.title === 'Cards view') {
table.classList.add('datatable-cards');
} else {
table.classList.remove('datatable-cards');
}
}); Bulk Selection with Actions
Preview
3
elementos seleccionados
| Nombre | Rol | ||
|---|---|---|---|
| María García | maria@erplora.com | Admin | |
| Pedro López | pedro@erplora.com | Editor | |
| Ana Martín | ana@erplora.com | Viewer |
<div class="datatable datatable-bordered">
<!-- Bulk toolbar (appears when items selected) -->
<div class="datatable-bulk">
<div class="datatable-bulk-info">
<span class="datatable-bulk-count">3</span>
<span>elementos seleccionados</span>
</div>
<div class="datatable-bulk-actions">
<button class="datatable-bulk-btn">
<svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Z" /></svg>
Editar
</button>
<button class="datatable-bulk-btn datatable-bulk-btn-danger">
<svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg>
Eliminar
</button>
<button class="datatable-bulk-clear" title="Deseleccionar">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" /></svg>
</button>
</div>
</div>
<div class="datatable-body" style="max-height: 200px">
<table class="datatable-table">
<thead class="datatable-thead">
<tr>
<th class="datatable-th datatable-th-checkbox"><input type="checkbox" class="checkbox checkbox-sm" checked /></th>
<th class="datatable-th">Nombre</th>
<th class="datatable-th">Email</th>
<th class="datatable-th datatable-th-right">Rol</th>
</tr>
</thead>
<tbody class="datatable-tbody">
<tr class="datatable-tr datatable-tr-selected">
<td class="datatable-td datatable-td-checkbox"><input type="checkbox" class="checkbox checkbox-sm" checked /></td>
<td class="datatable-td">María García</td>
<td class="datatable-td">maria@erplora.com</td>
<td class="datatable-td datatable-td-right">Admin</td>
</tr>
<tr class="datatable-tr datatable-tr-selected">
<td class="datatable-td datatable-td-checkbox"><input type="checkbox" class="checkbox checkbox-sm" checked /></td>
<td class="datatable-td">Pedro López</td>
<td class="datatable-td">pedro@erplora.com</td>
<td class="datatable-td datatable-td-right">Editor</td>
</tr>
<tr class="datatable-tr datatable-tr-selected">
<td class="datatable-td datatable-td-checkbox"><input type="checkbox" class="checkbox checkbox-sm" checked /></td>
<td class="datatable-td">Ana Martín</td>
<td class="datatable-td">ana@erplora.com</td>
<td class="datatable-td datatable-td-right">Viewer</td>
</tr>
</tbody>
</table>
</div>
</div> Requires: ux.min.css
<div class="flex flex-col w-full rounded-2xl overflow-hidden border border-base-300 bg-base-100">
<!-- Bulk toolbar -->
<div class="flex items-center justify-between gap-3 px-5 py-2 bg-primary/10 border-b border-primary/20">
<div class="flex items-center gap-2 text-sm font-medium text-primary">
<span class="inline-flex items-center justify-center min-w-6 h-6 px-1 rounded-full text-xs font-semibold bg-primary text-primary-content">3</span>
<span>elementos seleccionados</span>
</div>
<div class="flex items-center gap-1">
<button class="inline-flex items-center gap-1 px-2 py-1 text-sm cursor-pointer bg-base-100 border border-base-300 rounded hover:bg-base-200 hover:border-primary">
<svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Z" /></svg>
Editar
</button>
<button class="inline-flex items-center gap-1 px-2 py-1 text-sm cursor-pointer bg-base-100 border border-base-300 rounded hover:bg-error/10 hover:border-error hover:text-error">
<svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" /></svg>
Eliminar
</button>
<button class="flex items-center justify-center size-7 p-0 bg-transparent border-none rounded-lg cursor-pointer opacity-50 hover:bg-base-100 hover:opacity-100" title="Deseleccionar">
<svg class="size-4.5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" /></svg>
</button>
</div>
</div>
<!-- Body -->
<div class="flex-1 overflow-auto" style="max-height: 200px">
<table class="w-full" style="border-collapse: collapse;">
<thead class="sticky top-0 z-10">
<tr>
<th class="w-12 pl-3 pr-2 py-3 text-left text-xs font-semibold uppercase tracking-wide bg-base-200 border-b-2 border-base-300"><input type="checkbox" class="checkbox checkbox-sm" checked /></th>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">Nombre</th>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">Email</th>
<th class="px-5 py-3 text-right text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">Rol</th>
</tr>
</thead>
<tbody class="bg-base-100">
<tr class="bg-primary/10">
<td class="w-12 pl-3 pr-2 py-3 text-sm align-middle border-b border-base-300"><input type="checkbox" class="checkbox checkbox-sm" checked /></td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">Maria Garcia</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">maria@erplora.com</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-right">Admin</td>
</tr>
<tr class="bg-primary/10">
<td class="w-12 pl-3 pr-2 py-3 text-sm align-middle border-b border-base-300"><input type="checkbox" class="checkbox checkbox-sm" checked /></td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">Pedro Lopez</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">pedro@erplora.com</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-right">Editor</td>
</tr>
<tr class="bg-primary/10">
<td class="w-12 pl-3 pr-2 py-3 text-sm align-middle"><input type="checkbox" class="checkbox checkbox-sm" checked /></td>
<td class="px-5 py-3 text-sm align-middle">Ana Martin</td>
<td class="px-5 py-3 text-sm align-middle">ana@erplora.com</td>
<td class="px-5 py-3 text-sm align-middle text-right">Viewer</td>
</tr>
</tbody>
</table>
</div>
</div> Requires: tw.min.css
// Show/hide bulk toolbar based on selection count
const selected = document.querySelectorAll('.datatable-tr-selected').length;
if (selected > 0) {
bulkBar.style.display = 'flex';
bulkCount.textContent = selected;
} else {
bulkBar.style.display = 'none';
} Cards View (Grid)
Preview
Empleados
| Nombre | Departamento | Estado | ||
|---|---|---|---|---|
| María García | Ventas | maria@erplora.com | Activo | |
| Pedro López | IT | pedro@erplora.com | Ausente | |
| Ana Martín | RRHH | ana@erplora.com | Activo |
Mostrando 1-3 de 3
<!-- Add datatable-cards to show grid of cards instead of table rows -->
<div class="datatable datatable-bordered datatable-cards">
<div class="datatable-header">
<div><h3 class="datatable-title">Empleados</h3></div>
<div class="datatable-actions">
<div class="datatable-view-toggle">
<button class="datatable-view-btn" title="Table"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 12h16.5m-16.5 3.75h16.5M3.75 19.5h16.5M5.625 4.5h12.75a1.875 1.875 0 0 1 0 3.75H5.625a1.875 1.875 0 0 1 0-3.75Z" /></svg></button>
<button class="datatable-view-btn datatable-view-btn-active" title="Cards"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6A2.25 2.25 0 0 1 6 3.75h2.25A2.25 2.25 0 0 1 10.5 6v2.25a2.25 2.25 0 0 1-2.25 2.25H6a2.25 2.25 0 0 1-2.25-2.25V6ZM3.75 15.75A2.25 2.25 0 0 1 6 13.5h2.25a2.25 2.25 0 0 1 2.25 2.25V18a2.25 2.25 0 0 1-2.25 2.25H6A2.25 2.25 0 0 1 3.75 18v-2.25ZM13.5 6a2.25 2.25 0 0 1 2.25-2.25H18A2.25 2.25 0 0 1 20.25 6v2.25A2.25 2.25 0 0 1 18 10.5h-2.25a2.25 2.25 0 0 1-2.25-2.25V6ZM13.5 15.75a2.25 2.25 0 0 1 2.25-2.25H18a2.25 2.25 0 0 1 2.25 2.25V18A2.25 2.25 0 0 1 18 20.25h-2.25a2.25 2.25 0 0 1-2.25-2.25v-2.25Z" /></svg></button>
</div>
</div>
</div>
<div class="datatable-body">
<table class="datatable-table">
<thead class="datatable-thead">
<tr>
<th class="datatable-th datatable-th-checkbox"><input type="checkbox" class="checkbox checkbox-sm" /></th>
<th class="datatable-th">Nombre</th>
<th class="datatable-th">Departamento</th>
<th class="datatable-th">Email</th>
<th class="datatable-th">Estado</th>
</tr>
</thead>
<tbody class="datatable-tbody">
<tr class="datatable-tr">
<td class="datatable-td datatable-td-checkbox"><input type="checkbox" class="checkbox checkbox-sm" /></td>
<td class="datatable-td" data-label="Nombre">María García</td>
<td class="datatable-td" data-label="Departamento">Ventas</td>
<td class="datatable-td" data-label="Email">maria@erplora.com</td>
<td class="datatable-td" data-label="Estado"><span class="badge color-success badge-sm">Activo</span></td>
</tr>
<tr class="datatable-tr datatable-tr-selected">
<td class="datatable-td datatable-td-checkbox"><input type="checkbox" class="checkbox checkbox-sm" checked /></td>
<td class="datatable-td" data-label="Nombre">Pedro López</td>
<td class="datatable-td" data-label="Departamento">IT</td>
<td class="datatable-td" data-label="Email">pedro@erplora.com</td>
<td class="datatable-td" data-label="Estado"><span class="badge color-warning badge-sm">Ausente</span></td>
</tr>
<tr class="datatable-tr">
<td class="datatable-td datatable-td-checkbox"><input type="checkbox" class="checkbox checkbox-sm" /></td>
<td class="datatable-td" data-label="Nombre">Ana Martín</td>
<td class="datatable-td" data-label="Departamento">RRHH</td>
<td class="datatable-td" data-label="Email">ana@erplora.com</td>
<td class="datatable-td" data-label="Estado"><span class="badge color-success badge-sm">Activo</span></td>
</tr>
</tbody>
</table>
</div>
<div class="datatable-footer">
<span class="datatable-info">Mostrando 1-3 de 3</span>
</div>
</div> Requires: ux.min.css
<div class="flex flex-col w-full rounded-2xl overflow-hidden border border-base-300 bg-base-100">
<!-- Header -->
<div class="flex items-center justify-between px-5 py-3 border-b border-base-300">
<div><h3 class="text-lg font-semibold m-0">Empleados</h3></div>
<div class="flex items-center gap-2">
<div class="inline-flex items-center gap-0 p-0.5 bg-base-200 rounded border border-base-300">
<button class="inline-flex items-center justify-center size-8 border-none bg-transparent opacity-50 rounded cursor-pointer hover:opacity-100 hover:bg-base-100" title="Table"><svg class="size-4.5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 12h16.5m-16.5 3.75h16.5M3.75 19.5h16.5M5.625 4.5h12.75a1.875 1.875 0 0 1 0 3.75H5.625a1.875 1.875 0 0 1 0-3.75Z" /></svg></button>
<button class="inline-flex items-center justify-center size-8 border-none bg-base-100 text-primary rounded shadow-sm cursor-pointer" title="Cards"><svg class="size-4.5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6A2.25 2.25 0 0 1 6 3.75h2.25A2.25 2.25 0 0 1 10.5 6v2.25a2.25 2.25 0 0 1-2.25 2.25H6a2.25 2.25 0 0 1-2.25-2.25V6ZM3.75 15.75A2.25 2.25 0 0 1 6 13.5h2.25a2.25 2.25 0 0 1 2.25 2.25V18a2.25 2.25 0 0 1-2.25 2.25H6A2.25 2.25 0 0 1 3.75 18v-2.25ZM13.5 6a2.25 2.25 0 0 1 2.25-2.25H18A2.25 2.25 0 0 1 20.25 6v2.25A2.25 2.25 0 0 1 18 10.5h-2.25a2.25 2.25 0 0 1-2.25-2.25V6ZM13.5 15.75a2.25 2.25 0 0 1 2.25-2.25H18a2.25 2.25 0 0 1 2.25 2.25V18A2.25 2.25 0 0 1 18 20.25h-2.25a2.25 2.25 0 0 1-2.25-2.25v-2.25Z" /></svg></button>
</div>
</div>
</div>
<!-- Body as cards grid -->
<div class="grid gap-3 p-3" style="grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));">
<!-- Card 1 -->
<div class="rounded-xl overflow-hidden border border-base-300 shadow-sm hover:shadow-md transition-shadow">
<div class="bg-base-200 px-3 py-3 font-semibold text-sm border-b border-base-300 flex items-center justify-between">Maria Garcia <input type="checkbox" class="checkbox checkbox-sm" /></div>
<div class="flex items-center justify-between px-3 py-2 text-sm border-b border-base-300"><span class="text-xs font-semibold uppercase tracking-wide opacity-50">Departamento</span><span>Ventas</span></div>
<div class="flex items-center justify-between px-3 py-2 text-sm border-b border-base-300"><span class="text-xs font-semibold uppercase tracking-wide opacity-50">Email</span><span>maria@erplora.com</span></div>
<div class="flex items-center justify-between px-3 py-2 text-sm"><span class="text-xs font-semibold uppercase tracking-wide opacity-50">Estado</span><span class="badge color-success badge-sm">Activo</span></div>
</div>
<!-- Card 2 (selected) -->
<div class="rounded-xl overflow-hidden border border-primary shadow-[0_0_0_1px_var(--color-primary)] hover:shadow-md transition-shadow">
<div class="bg-base-200 px-3 py-3 font-semibold text-sm border-b border-base-300 flex items-center justify-between">Pedro Lopez <input type="checkbox" class="checkbox checkbox-sm" checked /></div>
<div class="flex items-center justify-between px-3 py-2 text-sm border-b border-base-300"><span class="text-xs font-semibold uppercase tracking-wide opacity-50">Departamento</span><span>IT</span></div>
<div class="flex items-center justify-between px-3 py-2 text-sm border-b border-base-300"><span class="text-xs font-semibold uppercase tracking-wide opacity-50">Email</span><span>pedro@erplora.com</span></div>
<div class="flex items-center justify-between px-3 py-2 text-sm"><span class="text-xs font-semibold uppercase tracking-wide opacity-50">Estado</span><span class="badge color-warning badge-sm">Ausente</span></div>
</div>
<!-- Card 3 -->
<div class="rounded-xl overflow-hidden border border-base-300 shadow-sm hover:shadow-md transition-shadow">
<div class="bg-base-200 px-3 py-3 font-semibold text-sm border-b border-base-300 flex items-center justify-between">Ana Martin <input type="checkbox" class="checkbox checkbox-sm" /></div>
<div class="flex items-center justify-between px-3 py-2 text-sm border-b border-base-300"><span class="text-xs font-semibold uppercase tracking-wide opacity-50">Departamento</span><span>RRHH</span></div>
<div class="flex items-center justify-between px-3 py-2 text-sm border-b border-base-300"><span class="text-xs font-semibold uppercase tracking-wide opacity-50">Email</span><span>ana@erplora.com</span></div>
<div class="flex items-center justify-between px-3 py-2 text-sm"><span class="text-xs font-semibold uppercase tracking-wide opacity-50">Estado</span><span class="badge color-success badge-sm">Activo</span></div>
</div>
</div>
<!-- Footer -->
<div class="flex items-center justify-between px-5 py-3 border-t border-base-300">
<span class="text-sm opacity-60">Mostrando 1-3 de 3</span>
</div>
</div> Requires: tw.min.css
// Toggle cards view
datatable.classList.toggle('datatable-cards'); Detail Panel (Side Panel)
Preview
Pedidos
| # | Cliente | Total |
|---|---|---|
| ORD-001 | ERPlora S.L. | €1,250.00 |
| ORD-002 | Tech Solutions | €890.50 |
| ORD-003 | Digital Corp | €2,100.00 |
ORD-001
Cliente
ERPlora S.L.
Fecha
2025-01-15
Total
€1,250.00
Estado
Completado
<!-- Wrap datatable in datatable-with-panel for side detail view -->
<div class="datatable-with-panel" style="border: 1px solid var(--color-base-300); border-radius: 1rem; overflow: hidden;">
<div class="datatable">
<div class="datatable-header">
<div><h3 class="datatable-title">Pedidos</h3></div>
</div>
<div class="datatable-body" style="max-height: 240px">
<table class="datatable-table">
<thead class="datatable-thead">
<tr>
<th class="datatable-th">#</th>
<th class="datatable-th">Cliente</th>
<th class="datatable-th datatable-th-right">Total</th>
</tr>
</thead>
<tbody class="datatable-tbody">
<tr class="datatable-tr datatable-tr-selected datatable-tr-clickable">
<td class="datatable-td">ORD-001</td>
<td class="datatable-td">ERPlora S.L.</td>
<td class="datatable-td datatable-td-right">€1,250.00</td>
</tr>
<tr class="datatable-tr datatable-tr-clickable">
<td class="datatable-td">ORD-002</td>
<td class="datatable-td">Tech Solutions</td>
<td class="datatable-td datatable-td-right">€890.50</td>
</tr>
<tr class="datatable-tr datatable-tr-clickable">
<td class="datatable-td">ORD-003</td>
<td class="datatable-td">Digital Corp</td>
<td class="datatable-td datatable-td-right">€2,100.00</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Detail panel on the right -->
<div class="datatable-panel">
<div class="datatable-panel-header">
<span class="datatable-panel-title">ORD-001</span>
<button class="datatable-panel-close">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" /></svg>
</button>
</div>
<div class="datatable-panel-body">
<div class="datatable-detail-list">
<div class="datatable-detail-item">
<span class="datatable-detail-label">Cliente</span>
<span class="datatable-detail-value">ERPlora S.L.</span>
</div>
<div class="datatable-detail-item">
<span class="datatable-detail-label">Fecha</span>
<span class="datatable-detail-value">2025-01-15</span>
</div>
<div class="datatable-detail-item">
<span class="datatable-detail-label">Total</span>
<span class="datatable-detail-value" style="color: var(--color-success); font-weight: 600;">€1,250.00</span>
</div>
<div class="datatable-detail-item">
<span class="datatable-detail-label">Estado</span>
<span class="datatable-detail-value"><span class="badge color-success badge-sm">Completado</span></span>
</div>
</div>
</div>
<div class="datatable-panel-footer">
<button class="btn btn-sm btn-outline">Editar</button>
<button class="btn btn-sm color-primary">Ver detalle</button>
</div>
</div>
</div> Requires: ux.min.css
<div class="flex" style="border: 1px solid var(--color-base-300); border-radius: 1rem; overflow: hidden;">
<!-- Table side -->
<div class="flex flex-col flex-1 min-w-0 bg-base-100">
<!-- Header -->
<div class="flex items-center justify-between px-5 py-3 border-b border-base-300">
<div><h3 class="text-lg font-semibold m-0">Pedidos</h3></div>
</div>
<!-- Body -->
<div class="flex-1 overflow-auto" style="max-height: 240px">
<table class="w-full" style="border-collapse: collapse;">
<thead class="sticky top-0 z-10">
<tr>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">#</th>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">Cliente</th>
<th class="px-5 py-3 text-right text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">Total</th>
</tr>
</thead>
<tbody class="bg-base-100">
<tr class="bg-primary/10 cursor-pointer">
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">ORD-001</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">ERPlora S.L.</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-right">€1,250.00</td>
</tr>
<tr class="cursor-pointer transition-colors duration-150 hover:bg-primary/5">
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">ORD-002</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">Tech Solutions</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-right">€890.50</td>
</tr>
<tr class="cursor-pointer transition-colors duration-150 hover:bg-primary/5">
<td class="px-5 py-3 text-sm align-middle">ORD-003</td>
<td class="px-5 py-3 text-sm align-middle">Digital Corp</td>
<td class="px-5 py-3 text-sm align-middle text-right">€2,100.00</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Detail panel -->
<div class="flex flex-col shrink-0 w-90 bg-base-100 border-l border-base-300">
<div class="flex items-center justify-between px-4 py-3 border-b border-base-300">
<span class="text-base font-semibold">ORD-001</span>
<button class="flex items-center justify-center size-8 p-0 bg-transparent border-none rounded-lg cursor-pointer opacity-50 hover:bg-base-200 hover:opacity-100">
<svg class="size-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" /></svg>
</button>
</div>
<div class="flex-1 overflow-auto p-4">
<div class="grid gap-3" style="grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));">
<div class="flex flex-col gap-0.5">
<span class="text-xs font-semibold uppercase tracking-wide opacity-60">Cliente</span>
<span class="text-sm">ERPlora S.L.</span>
</div>
<div class="flex flex-col gap-0.5">
<span class="text-xs font-semibold uppercase tracking-wide opacity-60">Fecha</span>
<span class="text-sm">2025-01-15</span>
</div>
<div class="flex flex-col gap-0.5">
<span class="text-xs font-semibold uppercase tracking-wide opacity-60">Total</span>
<span class="text-sm font-semibold text-success">€1,250.00</span>
</div>
<div class="flex flex-col gap-0.5">
<span class="text-xs font-semibold uppercase tracking-wide opacity-60">Estado</span>
<span class="text-sm"><span class="badge color-success badge-sm">Completado</span></span>
</div>
</div>
</div>
<div class="flex gap-2 px-4 py-3 border-t border-base-300">
<button class="btn btn-sm btn-outline">Editar</button>
<button class="btn btn-sm color-primary">Ver detalle</button>
</div>
</div>
</div> Requires: tw.min.css
// Open detail panel when clicking a row
rows.forEach(row => {
row.addEventListener('click', () => {
// Highlight selected row
rows.forEach(r => r.classList.remove('datatable-tr-selected'));
row.classList.add('datatable-tr-selected');
// Show panel
panel.classList.remove('datatable-panel-collapsed');
// Update panel content...
});
});
// Close panel
closeBtn.addEventListener('click', () => {
panel.classList.add('datatable-panel-collapsed');
}); Responsive (Card View)
| Nombre | Estado | |
|---|---|---|
| María García | maria@erplora.com | Activo |
| Pedro López | pedro@erplora.com | Pendiente |
<!-- Add datatable-responsive for mobile card view -->
<div class="datatable datatable-bordered datatable-responsive">
<div class="datatable-body">
<table class="datatable-table">
<thead class="datatable-thead">
<tr>
<th class="datatable-th">Nombre</th>
<th class="datatable-th">Email</th>
<th class="datatable-th">Estado</th>
</tr>
</thead>
<tbody class="datatable-tbody">
<tr class="datatable-tr">
<td class="datatable-td" data-label="Nombre">María García</td>
<td class="datatable-td" data-label="Email">maria@erplora.com</td>
<td class="datatable-td" data-label="Estado">Activo</td>
</tr>
<tr class="datatable-tr">
<td class="datatable-td" data-label="Nombre">Pedro López</td>
<td class="datatable-td" data-label="Email">pedro@erplora.com</td>
<td class="datatable-td" data-label="Estado">Pendiente</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- On mobile (< 768px): each row becomes a card with data-label as field names --> Requires: ux.min.css
<!-- On mobile (< 768px) each row becomes a card with data-label as field names.
This example shows the mobile card layout rendered at all sizes for demo purposes. -->
<div class="flex flex-col w-full rounded-2xl overflow-hidden border border-base-300 bg-base-100">
<div class="flex flex-col gap-3 p-3">
<!-- Card row 1 -->
<div class="rounded-xl overflow-hidden border border-base-300">
<div class="flex items-center justify-between px-4 py-3 border-b border-base-300">
<span class="shrink-0 font-semibold text-xs uppercase tracking-wide opacity-60 pr-3">Nombre</span>
<span class="text-sm text-right">Maria Garcia</span>
</div>
<div class="flex items-center justify-between px-4 py-3 border-b border-base-300">
<span class="shrink-0 font-semibold text-xs uppercase tracking-wide opacity-60 pr-3">Email</span>
<span class="text-sm text-right">maria@erplora.com</span>
</div>
<div class="flex items-center justify-between px-4 py-3">
<span class="shrink-0 font-semibold text-xs uppercase tracking-wide opacity-60 pr-3">Estado</span>
<span class="text-sm text-right">Activo</span>
</div>
</div>
<!-- Card row 2 -->
<div class="rounded-xl overflow-hidden border border-base-300">
<div class="flex items-center justify-between px-4 py-3 border-b border-base-300">
<span class="shrink-0 font-semibold text-xs uppercase tracking-wide opacity-60 pr-3">Nombre</span>
<span class="text-sm text-right">Pedro Lopez</span>
</div>
<div class="flex items-center justify-between px-4 py-3 border-b border-base-300">
<span class="shrink-0 font-semibold text-xs uppercase tracking-wide opacity-60 pr-3">Email</span>
<span class="text-sm text-right">pedro@erplora.com</span>
</div>
<div class="flex items-center justify-between px-4 py-3">
<span class="shrink-0 font-semibold text-xs uppercase tracking-wide opacity-60 pr-3">Estado</span>
<span class="text-sm text-right">Pendiente</span>
</div>
</div>
</div>
</div> Requires: tw.min.css
// No JavaScript required for responsive view — pure CSS Sales History (Full Example)
Preview
Historial de Ventas
Registro completo de transacciones
| Nro Venta ↓ | Fecha ⇅ | Cliente | Empleado | Método de Pago | Total ⇅ | Estado | Acciones |
|---|---|---|---|---|---|---|---|
| V-0048 | 09/02/2026 14:32 | María García |
Juan Pérez
|
Efectivo
|
$1,250.00 | Completada |
|
| V-0047 | 09/02/2026 11:15 | Pedro López |
Ana Martín
|
Tarjeta
|
$890.50 | Completada |
|
| V-0046 | 08/02/2026 17:45 | Sin cliente |
Juan Pérez
|
Transferencia
|
$320.00 | Pendiente |
|
| V-0045 | 08/02/2026 09:20 | Tech Solutions S.A. |
Ana Martín
|
Tarjeta
|
$2,100.00 | Cancelada |
|
Mostrar:
Mostrando 1-4 de 48
<div class="datatable datatable-bordered datatable-responsive">
<div class="datatable-header">
<div>
<h3 class="datatable-title">Historial de Ventas</h3>
<p class="datatable-subtitle">Registro completo de transacciones</p>
</div>
<div class="datatable-actions">
<button class="btn btn-sm color-success">
<svg class="size-4 mr-1" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 3h1.386c.51 0 .955.343 1.087.835l.383 1.437M7.5 14.25a3 3 0 0 0-3 3h15.75m-12.75-3h11.218c1.121-2.3 2.1-4.684 2.924-7.138a60.114 60.114 0 0 0-16.536-1.84M7.5 14.25 5.106 5.272M6 20.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Zm12.75 0a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z" /></svg>
Nueva Venta
</button>
</div>
</div>
<div class="datatable-toolbar">
<div class="datatable-toolbar-start">
<input class="input input-sm datatable-search" placeholder="Buscar por nro venta o cliente..." />
<input type="date" class="input input-sm" style="width: 150px" />
<input type="date" class="input input-sm" style="width: 150px" />
</div>
<div class="datatable-toolbar-end">
<select class="select select-sm" style="width: 160px">
<option>Todos los estados</option>
<option>Completada</option>
<option>Pendiente</option>
<option>Cancelada</option>
</select>
<button class="datatable-export-btn">
<svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" /></svg>
Exportar
</button>
</div>
</div>
<div class="datatable-body">
<table class="datatable-table">
<thead class="datatable-thead">
<tr>
<th class="datatable-th datatable-th-sortable datatable-th-sorted">Nro Venta <span class="datatable-sort-icon">↓</span></th>
<th class="datatable-th datatable-th-sortable">Fecha <span class="datatable-sort-icon">⇅</span></th>
<th class="datatable-th">Cliente</th>
<th class="datatable-th">Empleado</th>
<th class="datatable-th">Método de Pago</th>
<th class="datatable-th datatable-th-right datatable-th-sortable">Total <span class="datatable-sort-icon">⇅</span></th>
<th class="datatable-th datatable-th-center">Estado</th>
<th class="datatable-th datatable-th-actions">Acciones</th>
</tr>
</thead>
<tbody class="datatable-tbody">
<tr class="datatable-tr datatable-tr-clickable">
<td class="datatable-td font-mono font-semibold" data-label="Nro Venta"><a class="text-primary hover:underline" href="#">V-0048</a></td>
<td class="datatable-td opacity-70" data-label="Fecha">09/02/2026 14:32</td>
<td class="datatable-td" data-label="Cliente">María García</td>
<td class="datatable-td" data-label="Empleado">
<div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" /></svg> Juan Pérez</div>
</td>
<td class="datatable-td" data-label="Método">
<div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 18.75a60.07 60.07 0 0 1 15.797 2.101c.727.198 1.453-.342 1.453-1.096V18.75M3.75 4.5v.75A.75.75 0 0 1 3 6h-.75m0 0v-.375c0-.621.504-1.125 1.125-1.125H20.25M2.25 6v9m18-10.5v.75c0 .414.336.75.75.75h.75m-1.5-1.5h.375c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-.375m1.5-1.5H21a.75.75 0 0 0-.75.75v.75m0 0H3.75m0 0h-.375a1.125 1.125 0 0 1-1.125-1.125V15m1.5 1.5v-.75A.75.75 0 0 0 3 15h-.75M15 10.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm3 0h.008v.008H18V10.5Zm-12 0h.008v.008H6V10.5Z" /></svg> Efectivo</div>
</td>
<td class="datatable-td datatable-td-right font-semibold text-success" data-label="Total">$1,250.00</td>
<td class="datatable-td datatable-td-center" data-label="Estado"><span class="badge color-success badge-sm">Completada</span></td>
<td class="datatable-td datatable-td-actions">
<div class="datatable-row-actions">
<button class="datatable-row-action" title="Ver detalle"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" /></svg></button>
</div>
</td>
</tr>
<tr class="datatable-tr datatable-tr-clickable">
<td class="datatable-td font-mono font-semibold" data-label="Nro Venta"><a class="text-primary hover:underline" href="#">V-0047</a></td>
<td class="datatable-td opacity-70" data-label="Fecha">09/02/2026 11:15</td>
<td class="datatable-td" data-label="Cliente">Pedro López</td>
<td class="datatable-td" data-label="Empleado">
<div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" /></svg> Ana Martín</div>
</td>
<td class="datatable-td" data-label="Método">
<div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 8.25h19.5M2.25 9h19.5m-16.5 5.25h6m-6 2.25h3m-3.75 3h15a2.25 2.25 0 0 0 2.25-2.25V6.75A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25v10.5A2.25 2.25 0 0 0 4.5 19.5Z" /></svg> Tarjeta</div>
</td>
<td class="datatable-td datatable-td-right font-semibold text-success" data-label="Total">$890.50</td>
<td class="datatable-td datatable-td-center" data-label="Estado"><span class="badge color-success badge-sm">Completada</span></td>
<td class="datatable-td datatable-td-actions">
<div class="datatable-row-actions">
<button class="datatable-row-action" title="Ver detalle"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" /></svg></button>
</div>
</td>
</tr>
<tr class="datatable-tr datatable-tr-clickable">
<td class="datatable-td font-mono font-semibold" data-label="Nro Venta"><a class="text-primary hover:underline" href="#">V-0046</a></td>
<td class="datatable-td opacity-70" data-label="Fecha">08/02/2026 17:45</td>
<td class="datatable-td opacity-50" data-label="Cliente">Sin cliente</td>
<td class="datatable-td" data-label="Empleado">
<div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" /></svg> Juan Pérez</div>
</td>
<td class="datatable-td" data-label="Método">
<div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M7.5 21 3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5" /></svg> Transferencia</div>
</td>
<td class="datatable-td datatable-td-right font-semibold text-success" data-label="Total">$320.00</td>
<td class="datatable-td datatable-td-center" data-label="Estado"><span class="badge color-warning badge-sm">Pendiente</span></td>
<td class="datatable-td datatable-td-actions">
<div class="datatable-row-actions">
<button class="datatable-row-action" title="Ver detalle"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" /></svg></button>
</div>
</td>
</tr>
<tr class="datatable-tr datatable-tr-clickable">
<td class="datatable-td font-mono font-semibold" data-label="Nro Venta"><a class="text-primary hover:underline" href="#">V-0045</a></td>
<td class="datatable-td opacity-70" data-label="Fecha">08/02/2026 09:20</td>
<td class="datatable-td" data-label="Cliente">Tech Solutions S.A.</td>
<td class="datatable-td" data-label="Empleado">
<div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" /></svg> Ana Martín</div>
</td>
<td class="datatable-td" data-label="Método">
<div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 8.25h19.5M2.25 9h19.5m-16.5 5.25h6m-6 2.25h3m-3.75 3h15a2.25 2.25 0 0 0 2.25-2.25V6.75A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25v10.5A2.25 2.25 0 0 0 4.5 19.5Z" /></svg> Tarjeta</div>
</td>
<td class="datatable-td datatable-td-right font-semibold text-success" data-label="Total">$2,100.00</td>
<td class="datatable-td datatable-td-center" data-label="Estado"><span class="badge color-error badge-sm">Cancelada</span></td>
<td class="datatable-td datatable-td-actions">
<div class="datatable-row-actions">
<button class="datatable-row-action" title="Ver detalle"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" /></svg></button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="datatable-footer">
<div class="datatable-per-page">
<span>Mostrar:</span>
<select><option>10</option><option selected>25</option><option>50</option></select>
</div>
<span class="datatable-info">Mostrando 1-4 de 48</span>
<nav class="pagination pagination-sm">
<button class="pagination-btn pagination-prev" disabled><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5" /></svg></button>
<button class="pagination-btn pagination-active">1</button>
<button class="pagination-btn">2</button>
<button class="pagination-btn pagination-next"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" /></svg></button>
</nav>
</div>
</div> Requires: ux.min.css
<div class="flex flex-col w-full rounded-2xl overflow-hidden border border-base-300 bg-base-100">
<!-- Header -->
<div class="flex items-center justify-between px-5 py-3 border-b border-base-300">
<div>
<h3 class="text-lg font-semibold m-0">Historial de Ventas</h3>
<p class="text-xs mt-0.5 opacity-60">Registro completo de transacciones</p>
</div>
<div class="flex items-center gap-2">
<button class="btn btn-sm color-success">
<svg class="size-4 mr-1" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 3h1.386c.51 0 .955.343 1.087.835l.383 1.437M7.5 14.25a3 3 0 0 0-3 3h15.75m-12.75-3h11.218c1.121-2.3 2.1-4.684 2.924-7.138a60.114 60.114 0 0 0-16.536-1.84M7.5 14.25 5.106 5.272M6 20.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Zm12.75 0a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z" /></svg>
Nueva Venta
</button>
</div>
</div>
<!-- Toolbar -->
<div class="flex items-center justify-between gap-3 px-5 py-2 bg-base-200 border-b border-base-300 flex-wrap">
<div class="flex items-center gap-2 flex-wrap">
<input class="input input-sm min-w-48" placeholder="Buscar por nro venta o cliente..." />
<input type="date" class="input input-sm" style="width: 150px" />
<input type="date" class="input input-sm" style="width: 150px" />
</div>
<div class="flex items-center gap-2">
<select class="select select-sm" style="width: 160px">
<option>Todos los estados</option>
<option>Completada</option>
<option>Pendiente</option>
<option>Cancelada</option>
</select>
<button class="inline-flex items-center gap-1 px-2 py-1 text-sm cursor-pointer bg-base-100 border border-base-300 rounded hover:bg-base-200 hover:border-primary">
<svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" /></svg>
Exportar
</button>
</div>
</div>
<!-- Body -->
<div class="flex-1 overflow-auto">
<table class="w-full" style="border-collapse: collapse;">
<thead class="sticky top-0 z-10">
<tr>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide bg-base-200 border-b-2 border-base-300 text-primary opacity-100 cursor-pointer select-none">Nro Venta <span class="inline-flex ml-1">↓</span></th>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300 cursor-pointer select-none">Fecha <span class="inline-flex ml-1 opacity-50">⇅</span></th>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">Cliente</th>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">Empleado</th>
<th class="px-5 py-3 text-left text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">Método de Pago</th>
<th class="px-5 py-3 text-right text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300 cursor-pointer select-none">Total <span class="inline-flex ml-1 opacity-50">⇅</span></th>
<th class="px-5 py-3 text-center text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">Estado</th>
<th class="w-20 px-5 py-3 text-center text-xs font-semibold uppercase tracking-wide opacity-60 bg-base-200 border-b-2 border-base-300">Acciones</th>
</tr>
</thead>
<tbody class="bg-base-100">
<tr class="transition-colors duration-150 hover:bg-primary/5 cursor-pointer">
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 font-mono font-semibold"><a class="text-primary hover:underline" href="#">V-0048</a></td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 opacity-70">09/02/2026 14:32</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">María García</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300"><div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" /></svg> Juan Pérez</div></td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300"><div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 18.75a60.07 60.07 0 0 1 15.797 2.101c.727.198 1.453-.342 1.453-1.096V18.75M3.75 4.5v.75A.75.75 0 0 1 3 6h-.75m0 0v-.375c0-.621.504-1.125 1.125-1.125H20.25M2.25 6v9m18-10.5v.75c0 .414.336.75.75.75h.75m-1.5-1.5h.375c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-.375m1.5-1.5H21a.75.75 0 0 0-.75.75v.75m0 0H3.75m0 0h-.375a1.125 1.125 0 0 1-1.125-1.125V15m1.5 1.5v-.75A.75.75 0 0 0 3 15h-.75M15 10.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm3 0h.008v.008H18V10.5Zm-12 0h.008v.008H6V10.5Z" /></svg> Efectivo</div></td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-right font-semibold text-success">$1,250.00</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-center"><span class="badge color-success badge-sm">Completada</span></td>
<td class="w-20 px-5 py-3 text-sm align-middle border-b border-base-300 text-center"><div class="flex items-center justify-center gap-1"><button class="flex items-center justify-center size-8 p-0 bg-transparent border-none rounded-lg cursor-pointer opacity-60 hover:opacity-100 hover:bg-base-200"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" /></svg></button></div></td>
</tr>
<tr class="transition-colors duration-150 hover:bg-primary/5 cursor-pointer">
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 font-mono font-semibold"><a class="text-primary hover:underline" href="#">V-0047</a></td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 opacity-70">09/02/2026 11:15</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300">Pedro López</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300"><div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" /></svg> Ana Martín</div></td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300"><div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 8.25h19.5M2.25 9h19.5m-16.5 5.25h6m-6 2.25h3m-3.75 3h15a2.25 2.25 0 0 0 2.25-2.25V6.75A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25v10.5A2.25 2.25 0 0 0 4.5 19.5Z" /></svg> Tarjeta</div></td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-right font-semibold text-success">$890.50</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-center"><span class="badge color-success badge-sm">Completada</span></td>
<td class="w-20 px-5 py-3 text-sm align-middle border-b border-base-300 text-center"><div class="flex items-center justify-center gap-1"><button class="flex items-center justify-center size-8 p-0 bg-transparent border-none rounded-lg cursor-pointer opacity-60 hover:opacity-100 hover:bg-base-200"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" /></svg></button></div></td>
</tr>
<tr class="transition-colors duration-150 hover:bg-primary/5 cursor-pointer">
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 font-mono font-semibold"><a class="text-primary hover:underline" href="#">V-0046</a></td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 opacity-70">08/02/2026 17:45</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 opacity-50">Sin cliente</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300"><div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" /></svg> Juan Pérez</div></td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300"><div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M7.5 21 3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5" /></svg> Transferencia</div></td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-right font-semibold text-success">$320.00</td>
<td class="px-5 py-3 text-sm align-middle border-b border-base-300 text-center"><span class="badge color-warning badge-sm">Pendiente</span></td>
<td class="w-20 px-5 py-3 text-sm align-middle border-b border-base-300 text-center"><div class="flex items-center justify-center gap-1"><button class="flex items-center justify-center size-8 p-0 bg-transparent border-none rounded-lg cursor-pointer opacity-60 hover:opacity-100 hover:bg-base-200"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" /></svg></button></div></td>
</tr>
<tr class="transition-colors duration-150 hover:bg-primary/5 cursor-pointer">
<td class="px-5 py-3 text-sm align-middle font-mono font-semibold"><a class="text-primary hover:underline" href="#">V-0045</a></td>
<td class="px-5 py-3 text-sm align-middle opacity-70">08/02/2026 09:20</td>
<td class="px-5 py-3 text-sm align-middle">Tech Solutions S.A.</td>
<td class="px-5 py-3 text-sm align-middle"><div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" /></svg> Ana Martín</div></td>
<td class="px-5 py-3 text-sm align-middle"><div class="flex items-center gap-2"><svg class="size-4 opacity-50" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 8.25h19.5M2.25 9h19.5m-16.5 5.25h6m-6 2.25h3m-3.75 3h15a2.25 2.25 0 0 0 2.25-2.25V6.75A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25v10.5A2.25 2.25 0 0 0 4.5 19.5Z" /></svg> Tarjeta</div></td>
<td class="px-5 py-3 text-sm align-middle text-right font-semibold text-success">$2,100.00</td>
<td class="px-5 py-3 text-sm align-middle text-center"><span class="badge color-error badge-sm">Cancelada</span></td>
<td class="w-20 px-5 py-3 text-sm align-middle text-center"><div class="flex items-center justify-center gap-1"><button class="flex items-center justify-center size-8 p-0 bg-transparent border-none rounded-lg cursor-pointer opacity-60 hover:opacity-100 hover:bg-base-200"><svg class="size-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" /></svg></button></div></td>
</tr>
</tbody>
</table>
</div>
<!-- Footer -->
<div class="flex items-center justify-between px-5 py-3 border-t border-base-300 flex-wrap gap-3">
<div class="flex items-center gap-2 text-sm opacity-60">
<span>Mostrar:</span>
<select class="px-2 py-1 text-sm rounded-lg border border-base-300 bg-base-100"><option>10</option><option selected>25</option><option>50</option></select>
</div>
<span class="text-sm opacity-60">Mostrando 1-4 de 48</span>
<nav class="pagination pagination-sm">
<button class="pagination-btn pagination-prev" disabled><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5" /></svg></button>
<button class="pagination-btn pagination-active">1</button>
<button class="pagination-btn">2</button>
<button class="pagination-btn pagination-next"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" /></svg></button>
</nav>
</div>
</div> Requires: tw.min.css
// HTMX integration for Django backend
// Search with debounce
const search = document.querySelector('.datatable-search');
search.setAttribute('hx-get', '/m/sales/history/');
search.setAttribute('hx-trigger', 'keyup changed delay:400ms');
search.setAttribute('hx-target', '#sales-table-container');
// Sortable columns
document.querySelectorAll('.datatable-th-sortable').forEach(th => {
th.addEventListener('click', () => {
const sorted = th.classList.contains('datatable-th-sorted');
const desc = th.classList.contains('datatable-th-sorted-desc');
// Remove sorted from all
document.querySelectorAll('.datatable-th').forEach(h => {
h.classList.remove('datatable-th-sorted', 'datatable-th-sorted-desc');
});
// Toggle sort direction
th.classList.add('datatable-th-sorted');
if (sorted && !desc) th.classList.add('datatable-th-sorted-desc');
});
});
// Filter change triggers HTMX request
document.querySelectorAll('select, input[type="date"]').forEach(el => {
el.setAttribute('hx-get', '/m/sales/history/');
el.setAttribute('hx-trigger', 'change');
el.setAttribute('hx-target', '#sales-table-container');
}); Classes Reference
| Class | Description |
|---|---|
| .datatable | Container |
| .datatable-header | Title + actions bar |
| .datatable-title | Table title |
| .datatable-toolbar | Search + filter bar |
| .datatable-body | Scrollable table area |
| .datatable-table | The <table> element |
| .datatable-thead | Sticky header |
| .datatable-th | Header cell |
| .datatable-th-sortable | Sortable column |
| .datatable-th-sorted | Currently sorted |
| .datatable-tr | Table row |
| .datatable-tr-selected | Selected row |
| .datatable-td | Table cell |
| .datatable-row-actions | Actions container |
| .datatable-row-action | Action button |
| .datatable-footer | Pagination + info |
| .datatable-empty | Empty state |
| .datatable-loading | Loading state |
| .datatable-bulk | Bulk selection bar |
| .datatable-responsive | Mobile card view |
| .datatable-bordered | Bordered variant |
| .datatable-striped | Striped rows |
| .datatable-compact | Compact size |