Table

A responsive table component.

A list of your recent invoices.
Invoice Status Method Amount
INV001 Paid Credit Card $250.00
INV002 Pending PayPal $150.00
INV003 Unpaid Bank Transfer $350.00
INV004 Paid Credit Card $450.00
INV005 Paid PayPal $550.00
INV006 Pending Bank Transfer $200.00
INV007 Unpaid Credit Card $300.00
Total $2,500.00
{% set 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",
    },
] %}
<div class="w-full p-10">
  <Table>
    <TableCaption>A list of your recent invoices.</TableCaption>
    <TableHeader>
      <TableRow>
        <TableHead className="w-[100px]">Invoice</TableHead>
        <TableHead>Status</TableHead>
        <TableHead>Method</TableHead>
        <TableHead className="text-right p-4">Amount</TableHead>
      </TableRow>
    </TableHeader>
    <TableBody>
      {% for invoice in invoices %}
        <TableRow id={{ invoice.invoice }}>
          <TableCell className="font-medium">{{ invoice.invoice }}</TableCell>
          <TableCell>{{ invoice.paymentStatus }}</TableCell>
          <TableCell>{{ invoice.paymentMethod }}</TableCell>
          <TableCell className="text-right">{{ invoice.totalAmount }}</TableCell>
        </TableRow>
      {% endfor %}
    </TableBody>
    <TableFooter>
      <TableRow>
        <TableCell colSpan="3">Total</TableCell>
        <TableCell className="text-right">$2,500.00</TableCell>
      </TableRow>
    </TableFooter>
  </Table>
</div>

Installation

uvx --from basic-components components add table
pipx run --spec basic-components components add table
pip install basic-components && components add table
  • Copy Table components below to your local environment
  • Place them in the components/ui/table directory in your project
  • Configure your jinja environment for JinjaX
  • Add the cn() helper function to your global jinja environment

Usage

{% set 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",
    },
] %}
<div class="w-full p-10">
  <Table>
    <TableCaption>A list of your recent invoices.</TableCaption>
    <TableHeader>
      <TableRow>
        <TableHead className="w-[100px]">Invoice</TableHead>
        <TableHead>Status</TableHead>
        <TableHead>Method</TableHead>
        <TableHead className="text-right p-4">Amount</TableHead>
      </TableRow>
    </TableHeader>
    <TableBody>
      {% for invoice in invoices %}
        <TableRow id={{ invoice.invoice }}>
          <TableCell className="font-medium">{{ invoice.invoice }}</TableCell>
          <TableCell>{{ invoice.paymentStatus }}</TableCell>
          <TableCell>{{ invoice.paymentMethod }}</TableCell>
          <TableCell className="text-right">{{ invoice.totalAmount }}</TableCell>
        </TableRow>
      {% endfor %}
    </TableBody>
    <TableFooter>
      <TableRow>
        <TableCell colSpan="3">Total</TableCell>
        <TableCell className="text-right">$2,500.00</TableCell>
      </TableRow>
    </TableFooter>
  </Table>
</div>

Attributes

Component Prop Type Default Description
TableHead sortable bool False Displays and indicator if table is sortable by this colum.
TableHead ascending bool True True if the order is ascending.

Code

{#def
    className: str = ""
#}
<div class="relative w-full overflow-visible">
  <table class="{{ className }} w-full caption-bottom text-sm" {{ attrs.render() }}>
    {{ content }}
  </table>
</div>
{#def
    className: str = ""
#}
<tbody class="{{ className }} [&_tr:last-child]:border-0" {{ attrs.render() }}>{{ content }}</tbody>
{#def
  className: str = ""
#}
<caption class="{{ className }} mt-4 text-sm text-zinc-500 dark:text-zinc-400" {{ attrs.render() }}>
  {{ content }}
</caption>
{#def
    className: str = ""
#}
<td class="p-4 align-middle [&:has([role=checkbox])]:pr-0 {{ className }} "
    {{ attrs.render() }}>
  {{ content }}
</td>
{#def
  className: str = ""
#}
<tfoot
    class="{{ className }} border-t border-zinc-200 bg-zinc-100/50 font-medium dark:border-zinc-700 dark:bg-zinc-800/50"
    {{ attrs.render() }}
>
{{ content }}
</tfoot>
{# def
  className: str = "",
  sortable = False,
  sorted = False,
  ascending = False,
#}
<th
    class="h-12 pl-4 text-left align-middle font-medium text-zinc-500 dark:text-zinc-400 {{ className }}"
    sorted="{{ sorted }}"
    {{ attrs.render() }}
>
  {{ content }}
  {%- if sorted -%}
    <span
        class="inline-flex {% if sorted %}opacity-100{% else %}opacity-25{% endif %} ml-2 flex-none rounded text-zinc-800 dark:text-zinc-200 group-hover:visible group-focus:visible"
    >
      {% if ascending is true %}
        <ChevronUpIcon className="h-4 w-4" />
      {% else %}
        <ChevronDownIcon className="h-4 w-4" />
      {% endif %}
    </span>
  {%- elif sortable -%}
    <span
        class="inline-flex opacity-25 ml-2 flex-none rounded text-zinc-800 dark:text-zinc-200 group-hover:visible group-focus:visible"
    >
        <ChevronsUpDownIcon className="h-4 w-4" />
    </span>
  {%- endif -%}
</th>
{#def
    className: str = ""
#}
<thead class="{{ className }} [&_tr]:border-b" {{ attrs.render() }}>{{ content }}</thead>
{#def
    className: str = ""
#}
<tr
    class="{{ className }} border-b border-zinc-200 transition-colors hover:bg-zinc-100/50 data-[state=selected]:bg-zinc-100 dark:border-zinc-700 dark:hover:bg-zinc-800/50 dark:data-[state=selected]:bg-zinc-800"
    {{ attrs.render() }}
>
  {{ content }}
</tr>