Docs
Table
Table
A responsive table component.
Loading...
Loading...
import {
UbTableBodyDirective,
UbTableCaptionDirective,
UbTableCellDirective,
UbTableDirective,
UbTableFooterDirective,
UbTableHeadDirective,
UbTableHeaderDirective,
UbTableRowDirective,
} from '@/components/ui/table'
import { Component } from '@angular/core'
@Component({
standalone: true,
selector: 'table-demo-new-york',
imports: [
UbTableDirective,
UbTableCaptionDirective,
UbTableHeaderDirective,
UbTableRowDirective,
UbTableHeadDirective,
UbTableBodyDirective,
UbTableCellDirective,
UbTableFooterDirective,
],
template: `
<table ubTable>
<caption ubTableCaption>
A list of your recent invoices.
</caption>
<thead ubTableHeader>
<tr ubTableRow>
<th ubTableHead class="w-[100px]">Invoice</th>
<th ubTableHead>Status</th>
<th ubTableHead>Method</th>
<th ubTableHead class="text-right">Amount</th>
</tr>
</thead>
<tbody ubTableBody>
@for (invoice of invoices; track $index) {
<tr ubTableRow>
<td ubTableCell class="font-medium">
{{ invoice.invoice }}
</td>
<td ubTableCell>
{{ invoice.paymentStatus }}
</td>
<td ubTableCell>
{{ invoice.paymentMethod }}
</td>
<td ubTableCell class="text-right">
{{ invoice.totalAmount }}
</td>
</tr>
}
</tbody>
<tfoot ubTableFooter>
<tr ubTableRow>
<td ubTableCell colspan="3">Total</td>
<td ubTableCell class="text-right">$2,500.00</td>
</tr>
</tfoot>
</table>
`,
})
export class TableDemoNewYork {
invoices = [
{
invoice: 'INV001',
paymentStatus: 'Paid',
totalAmount: '$250.00',
paymentMethod: 'Credit Card',
},
{
invoice: 'INV002',
paymentStatus: 'Pending',
totalAmount: '$150.00',
paymentMethod: 'PayPal',
},
{
invoice: 'INV003',
paymentStatus: 'Unpaid',
totalAmount: '$350.00',
paymentMethod: 'Bank Transfer',
},
{
invoice: 'INV004',
paymentStatus: 'Paid',
totalAmount: '$450.00',
paymentMethod: 'Credit Card',
},
{
invoice: 'INV005',
paymentStatus: 'Paid',
totalAmount: '$550.00',
paymentMethod: 'PayPal',
},
{
invoice: 'INV006',
paymentStatus: 'Pending',
totalAmount: '$200.00',
paymentMethod: 'Bank Transfer',
},
{
invoice: 'INV007',
paymentStatus: 'Unpaid',
totalAmount: '$300.00',
paymentMethod: 'Credit Card',
},
]
}
import {
UbTableBodyDirective,
UbTableCaptionDirective,
UbTableCellDirective,
UbTableDirective,
UbTableFooterDirective,
UbTableHeadDirective,
UbTableHeaderDirective,
UbTableRowDirective,
} from '@/components/ui/table'
import { Component } from '@angular/core'
@Component({
standalone: true,
selector: 'table-demo-default',
imports: [
UbTableDirective,
UbTableCaptionDirective,
UbTableHeaderDirective,
UbTableRowDirective,
UbTableHeadDirective,
UbTableBodyDirective,
UbTableCellDirective,
UbTableFooterDirective,
],
template: `
<table ubTable>
<caption ubTableCaption>
A list of your recent invoices.
</caption>
<thead ubTableHeader>
<tr ubTableRow>
<th ubTableHead class="w-[100px]">Invoice</th>
<th ubTableHead>Status</th>
<th ubTableHead>Method</th>
<th ubTableHead class="text-right">Amount</th>
</tr>
</thead>
<tbody ubTableBody>
@for (invoice of invoices; track $index) {
<tr ubTableRow>
<td ubTableCell class="font-medium">
{{ invoice.invoice }}
</td>
<td ubTableCell>
{{ invoice.paymentStatus }}
</td>
<td ubTableCell>
{{ invoice.paymentMethod }}
</td>
<td ubTableCell class="text-right">
{{ invoice.totalAmount }}
</td>
</tr>
}
</tbody>
<tfoot ubTableFooter>
<tr ubTableRow>
<td ubTableCell colspan="3">Total</td>
<td ubTableCell class="text-right">$2,500.00</td>
</tr>
</tfoot>
</table>
`,
})
export class TableDemoDefault {
invoices = [
{
invoice: 'INV001',
paymentStatus: 'Paid',
totalAmount: '$250.00',
paymentMethod: 'Credit Card',
},
{
invoice: 'INV002',
paymentStatus: 'Pending',
totalAmount: '$150.00',
paymentMethod: 'PayPal',
},
{
invoice: 'INV003',
paymentStatus: 'Unpaid',
totalAmount: '$350.00',
paymentMethod: 'Bank Transfer',
},
{
invoice: 'INV004',
paymentStatus: 'Paid',
totalAmount: '$450.00',
paymentMethod: 'Credit Card',
},
{
invoice: 'INV005',
paymentStatus: 'Paid',
totalAmount: '$550.00',
paymentMethod: 'PayPal',
},
{
invoice: 'INV006',
paymentStatus: 'Pending',
totalAmount: '$200.00',
paymentMethod: 'Bank Transfer',
},
{
invoice: 'INV007',
paymentStatus: 'Unpaid',
totalAmount: '$300.00',
paymentMethod: 'Credit Card',
},
]
}
Installation
npx shadcn-ng@latest add table
npm
yarn
pnpm
bun
Copy and paste the following code into your project.
import { cn } from '@/lib/utils'
import { computed, Directive, input } from '@angular/core'
@Directive({
selector: 'table[ubTable]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableDirective {
readonly class = input<string>('')
protected computedClass = computed(() =>
cn('w-full caption-bottom text-sm', this.class()),
)
}
@Directive({
selector: 'thead[ubTableHeader]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableHeaderDirective {
readonly class = input<string>('')
protected computedClass = computed(() => cn('[&_tr]:border-b', this.class()))
}
@Directive({
selector: 'tbody[ubTableBody]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableBodyDirective {
readonly class = input<string>('')
protected computedClass = computed(() =>
cn('[&_tr:last-child]:border-0', this.class()),
)
}
@Directive({
selector: 'tfoot[ubTableFooter]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableFooterDirective {
readonly class = input<string>('')
protected computedClass = computed(() =>
cn('border-t bg-muted/50 font-medium [&>tr]:last:border-b-0', this.class()),
)
}
@Directive({
selector: 'tr[ubTableRow]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableRowDirective {
readonly class = input<string>('')
protected computedClass = computed(() =>
cn(
'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',
this.class(),
),
)
}
@Directive({
selector: 'th[ubTableHead]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableHeadDirective {
readonly class = input<string>('')
protected computedClass = computed(() =>
cn(
'h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
this.class(),
),
)
}
@Directive({
selector: 'td[ubTableCell]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableCellDirective {
readonly class = input<string>('')
protected computedClass = computed(() =>
cn(
'p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
this.class(),
),
)
}
@Directive({
selector: 'caption[ubTableCaption]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableCaptionDirective {
readonly class = input<string>('')
protected computedClass = computed(() =>
cn('mt-4 text-sm text-muted-foreground', this.class()),
)
}
import { cn } from '@/lib/utils'
import { computed, Directive, input } from '@angular/core'
@Directive({
selector: 'table[ubTable]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableDirective {
readonly class = input<string>('')
protected computedClass = computed(() =>
cn('w-full caption-bottom text-sm', this.class()),
)
}
@Directive({
selector: 'thead[ubTableHeader]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableHeaderDirective {
readonly class = input<string>('')
protected computedClass = computed(() => cn('[&_tr]:border-b', this.class()))
}
@Directive({
selector: 'tbody[ubTableBody]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableBodyDirective {
readonly class = input<string>('')
protected computedClass = computed(() =>
cn('[&_tr:last-child]:border-0', this.class()),
)
}
@Directive({
selector: 'tfoot[ubTableFooter]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableFooterDirective {
readonly class = input<string>('')
protected computedClass = computed(() =>
cn('border-t bg-muted/50 font-medium [&>tr]:last:border-b-0', this.class()),
)
}
@Directive({
selector: 'tr[ubTableRow]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableRowDirective {
readonly class = input<string>('')
protected computedClass = computed(() =>
cn(
'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',
this.class(),
),
)
}
@Directive({
selector: 'th[ubTableHead]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableHeadDirective {
readonly class = input<string>('')
protected computedClass = computed(() =>
cn(
'h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0',
this.class(),
),
)
}
@Directive({
selector: 'td[ubTableCell]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableCellDirective {
readonly class = input<string>('')
protected computedClass = computed(() =>
cn('p-4 align-middle [&:has([role=checkbox])]:pr-0', this.class()),
)
}
@Directive({
selector: 'caption[ubTableCaption]',
standalone: true,
host: {
'[class]': 'computedClass()',
},
})
export class UbTableCaptionDirective {
readonly class = input<string>('')
protected computedClass = computed(() =>
cn('mt-4 text-sm text-muted-foreground', this.class()),
)
}
Update the import paths to match your project setup.
Usage
import {
UbTableDirective,
UbTableCaptionDirective,
UbTableHeaderDirective,
UbTableRowDirective,
UbTableHeadDirective,
UbTableBodyDirective,
UbTableCellDirective,
} from "@/components/ui/table.directive";
<table ubTable>
<caption ubTableCaption>A list of your recent invoices.</caption>
<thead ubTableHeader>
<tr ubTableRow>
<th ubTableHead class="w-[100px]">Invoice</th>
<th ubTableHead>Status</th>
<th ubTableHead>Method</th>
<th ubTableHead class="text-right">Amount</th>
</tr>
</thead>
<tbody ubTableBody>
<tr ubTableRow>
<td ubTableCell class="font-medium">INV001</td>
<td ubTableCell>Paid</td>
<td ubTableCell>Credit Card</td>
<td ubTableCell class="text-right">$250.00</td>
</tr>
</tbody>
</table>