1. Interactive Playground (Employee List)
Showcases Custom UI Slots for Selection, Drag Handles, and Accordions to perfectly construct complex cell layouts without breaking column limits.
Emp ID | Employee Profile | Department | Location | Status | Rating | Contact Email | Actions | |
|---|---|---|---|---|---|---|---|---|
EMP-0001 | Marcus ChenLogistics Coordinator | Operations | Singapore | On Leave | Exceeds Expectations | |||
EMP-0002 | Emily ThorneHR Manager | Human Resources | London, UK | Deployed | Meets Expectations | |||
EMP-0003 | John DoeVessel Captain | Maritime | Tokyo, JP | Inactive | Needs Improvement | |||
EMP-0004 | Alicia KeysDeck Cadet | Finance | Dubai, UAE | Active | Outstanding | |||
EMP-0005 | Robert BaratheonSenior Developer | Engineering | Manila, PH | On Leave | Exceeds Expectations | |||
EMP-0006 | Sarah JenkinsLogistics Coordinator | Operations | Singapore | Deployed | Meets Expectations | |||
EMP-0007 | Marcus ChenHR Manager | Human Resources | London, UK | Inactive | Needs Improvement | |||
EMP-0008 | Emily ThorneVessel Captain | Maritime | Tokyo, JP | Active | Outstanding | |||
EMP-0009 | John DoeDeck Cadet | Finance | Dubai, UAE | On Leave | Exceeds Expectations | |||
EMP-0010 | Alicia KeysSenior Developer | Engineering | Manila, PH | Deployed | Meets Expectations |
1 to 10 of 45 records
<Table
:records="employeeRecords"
:columns="employeeColumns"
rowKey="id"
:maxHeight="400"
rowSelection
expandableRows
reorderableColumns
reorderableRows
@row-click="handleRowClick"
>
<template #cell-selection="{ row, checked, toggle }">
<Checkbox :modelValue="checked" @update:modelValue="toggle" />
</template>
<template #cell-drag-handle="{ row }">
<img :src="row.avatar" alt="Example user avatar" class="h-9 w-9 rounded-full" />
<span>{{ row.name }}</span>
</template>
<template #cell-status="{ row }">
<span :class="getStatusBadgeVariant(row.status)">{{ row.status }}</span>
</template>
<template #expanded-row="{ row }">
Contact: {{ row.email }}
</template>
<template #pagination>
<Pagination v-model:currentPage="currentPage" v-model:rowsPerPage="rowsPerPage" :totalRecords="employeeRecords.length" />
</template>
</Table>2. Crew Change Batches (Full-Width Row Override)
Manning layout utilizing the #row slot. It intercepts records containing children arrays and renders a full-width header spanning all columns.
Crew Member Name | Rank | Nationality | Passport Exp |
|---|---|---|---|
Manila Embarkation - Vessel Alpha(2 Crew) Oct 12, 2026Approved | |||
Singapore Disembarkation - Vessel Beta(3 Crew) Oct 15, 2026Pending | |||
1 to 2 of 2 records
<Table :records="crewRecords" :columns="crewColumns" treeNodeKey="crewList">
<!-- treeNodeKey tells Table which key holds nested rows - this dataset uses
"crewList" instead of the library's default "children" -->
<!-- #row intercepts the whole <tr>, so a record with a nested crewList
array can render a full-width, colspan-ed group header instead of normal cells -->
<template #row="{ row, depth, expanded, toggle, colspan }">
<template v-if="row.batchName">
<td :colspan="colspan" @click="toggle">
<Icon :icon="expanded ? 'lucide:chevron-down' : 'lucide:chevron-right'" />
{{ row.batchName }} ({{ row.crewList.length }} Crew)
<span>{{ row.status }}</span>
</td>
</template>
<template v-else>
<td :style="{ paddingLeft: `${depth * 20 + 16}px` }">{{ row.name }}</td>
<td>{{ row.rank }}</td>
<td>{{ row.nationality }}</td>
<td>{{ row.passport }}</td>
</template>
</template>
</Table>3. Vehicle Order Form (Inline Editing)
Injects standard InputText and InputNumber components directly into the cells via named slots for rapid data entry.
Vehicle Type | Plate Number | Quantity | Rate (PHP) | Line Total |
|---|---|---|---|---|
4-Wheeler Closed Van | ₱30,000.00 | |||
6-Wheeler Forward | ₱22,500.00 | |||
10-Wheeler Wing Van | ₱0.00 |
1 to 3 of 3 records
<Table :records="vofRecords" :columns="vofColumns">
<template #cell-plateNumber="{ row }">
<InputText v-model="row.plateNumber" size="sm" />
</template>
<template #cell-qty="{ row }">
<InputNumber v-model="row.qty" :min="0" size="sm" />
</template>
<template #cell-rate="{ row }">
<InputNumber v-model="row.rate" mode="currency" currency="PHP" size="sm" />
</template>
<template #cell-total="{ row }">
{{ (row.qty * row.rate).toLocaleString('en-PH', { style: 'currency', currency: 'PHP' }) }}
</template>
</Table>4. Accounting Table (Footer Aggregation)
Leveraging the #footer slot to display computed properties across the entire dataset.
Invoice ID | Description / Particulars | Issue Date | Amount (USD) |
|---|---|---|---|
INV-2026-001 | Port Dues - Manila South Harbor | 2026-06-01 | $4,500.00 |
INV-2026-002 | Bunker Fuel Surcharge | 2026-06-03 | $12,500.50 |
INV-2026-003 | Pilotage Fees | 2026-06-05 | $850.75 |
Grand Total$17,851.25 | |||
1 to 3 of 3 records
<Table :records="accountingRecords" :columns="accountingColumns" stripedRows>
<template #cell-amount="{ row }">
{{ row.amount.toLocaleString('en-US', { style: 'currency', currency: 'USD' }) }}
</template>
<!-- #footer spans the full width beneath every row, ideal for aggregation -->
<template #footer>
<div class="flex justify-end gap-8">
<span>Grand Total</span>
<span>{{ totalAmount }}</span>
</div>
</template>
</Table>5. Rates Entry (Floating Column Filters & Collapsibles)
Combines tree-node grouping with the #filter-{key} slot to build AG-Grid style header inputs.
Trade Route | Container | Base Freight | BAF | Total USD |
|---|---|---|---|---|
Asia to US West Coast | Various | - | - | - |
Asia to Europe Base Ports | Various | - | - | - |
1 to 2 of 2 records
<Table :records="ratesRecords" :columns="ratesColumns">
<!-- #filter-{key} renders an input directly in that column's header cell -->
<template #filter-route>
<InputText v-model="filters.route" placeholder="Filter Routes..." icon="lucide:search" />
</template>
<template #filter-containerType>
<InputText v-model="filters.containerType" placeholder="Filter Type..." />
</template>
<template #cell-baseRate="{ row }">
{{ row.baseRate ? `$${row.baseRate}` : '-' }}
</template>
<template #cell-total="{ row }">
{{ row.total ? `$${row.total}` : '-' }}
</template>
</Table>API Reference
Complete specifications for components, props, events, and dynamic slots.
Props
Name | Type / Payload | Default | Description |
|---|---|---|---|
records | any[] | [] (v-model) | The flat array of data objects to render. Natively supports nested children matrices. |
columns | TableColumn[] | [] | Array of column definitions specifying keys, headers, alignments, and widths. |
rowKey | string | "id" | The unique property identifier used for tracking expanded, selected, and dragged rows. |
sortKey | string | "" | The currently active sorted column key. |
sortDirection | "asc" | "desc" | null | null | The currently active sort direction modifier. |
maxHeight | string | number | "auto" | Limits table height and enforces vertical scrolling. Accepts px (number) or string (vh/rem). |
rowSelection | boolean | false | Injects a pinned left column containing bulk selection checkboxes. |
reorderableColumns | boolean | false | Allows drag-and-drop structural reorganization of the header columns. |
reorderableRows | boolean | function | false | Enables row dragging. Supply a function `(row) => boolean` to conditionally lock rows. |
expandableRows | boolean | false | Injects a pinned left column allowing row accordion dropdowns. |
loading | boolean | false | Mounts an overlay indicating pending network requests. |
loadingMessage | string | "Loading records..." | Custom text displayed during the loading state. |
emptyMessage | string | "No records found." | Text displayed when the `records` array is empty. |
emptyStateIcon | string | "lucide:inbox" | Iconify key used in the empty state splash. |
treeNodeKey | string | "children" | The object key used to identify hierarchical nested sub-rows. |
rowClass | string | array | object | fn | undefined | Applies dynamic Tailwind classes to specific rows. Functions receive `(row, index)`. |
stripedRows | boolean | true | Applies alternating background colors for easier row scanning. |
bordered | boolean | false | Renders explicit vertical and horizontal borders between all matrix cells. |
seamless | boolean | false | Removes the outer table border wrapper for clean nested integration. |
size | "xs" | "sm" | "md" | "lg" | "xl" | "sm" | Modifies the total vertical and horizontal padding across all table cells. |
highlightOnHover | boolean | true | Enables standard row background highlighting on mouse hover. |
rtlDirection | boolean | false | Forces Right-To-Left layout logic. |
Column Definition (TableColumn)
Name | Type / Payload | Default | Description |
|---|---|---|---|
key | string | Required | The data key in your records object to bind to this column. |
header | string | Required | The display text for the column header. |
width | string | number | auto | Fixed width in px (number) or CSS string. Required for pinned columns. |
sortable | boolean | false | Enables click-to-sort functionality for this specific column. |
pinned | "left" | "right" | undefined | Pins the column to the edge of the scrolling viewport. |
align | "left" | "center" | "right" | "left" | Alignment of both the header and data cells. |
hidden | boolean | false | Toggles column visibility without removing it from the array. |
headerClass | string | "" | Custom classes strictly applied to the `<th>` cell. |
cellClass | string | fn | "" | Custom classes applied to the `<td>`. Functions receive `(row)`. |
children | TableColumn[] | undefined | Array of nested columns to build multi-level AG-Grid style header groups. |
Events (Emits)
Name | Type / Payload | Default | Description |
|---|---|---|---|
row-click | (row, event) | - | Fired when a user clicks anywhere on a row that is not an interactive button or input. |
row-contextmenu | (row, event) | - | Intercepts right-clicks on a row to trigger the `#context-menu` slot layout. |
selection-change | (selectedRows[]) | - | Fired whenever a user toggles the selection status of any checkboxes. |
sort-change | ({ key, direction }) | - | Dispatched when a sortable header is clicked. Executed logic is headless. |
column-drop | (sourceField, targetField) | - | Dispatched when a column completes a drag-and-drop horizontal reordering action. |
row-drop | (sourceId, targetId) | - | Dispatched when a row completes a vertical drag-and-drop reordering action. |
Slots
Slot Name | Exposed Bindings | Description |
|---|---|---|
toolbar | - | Injects full-width components completely above the table (e.g. search bars, batch actions). |
empty | - | Overrides the standard icon/text splash screen when 0 records are provided. |
header-expand | - | Overrides the empty `<th>` cell directly above the accordion column. |
header-selection | { checked, indeterminate, toggle } | Overrides the "Select All" checkbox in the header. Exposes full toggle state. |
header-drag-handle | - | Overrides the empty `<th>` cell directly above the row drag column. |
header-{key} | { column } | Dynamically targets a specific column key to inject custom typography or sort icons. |
header-action | - | Overrides the default "Actions" text in the pinned right-side column. |
filter-{key} | { column } | Creates a sub-header row dedicated to injecting standard form inputs for column filtering. |
tbody-start | { colspan } | Injects persistent static rows at the absolute top of the table body. |
row | { row, index, expanded, toggle, colspan } | Triggered when a row has an array of children. Bypasses standard `<td>` loops, granting total <tr> structure control. |
cell-expand | { row, expanded, toggle } | Overrides the accordion expansion button in the system column. |
cell-selection | { row, checked, toggle } | Overrides the row selection checkboxes in the system column. |
cell-drag-handle | { row } | Overrides the grab handle in the system column. |
body-tree-toggle | { row, expanded, toggle } | Overrides the expand toggle button on hierarchical tree nodes within the first data column. |
cell-{key} | { row, column, index } | The most heavily utilized slot. Replaces the text output of a cell with interactive UI elements. |
action | { row, index } | Populates the pinned right-side cell for dropdown menus or edit buttons. |
expanded-row | { row, index } | Populates the dynamic accordion container injected directly beneath a toggled row. |
tbody-end | { colspan } | Injects persistent static rows at the absolute bottom of the table body. |
footer | - | A dedicated area spanning all columns for statistical aggregation or sums. |
context-menu | { row, close } | A hidden layout zone activated strictly on right-click for advanced nested actions. |
pagination | - | A protected zone beneath the entire table footprint designated for injecting Pagination controls. |