Table
Tables display information in a grid-like format of rows and columns. @duskmoon-dev/core provides a complete set of Material Design 3 table variants with support for different layouts, interactions, and data presentations.
Basic Usage
Name
Email
Role
John Doe
john@example.com
Developer
Jane Smith
jane@example.com
Designer
Bob Johnson
bob@example.com
Manager
< table class = "table" >
< thead >
< tr >
< th >Name</ th >
< th >Email</ th >
< th >Role</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >John Doe</ td >
< td >john@example.com</ td >
< td >Developer</ td >
</ tr >
< tr >
< td >Jane Smith</ td >
< td >jane@example.com</ td >
< td >Designer</ td >
</ tr >
< tr >
< td >Bob Johnson</ td >
< td >bob@example.com</ td >
< td >Manager</ td >
</ tr >
</ tbody >
</ table >
Variants
Striped Table
Alternate row colors for improved readability:
Product
Category
Price
Widget A
Hardware
$29.99
Widget B
Software
$49.99
Widget C
Hardware
$19.99
Widget D
Software
$99.99
< table class = "table table-striped" >
< thead >
< tr >
< th >Product</ th >
< th >Category</ th >
< th >Price</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >Widget A</ td >
< td >Hardware</ td >
< td >$29.99</ td >
</ tr >
< tr >
< td >Widget B</ td >
< td >Software</ td >
< td >$49.99</ td >
</ tr >
< tr >
< td >Widget C</ td >
< td >Hardware</ td >
< td >$19.99</ td >
</ tr >
< tr >
< td >Widget D</ td >
< td >Software</ td >
< td >$99.99</ td >
</ tr >
</ tbody >
</ table >
Bordered Table
Add borders to all cells:
ID
Name
Status
001
Project Alpha
Active
002
Project Beta
Completed
003
Project Gamma
Pending
< table class = "table table-bordered" >
< thead >
< tr >
< th >ID</ th >
< th >Name</ th >
< th >Status</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >001</ td >
< td >Project Alpha</ td >
< td >Active</ td >
</ tr >
< tr >
< td >002</ td >
< td >Project Beta</ td >
< td >Completed</ td >
</ tr >
< tr >
< td >003</ td >
< td >Project Gamma</ td >
< td >Pending</ td >
</ tr >
</ tbody >
</ table >
Borderless Table
Remove all borders for a clean look:
Date
Event
Location
2025-01-15
Team Meeting
Conference Room A
2025-01-20
Product Launch
Main Hall
< table class = "table table-borderless" >
< thead >
< tr >
< th >Date</ th >
< th >Event</ th >
< th >Location</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >2025-01-15</ td >
< td >Team Meeting</ td >
< td >Conference Room A</ td >
</ tr >
< tr >
< td >2025-01-20</ td >
< td >Product Launch</ td >
< td >Main Hall</ td >
</ tr >
</ tbody >
</ table >
Hoverable Rows
Add hover effects to table rows:
Customer
Order ID
Total
Alice Brown
#12345
$150.00
Charlie Davis
#12346
$275.50
Eve Wilson
#12347
$89.99
< table class = "table table-hover" >
< thead >
< tr >
< th >Customer</ th >
< th >Order ID</ th >
< th >Total</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >Alice Brown</ td >
< td >#12345</ td >
< td >$150.00</ td >
</ tr >
< tr >
< td >Charlie Davis</ td >
< td >#12346</ td >
< td >$275.50</ td >
</ tr >
< tr >
< td >Eve Wilson</ td >
< td >#12347</ td >
< td >$89.99</ td >
</ tr >
</ tbody >
</ table >
Combined Variants
Combine striped and hover effects:
Task
Assignee
Due Date
Update documentation
John
2025-01-15
Fix bug #123
Jane
2025-01-16
Review PR #45
Bob
2025-01-17
< table class = "table table-striped table-hover" >
< thead >
< tr >
< th >Task</ th >
< th >Assignee</ th >
< th >Due Date</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >Update documentation</ td >
< td >John</ td >
< td >2025-01-15</ td >
</ tr >
< tr >
< td >Fix bug #123</ td >
< td >Jane</ td >
< td >2025-01-16</ td >
</ tr >
< tr >
< td >Review PR #45</ td >
< td >Bob</ td >
< td >2025-01-17</ td >
</ tr >
</ tbody >
</ table >
Density Options
Compact Table
Reduce padding for space-efficient layouts:
Code
Description
Qty
ABC-001
Component A
50
ABC-002
Component B
75
< table class = "table table-compact" >
< thead >
< tr >
< th >Code</ th >
< th >Description</ th >
< th >Qty</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >ABC-001</ td >
< td >Component A</ td >
< td >50</ td >
</ tr >
< tr >
< td >ABC-002</ td >
< td >Component B</ td >
< td >75</ td >
</ tr >
</ tbody >
</ table >
Comfortable Table
Increase padding for better readability:
Title
Author
Year
The Great Gatsby
F. Scott Fitzgerald
1925
To Kill a Mockingbird
Harper Lee
1960
< table class = "table table-comfortable" >
< thead >
< tr >
< th >Title</ th >
< th >Author</ th >
< th >Year</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >The Great Gatsby</ td >
< td >F. Scott Fitzgerald</ td >
< td >1925</ td >
</ tr >
< tr >
< td >To Kill a Mockingbird</ td >
< td >Harper Lee</ td >
< td >1960</ td >
</ tr >
</ tbody >
</ table >
Interactive Features
Selectable Rows
Make rows selectable with visual feedback:
File Name
Size
Modified
document.pdf
2.4 MB
2025-01-10
spreadsheet.xlsx
1.8 MB
2025-01-11
presentation.pptx
5.2 MB
2025-01-12
< table class = "table table-selectable" >
< thead >
< tr >
< th >File Name</ th >
< th >Size</ th >
< th >Modified</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >document.pdf</ td >
< td >2.4 MB</ td >
< td >2025-01-10</ td >
</ tr >
< tr class = "selected" >
< td >spreadsheet.xlsx</ td >
< td >1.8 MB</ td >
< td >2025-01-11</ td >
</ tr >
< tr >
< td >presentation.pptx</ td >
< td >5.2 MB</ td >
< td >2025-01-12</ td >
</ tr >
</ tbody >
</ table >
With Checkboxes
Add checkboxes for multi-selection:
< table class = "table table-hover" >
< thead >
< tr >
< th class = "table-checkbox" >
< input type = "checkbox" aria-label = "Select all" >
</ th >
< th >Name</ th >
< th >Department</ th >
< th >Status</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td class = "table-checkbox" >
< input type = "checkbox" aria-label = "Select row" >
</ td >
< td >Emma Thompson</ td >
< td >Engineering</ td >
< td >Active</ td >
</ tr >
< tr >
< td class = "table-checkbox" >
< input type = "checkbox" aria-label = "Select row" >
</ td >
< td >Michael Chen</ td >
< td >Design</ td >
< td >Active</ td >
</ tr >
</ tbody >
</ table >
Sortable Columns
Add sort indicators to columns:
Name
↑
Email
↕
Role
↕
Alice Johnson
alice@example.com
Engineer
Bob Smith
bob@example.com
Designer
< table class = "table" >
< thead >
< tr >
< th class = "table-sort table-sort-asc" >
Name
< span class = "table-sort-icon" >↑</ span >
</ th >
< th class = "table-sort" >
Email
< span class = "table-sort-icon" >↕</ span >
</ th >
< th class = "table-sort" >
Role
< span class = "table-sort-icon" >↕</ span >
</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >Alice Johnson</ td >
< td >alice@example.com</ td >
< td >Engineer</ td >
</ tr >
< tr >
< td >Bob Smith</ td >
< td >bob@example.com</ td >
< td >Designer</ td >
</ tr >
</ tbody >
</ table >
Column Alignment
Numeric Columns
Right-align numeric data with tabular figures:
Product
Price
Stock
Sales
Widget Pro
$1,234.56
1,250
3,456
Widget Lite
$89.99
850
2,789
< table class = "table" >
< thead >
< tr >
< th >Product</ th >
< th class = "table-numeric" >Price</ th >
< th class = "table-numeric" >Stock</ th >
< th class = "table-numeric" >Sales</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >Widget Pro</ td >
< td class = "table-numeric" >$1,234.56</ td >
< td class = "table-numeric" >1,250</ td >
< td class = "table-numeric" >3,456</ td >
</ tr >
< tr >
< td >Widget Lite</ td >
< td class = "table-numeric" >$89.99</ td >
< td class = "table-numeric" >850</ td >
< td class = "table-numeric" >2,789</ td >
</ tr >
</ tbody >
</ table >
Center Aligned
Center-align content:
Name
Status
Badge
Project Alpha
✓
Gold
Project Beta
⋯
Silver
< table class = "table" >
< thead >
< tr >
< th >Name</ th >
< th class = "table-center" >Status</ th >
< th class = "table-center" >Badge</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >Project Alpha</ td >
< td class = "table-center" >✓</ td >
< td class = "table-center" >Gold</ td >
</ tr >
< tr >
< td >Project Beta</ td >
< td class = "table-center" >⋯</ td >
< td class = "table-center" >Silver</ td >
</ tr >
</ tbody >
</ table >
Actions Column
Right-align action buttons:
Name
Email
Actions
John Doe
john@example.com
Edit
Delete
Jane Smith
jane@example.com
Edit
Delete
< table class = "table" >
< thead >
< tr >
< th >Name</ th >
< th >Email</ th >
< th class = "table-actions" >Actions</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >John Doe</ td >
< td >john@example.com</ td >
< td class = "table-actions" >
< button class = "btn btn-text btn-sm" >Edit</ button >
< button class = "btn btn-text btn-sm btn-error" >Delete</ button >
</ td >
</ tr >
< tr >
< td >Jane Smith</ td >
< td >jane@example.com</ td >
< td class = "table-actions" >
< button class = "btn btn-text btn-sm" >Edit</ button >
< button class = "btn btn-text btn-sm btn-error" >Delete</ button >
</ td >
</ tr >
</ tbody >
</ table >
Advanced Features
Keep header visible while scrolling:
ID
Name
Description
001
Item 1
Description for item 1
002
Item 2
Description for item 2
< div style = "max-height: 300px; overflow-y: auto;" >
< table class = "table table-sticky" >
< thead >
< tr >
< th >ID</ th >
< th >Name</ th >
< th >Description</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >001</ td >
< td >Item 1</ td >
< td >Description for item 1</ td >
</ tr >
< tr >
< td >002</ td >
< td >Item 2</ td >
< td >Description for item 2</ td >
</ tr >
<!-- More rows... -->
</ tbody >
</ table >
</ div >
With Caption
Add a caption to describe the table:
User Activity Report - January 2025
User
Login Count
Last Active
Alice
45
2025-01-10
Bob
32
2025-01-11
< table class = "table" >
< caption class = "table-caption" >
User Activity Report - January 2025
</ caption >
< thead >
< tr >
< th >User</ th >
< th >Login Count</ th >
< th >Last Active</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >Alice</ td >
< td >45</ td >
< td >2025-01-10</ td >
</ tr >
< tr >
< td >Bob</ td >
< td >32</ td >
< td >2025-01-11</ td >
</ tr >
</ tbody >
</ table >
Add footer totals or summaries:
Item
Quantity
Price
Total
Product A
10
$25.00
$250.00
Product B
5
$50.00
$250.00
Total
$500.00
< table class = "table" >
< thead >
< tr >
< th >Item</ th >
< th class = "table-numeric" >Quantity</ th >
< th class = "table-numeric" >Price</ th >
< th class = "table-numeric" >Total</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >Product A</ td >
< td class = "table-numeric" >10</ td >
< td class = "table-numeric" >$25.00</ td >
< td class = "table-numeric" >$250.00</ td >
</ tr >
< tr >
< td >Product B</ td >
< td class = "table-numeric" >5</ td >
< td class = "table-numeric" >$50.00</ td >
< td class = "table-numeric" >$250.00</ td >
</ tr >
</ tbody >
< tfoot >
< tr >
< td colspan = "3" >Total</ td >
< td class = "table-numeric" >$500.00</ td >
</ tr >
</ tfoot >
</ table >
Responsive Table
Wrap table in a responsive container for horizontal scrolling:
Name
Email
Phone
Department
Location
Role
Start Date
Status
John Doe
john@example.com
+1-234-567-8900
Engineering
New York
Senior Developer
2023-01-15
Active
< div class = "table-responsive" >
< table class = "table" >
< thead >
< tr >
< th >Name</ th >
< th >Email</ th >
< th >Phone</ th >
< th >Department</ th >
< th >Location</ th >
< th >Role</ th >
< th >Start Date</ th >
< th >Status</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >John Doe</ td >
< td >john@example.com</ td >
< td >+1-234-567-8900</ td >
< td >Engineering</ td >
< td >New York</ td >
< td >Senior Developer</ td >
< td >2023-01-15</ td >
< td >Active</ td >
</ tr >
<!-- More rows... -->
</ tbody >
</ table >
</ div >
Surface Variant
Use alternative surface color:
Metric
Value
Change
Revenue
$150,000
+12%
Users
5,432
+8%
< table class = "table table-surface table-striped" >
< thead >
< tr >
< th >Metric</ th >
< th class = "table-numeric" >Value</ th >
< th class = "table-numeric" >Change</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >Revenue</ td >
< td class = "table-numeric" >$150,000</ td >
< td class = "table-numeric" >+12%</ td >
</ tr >
< tr >
< td >Users</ td >
< td class = "table-numeric" >5,432</ td >
< td class = "table-numeric" >+8%</ td >
</ tr >
</ tbody >
</ table >
Best Practices
Data Organization
Structure data logically with appropriate headers:
Quarter
Revenue
Expenses
Profit
Margin
Q1 2024
$450,000
$280,000
$170,000
37.8%
Q2 2024
$520,000
$310,000
$210,000
40.4%
< table class = "table table-striped table-hover" >
< thead >
< tr >
< th >Quarter</ th >
< th class = "table-numeric" >Revenue</ th >
< th class = "table-numeric" >Expenses</ th >
< th class = "table-numeric" >Profit</ th >
< th class = "table-numeric" >Margin</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >Q1 2024</ td >
< td class = "table-numeric" >$450,000</ td >
< td class = "table-numeric" >$280,000</ td >
< td class = "table-numeric" >$170,000</ td >
< td class = "table-numeric" >37.8%</ td >
</ tr >
< tr >
< td >Q2 2024</ td >
< td class = "table-numeric" >$520,000</ td >
< td class = "table-numeric" >$310,000</ td >
< td class = "table-numeric" >$210,000</ td >
< td class = "table-numeric" >40.4%</ td >
</ tr >
</ tbody >
</ table >
Accessibility
Use <thead>, <tbody>, and <tfoot> for semantic structure
Always include proper column headers with <th>
Add scope attributes to headers
Use aria-label for icon-only buttons in action columns
Provide table captions for screen readers
Employee Directory
Name
Email
Department
John Doe
john@example.com
Engineering
< table class = "table" >
< caption class = "table-caption" >Employee Directory</ caption >
< thead >
< tr >
< th scope = "col" >Name</ th >
< th scope = "col" >Email</ th >
< th scope = "col" >Department</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td >John Doe</ td >
< td >john@example.com</ td >
< td >Engineering</ td >
</ tr >
</ tbody >
</ table >
Mobile Responsiveness
For complex tables, use responsive wrapper:
< div class = "table-responsive" >
< table class = "table table-striped" >
<!-- Many columns that may overflow on mobile -->
</ table >
</ div >
Framework Examples
React
interface TableProps {
data : Array < Record < string , any >>;
columns : Array <{ key : string ; header : string ; align ?: 'left' | 'center' | 'right' }>;
striped ?: boolean ;
hover ?: boolean ;
bordered ?: boolean ;
}
export function Table ({ data , columns , striped , hover , bordered } : TableProps ) {
const className = [
'table' ,
striped && 'table-striped' ,
hover && 'table-hover' ,
bordered && 'table-bordered' ,
]. filter (Boolean). join ( ' ' );
return (
< table className = {className}>
< thead >
< tr >
{columns. map (( col ) => (
< th
key = {col.key}
className = {col.align === 'right' ? 'table-numeric' : col.align === 'center' ? 'table-center' : '' }
>
{col.header}
</ th >
))}
</ tr >
</ thead >
< tbody >
{data. map (( row , idx ) => (
< tr key = {idx}>
{columns. map (( col ) => (
< td
key = {col.key}
className = {col.align === 'right' ? 'table-numeric' : col.align === 'center' ? 'table-center' : '' }
>
{row[col.key]}
</ td >
))}
</ tr >
))}
</ tbody >
</ table >
);
}
// Usage
< Table
data = {users}
columns = {[
{ key: 'name' , header: 'Name' },
{ key: 'email' , header: 'Email' },
{ key: 'count' , header: 'Count' , align: 'right' },
]}
striped
hover
/>
Vue
< template >
< table : class = " tableClasses " >
< thead >
< tr >
< th
v-for = " col in columns "
: key = " col.key "
: class = " getAlignClass (col.align) "
>
{{ col.header }}
</ th >
</ tr >
</ thead >
< tbody >
< tr v-for = " (row, idx) in data " : key = " idx " >
< td
v-for = " col in columns "
: key = " col.key "
: class = " getAlignClass (col.align) "
>
{{ row[col.key] }}
</ td >
</ tr >
</ tbody >
</ table >
</ template >
< script setup >
import { computed } from 'vue' ;
const props = defineProps ({
data: Array,
columns: Array,
striped: Boolean,
hover: Boolean,
bordered: Boolean,
});
const tableClasses = computed (() => {
return [
'table' ,
props.striped && 'table-striped' ,
props.hover && 'table-hover' ,
props.bordered && 'table-bordered' ,
]. filter (Boolean). join ( ' ' );
});
function getAlignClass ( align ) {
if (align === 'right' ) return 'table-numeric' ;
if (align === 'center' ) return 'table-center' ;
return '' ;
}
</ script >
<!-- Usage -->
< Table
: data = " users "
: columns = " columns "
striped
hover
/>
API Reference
Table Classes
Class Description .tableBase table styles (required) .table-stripedAlternate row background colors .table-borderedAdd borders to all cells .table-borderlessRemove all borders .table-hoverAdd hover effect to rows .table-compactReduce cell padding .table-comfortableIncrease cell padding .table-selectableMake rows selectable with cursor .table-stickySticky table header .table-surfaceUse surface background color .table-responsiveHorizontal scroll wrapper
Column Classes
Class Description .table-numericRight-align with tabular numbers .table-centerCenter-align content .table-checkboxCheckbox column (width: 3rem) .table-actionsActions column (right-aligned)
Row Classes
Class Description .selectedMark row as selected (use with .table-selectable)
Sort Classes
Class Description .table-sortSortable column header .table-sort-iconSort indicator icon .table-sort-ascAscending sort state .table-sort-descDescending sort state
Other Classes
Class Description .table-captionTable caption styling
Combinations
<!-- Striped table with hover and borders -->
< table class = "table table-striped table-hover table-bordered" >
<!-- ... -->
</ table >
<!-- Compact selectable table with sticky header -->
< table class = "table table-compact table-selectable table-sticky" >
<!-- ... -->
</ table >
Card - Container for tables
Badge - Status indicators in tables
Button - Action buttons in table cells
See Also