Table

The Table component provides a full-featured data table with sorting, pagination, row selection, and customizable styling.

Installation

npm install @duskmoon-dev/el-table

Usage

import '@duskmoon-dev/el-table/register';
<el-dm-table id="my-table"></el-dm-table>

<script>
  const table = document.getElementById('my-table');
  table.columns = [
    { key: 'name', label: 'Name', sortable: true },
    { key: 'email', label: 'Email' }
  ];
  table.data = [
    { id: 1, name: 'Alice', email: 'alice@example.com' },
    { id: 2, name: 'Bob', email: 'bob@example.com' }
  ];
</script>

Live Demo

Basic Table

Properties

PropertyTypeDefaultDescription
columnsTableColumn[][]Column definitions
dataTableRow[][]Row data array
sort-columnstring-Current sort column key
sort-direction'asc' | 'desc''asc'Sort direction
paginatedbooleanfalseEnable pagination
pagenumber1Current page number
page-sizenumber10Rows per page
selection-mode'none' | 'single' | 'multiple''none'Row selection mode
stripedbooleanfalseAlternating row colors
borderedbooleanfalseShow cell borders
hoverablebooleantrueHighlight rows on hover
compactbooleanfalseReduced padding
sticky-headerbooleanfalseFixed header on scroll
loadingbooleanfalseShow loading state
empty-messagestring'No data available'Empty state text

TableColumn Interface

interface TableColumn {
  key: string;        // Data key for this column
  label: string;      // Display label in header
  sortable?: boolean; // Enable sorting
  width?: string;     // CSS width (e.g., '100px', '20%')
  align?: 'left' | 'center' | 'right';
  hidden?: boolean;   // Hide column
}

TableRow Interface

interface TableRow {
  id: string | number;  // Required unique identifier
  [key: string]: unknown; // Data fields matching column keys
}

Sorting

Click on sortable column headers to sort. Clicking the same header toggles between ascending and descending order.

Sortable Table

<el-dm-table id="table"></el-dm-table>

<script>
  table.columns = [
    { key: 'name', label: 'Name', sortable: true },
    { key: 'salary', label: 'Salary', sortable: true, align: 'right' }
  ];
</script>

Pagination

Enable pagination to split large datasets across multiple pages.

Paginated Table

<el-dm-table paginated page-size="10"></el-dm-table>

Row Selection

Enable single or multiple row selection with checkboxes/radio buttons.

Multiple Selection

<!-- Multiple selection with checkboxes -->
<el-dm-table selection-mode="multiple"></el-dm-table>

<!-- Single selection with radio buttons -->
<el-dm-table selection-mode="single"></el-dm-table>

Styling Variants

Striped

Striped Rows

<el-dm-table striped></el-dm-table>

Bordered

Bordered Cells

<el-dm-table bordered></el-dm-table>

Compact

Compact Table

<el-dm-table compact></el-dm-table>

Declarative Columns

Use <el-dm-table-column> elements for declarative column definition:

<el-dm-table id="table">
  <el-dm-table-column key="name" label="Name" sortable></el-dm-table-column>
  <el-dm-table-column key="email" label="Email"></el-dm-table-column>
  <el-dm-table-column key="role" label="Role" width="120px"></el-dm-table-column>
</el-dm-table>

<script>
  // Only need to set data, columns come from children
  table.data = [
    { id: 1, name: 'Alice', email: 'alice@example.com', role: 'Admin' }
  ];
</script>

Events

EventDetailDescription
sort{ column, direction }Fired when sort changes
select{ selectedIds, selectedRows }Fired when selection changes
page-change{ page, pageSize }Fired when page changes
row-click{ row, rowIndex }Fired when a row is clicked

Event Handling

const table = document.querySelector('el-dm-table');

table.addEventListener('sort', (e) => {
  console.log('Sorted by:', e.detail.column, e.detail.direction);
});

table.addEventListener('select', (e) => {
  console.log('Selected rows:', e.detail.selectedRows);
});

table.addEventListener('page-change', (e) => {
  console.log('Page changed to:', e.detail.page);
});

Methods

MethodParametersDescription
sort(column, direction?)column: string, direction?: 'asc' | 'desc'Sort by column
goToPage(page)page: numberNavigate to page
selectRow(id)id: string | numberSelect a row
deselectRow(id)id: string | numberDeselect a row
selectAll()-Select all visible rows
deselectAll()-Deselect all rows
getSelectedRows()-Get selected row data

CSS Custom Properties

PropertyDefaultDescription
--table-max-height400pxMax height for sticky header
--dm-color-surface-Table background
--dm-color-surface-variant-Header/stripe background
--dm-color-outline-Border color
--dm-color-primary-Sort indicator color
--dm-color-primary-container-Selected row background

Accessibility

  • Uses native <table> semantics with proper ARIA roles
  • Sortable headers have aria-sort attribute
  • Selected rows have aria-selected attribute
  • Loading state uses aria-busy attribute
  • Keyboard navigation for interactive elements
  • Focus indicators on all interactive elements