UnifiedTable
Alternative unified table implementation with a simplified feature set.
Overview
UnifiedTable is a lighter-weight alternative to DocBitsTable. It provides core table functionality with a simpler API for cases where you don't need all features.
Best for: Simpler tables with lighter bundle size
Key Features:
- ✅ Sorting
- ✅ Pagination
- ✅ Row selection
- ✅ Dark mode support
- ✅ Simplified API
Comparison with DocBitsTable
| Feature | DocBitsTable | UnifiedTable |
|---|---|---|
| Sorting | ✅ | ✅ |
| Pagination | ✅ | ✅ |
| Row Selection | ✅ | ✅ |
| Filtering | ✅ | - |
| Bulk Actions | ✅ | - |
| Row Actions | ✅ | - |
| Column Resizing | ✅ | - |
| Dark Mode | ✅ | ✅ |
| Accessibility | ✅ | ✅ |
When to use UnifiedTable:
- Simpler data tables
- Lighter bundle size is critical
- Don't need bulk operations
- Don't need column resizing
When to use DocBitsTable:
- Full-featured tables
- Complex interactions
- Bulk operations needed
- Maximum flexibility
Props
Same as DocBitsTable but with fewer features available.
Basic Usage
<template>
<UnifiedTable
:rows="documents"
:columns="columns"
row-key="id"
:features="{
sorting: true,
selection: true,
pagination: true
}"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import UnifiedTable from '@/components/Table/UnifiedTable.vue'
const columns = [
{ name: 'id', label: 'ID', field: 'id', sortable: true },
{ name: 'name', label: 'Name', field: 'name', sortable: true },
{ name: 'status', label: 'Status', field: 'status' }
]
const documents = ref([
{ id: 1, name: 'Document 1', status: 'Active' },
{ id: 2, name: 'Document 2', status: 'Archived' }
])
</script>Real-World Example: Simple Invoice Table
This example demonstrates UnifiedTable with realistic invoice data, showing core features like sorting, pagination, and selection without advanced features.
Implementation
<template>
<div class="invoice-table-container">
<div class="table-controls">
<h2>Invoices</h2>
<div class="control-actions">
<button v-if="selectedRows.size > 0" class="btn export" @click="exportSelected">
Export ({{ selectedRows.size }} selected)
</button>
</div>
</div>
<UnifiedTable
:rows="invoices"
:columns="columns"
row-key="id"
:page-size="5"
:features="{
sorting: true,
selection: true,
pagination: true
}"
@row-click="handleRowClick"
@selection-change="handleSelectionChange"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import UnifiedTable from '@/components/Table/UnifiedTable.vue'
interface Invoice {
id: string
documentNumber: string
vendor: string
amount: number
currency: string
invoiceDate: string
status: 'pending' | 'approved' | 'processed'
}
const columns = [
{ name: 'documentNumber', label: 'Invoice #', field: 'documentNumber', sortable: true },
{ name: 'vendor', label: 'Vendor', field: 'vendor', sortable: true },
{ name: 'amount', label: 'Amount', field: 'amount', sortable: true, align: 'right',
format: (val: number, row: Invoice) => `${row.currency} ${val.toFixed(2)}` },
{ name: 'invoiceDate', label: 'Date', field: 'invoiceDate', sortable: true,
format: (val: string) => new Date(val).toLocaleDateString() },
{ name: 'status', label: 'Status', field: 'status', sortable: true,
format: (val: string) => val.charAt(0).toUpperCase() + val.slice(1) }
]
const invoices = ref<Invoice[]>([
{
id: 'INV-2024-001',
documentNumber: 'INV-001234',
vendor: 'Acme Corporation',
amount: 1250.00,
currency: 'USD',
invoiceDate: '2024-01-15',
status: 'pending'
},
{
id: 'INV-2024-002',
documentNumber: 'INV-001235',
vendor: 'Global Supplies Inc',
amount: 3750.50,
currency: 'USD',
invoiceDate: '2024-01-16',
status: 'pending'
},
{
id: 'INV-2024-003',
documentNumber: 'RE-2024-789',
vendor: 'Tech Solutions GmbH',
amount: 2100.00,
currency: 'EUR',
invoiceDate: '2024-01-18',
status: 'approved'
},
{
id: 'INV-2024-004',
documentNumber: 'INV-UK-445',
vendor: 'British Office Ltd',
amount: 890.00,
currency: 'GBP',
invoiceDate: '2024-01-20',
status: 'pending'
},
{
id: 'INV-2024-005',
documentNumber: 'F-2024-1122',
vendor: 'Consulting Partners SA',
amount: 8500.00,
currency: 'EUR',
invoiceDate: '2024-01-22',
status: 'processed'
},
{
id: 'INV-2024-006',
documentNumber: 'INV-2024-556',
vendor: 'Cloud Services Corp',
amount: 4200.00,
currency: 'USD',
invoiceDate: '2024-01-25',
status: 'approved'
},
{
id: 'INV-2024-007',
documentNumber: 'BILL-7788',
vendor: 'Utilities Company',
amount: 650.25,
currency: 'USD',
invoiceDate: '2024-01-28',
status: 'processed'
},
{
id: 'INV-2024-008',
documentNumber: 'INV-Q1-2024',
vendor: 'Marketing Agency LLC',
amount: 12000.00,
currency: 'USD',
invoiceDate: '2024-01-30',
status: 'pending'
}
]
const selectedRows = ref(new Set<string>())
function handleRowClick(row: Invoice) {
console.log('Clicked row:', row)
}
function handleSelectionChange(selected: string[]) {
selectedRows.value = new Set(selected)
}
function exportSelected() {
const selected = Array.from(selectedRows.value)
const data = invoices.value.filter(inv => selected.includes(inv.id))
const csv = [
['Invoice #', 'Vendor', 'Amount', 'Date', 'Status'],
...data.map(inv => [
inv.documentNumber,
inv.vendor,
`${inv.currency} ${inv.amount.toFixed(2)}`,
new Date(inv.invoiceDate).toLocaleDateString(),
inv.status
])
]
.map(row => row.join(','))
.join('\n')
const blob = new Blob([csv], { type: 'text/csv' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = 'invoices.csv'
a.click()
URL.revokeObjectURL(url)
}
</script>
<style scoped>
.invoice-table-container {
background: white;
border-radius: 8px;
overflow: hidden;
border: 1px solid #e0e0e0;
}
.table-controls {
padding: 20px;
border-bottom: 1px solid #e0e0e0;
display: flex;
justify-content: space-between;
align-items: center;
}
.table-controls h2 {
margin: 0;
font-size: 1.25em;
}
.control-actions {
display: flex;
gap: 8px;
}
.btn {
padding: 8px 16px;
background: #2388AE;
color: white;
border: none;
border-radius: 4px;
font-weight: 600;
cursor: pointer;
transition: background 0.2s;
}
.btn:hover {
background: #1a6a8a;
}
.btn.export {
background: #34eea9;
}
.btn.export:hover {
background: #2dd897;
}
</style>What This Example Shows
- Simple Feature Set: Only sorting, pagination, and selection - no bulk actions or row actions
- Pagination: Built-in pagination with 5 rows per page
- Sorting: Click column headers to sort by vendor, amount, or date
- Selection: Select multiple invoices to export as CSV
- Formatting: Currency formatting and date localization for different locales
- Realistic Data: Multiple vendors, currencies (USD, EUR, GBP), and statuses
- Export Functionality: Export selected invoices as CSV file
- Lighter Weight: Simpler implementation perfect for straightforward data display use cases
Features Demonstrated
| Feature | Status | Description |
|---|---|---|
| Sorting | ✅ | Sort invoices by any column |
| Pagination | ✅ | Display 5 rows per page with navigation |
| Row Selection | ✅ | Select multiple rows, export selected |
| Data Formatting | ✅ | Currency formatting with amounts |
| Status Display | ✅ | Pending, approved, processed states |
| Bulk Actions | - | Not supported in UnifiedTable |
| Row Actions | - | Not supported in UnifiedTable |
When to Use UnifiedTable vs DocBitsTable
Choose UnifiedTable for:
- Simple read-only data display
- Need to minimize bundle size
- Only need basic sorting and pagination
- No bulk operations required
Choose DocBitsTable for:
- Need bulk operations (approve multiple, export batch)
- Need per-row actions (view details, delete)
- Need filtering and advanced searching
- Need maximum flexibility and features
Performance
Slightly faster than DocBitsTable due to simpler implementation:
- Smaller component size
- Fewer features to manage
- Faster initial render
Bundle Size
- UnifiedTable: ~15KB (minified)
- DocBitsTable: ~20KB (minified)
Migration from UnifiedTable to DocBitsTable
If you outgrow UnifiedTable, migrating to DocBitsTable is straightforward:
- Replace component import
- Add additional features to
featuresobject - Handle new events if using bulk actions or row actions
<!-- Before: UnifiedTable -->
<UnifiedTable
:rows="documents"
:columns="columns"
:features="{ sorting: true, pagination: true }"
/>
<!-- After: DocBitsTable with all features -->
<DocBitsTable
:rows="documents"
:columns="columns"
:features="{
sorting: true,
pagination: true,
selection: true,
bulkActions: true,
rowActions: true
}"
@bulk-action="handleBulkAction"
@row-action="handleRowAction"
/>Browser Support
Supported in all modern browsers:
- Chrome 88+
- Firefox 78+
- Safari 14+
- Edge 88+
Related Components
- DocBitsTable - Full-featured alternative
Source Code
- Component:
src/components/Table/UnifiedTable.vue(656 lines)
Changelog
v1.0.0 (2025-12-18)
- Initial release
- Simplified table implementation
- Core features only
- Lighter bundle size