Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/TheSerchCp/SEAM/llms.txt

Use this file to discover all available pages before exploring further.

The Table component turns a columns definition and a rows array into a fully responsive data table. On screens wider than the md Tailwind breakpoint it renders a standard HTML <table>; on smaller screens it automatically switches to a stacked card layout so every row is readable without horizontal scrolling. Both views share the same columns and actions configuration — you define your data shape once and both layouts render from it.
import { Table } from '../../shared/components/ui/Table.js';

Props

columns
array
required
Ordered array of column descriptor objects. Each object controls both the header label and the row data key.
[
  { label: '#',       key: 'idUser'    },
  { label: 'Nombre',  key: 'full_name' },
  { label: 'Email',   key: 'email'     },
  { label: 'Rol',     key: 'roleName'  },
]
PropertyTypeDescription
labelstringText shown in the <th> header and as the field label in the mobile card.
keystringProperty name read from each row object. Falls back to '-' when the value is falsy.
rows
array
required
Array of plain objects. Each object must contain a property for every key declared in columns. Extra properties are ignored by the renderer but are available inside the actions callback.
tbodyId
string
default:"\"table-body\""
The id attribute written onto the <tbody> element in the desktop table view. Useful when you need to update table rows in-place via document.getElementById(tbodyId).
emptyMessage
string
default:"\"Sin datos\""
Text shown inside a centred empty-state block when rows is empty or undefined. The empty state renders a large inbox icon above the message.
actions
function | null
default:"null"
Optional callback invoked once per row: (row) => htmlString. The returned HTML is injected into an Acciones column on desktop and into a flex-wrap footer strip on mobile. Return an empty string to suppress the column for a specific row.
actions: (user) =>
  `<button onclick="window.editUser?.(${user.idUser})">Editar</button>
   <button onclick="window.deleteUser?.(${user.idUser})">Eliminar</button>`

Column definition — USER_COLUMNS from users.page.js

const USER_COLUMNS = [
    { label: '#',      key: 'idUser'    },
    { label: 'Nombre', key: 'full_name' },
    { label: 'Email',  key: 'email'     },
    { label: 'Rol',    key: 'roleName'  },
];

Complete usage example

The following is taken directly from users.page.js and shows columns, rows, a custom tbodyId, and per-row action buttons:
import { Table } from '../../shared/components/ui/Table.js';

const editButtonClasses =
    'inline-flex items-center justify-center gap-1 rounded-md border border-amber-500 bg-amber-500 px-2 py-1.5 text-[10px] sm:text-xs font-semibold text-white transition hover:bg-amber-600';
const deleteButtonClasses =
    'inline-flex items-center justify-center gap-1 rounded-md border border-red-500 bg-red-500 px-2 py-1.5 text-[10px] sm:text-xs font-semibold text-white transition hover:bg-red-600';

document.getElementById('users-table-wrap').innerHTML = Table({
    columns: USER_COLUMNS,
    rows: users,              // array fetched from the API
    tbodyId: 'users-body',
    emptyMessage: 'No hay usuarios registrados',
    actions: (user) => `
        <button
            class="${editButtonClasses}"
            onclick="window.editUser?.(${user.idUser})"
            title="Editar">
            <i class="fa-solid fa-pen"></i>
            <span class="hidden sm:inline">Editar</span>
        </button>
        <button
            class="${deleteButtonClasses}"
            onclick="window.deleteUser?.(${user.idUser})"
            title="Eliminar">
            <i class="fa-solid fa-trash"></i>
            <span class="hidden sm:inline">Eliminar</span>
        </button>
    `,
});

Responsive design

Table renders two sibling HTML structures from the same data:
1

Desktop — hidden below md breakpoint

A standard <table> wrapped in an overflow-x-auto scroll container. Headers use sticky positioning (sticky top-0) so they remain visible when the table scrolls vertically. Odd rows receive a subtle alternate background. The actions column header is labelled Acciones and its cells are centre-aligned.
2

Mobile — hidden above md breakpoint

Each row becomes a rounded card with border border-gray-700/60. Column values are stacked vertically with their label shown in bold uppercase above the value. Long values (over 40 characters) wrap rather than truncate. Action buttons are rendered in a flex-wrap strip separated from the data by a top border.
3

Empty state — shown for both viewports

When rows is empty or not provided, a single centred block with a fa-inbox icon and the emptyMessage string is rendered instead of either layout.
Both the desktop <table> and the mobile cards are always present in the DOM. Visibility is controlled exclusively by the Tailwind hidden / md:block / md:hidden utility classes, so no JavaScript is required to switch between layouts on resize.

Updating the table after a data change

Because Table returns a plain HTML string, the recommended pattern for refreshing data is to re-render the entire component and replace the wrapper element:
// Re-render and replace only the table wrapper, leaving the rest of the page intact.
async function updateUsersTable() {
    const users   = await getUsers();
    const wrapper = document.getElementById('users-table-wrap');

    if (!wrapper) return;

    const temp        = document.createElement('div');
    temp.innerHTML    = Table({ columns: USER_COLUMNS, rows: users, tbodyId: 'users-body', actions });
    const newContent  = temp.firstElementChild;

    wrapper.replaceWith(newContent);
}

Build docs developers (and LLMs) love