Table

A structured grid element that organizes data into rows and columns, supporting headers, captions, and footers.

Loading...
{%- 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" },
] -%}
<twig:Table>
    <twig:Table:Caption>A list of your recent invoices.</twig:Table:Caption>
    <twig:Table:Header>
        <twig:Table:Row>
            <twig:Table:Head class="w-[100px]">Invoice</twig:Table:Head>
            <twig:Table:Head>Status</twig:Table:Head>
            <twig:Table:Head>Method</twig:Table:Head>
            <twig:Table:Head class="text-right">Amount</twig:Table:Head>
        </twig:Table:Row>
    </twig:Table:Header>
    <twig:Table:Body>
        {% for invoice in invoices %}
            <twig:Table:Row>
                <twig:Table:Cell class="font-medium">{{ invoice.invoice }}</twig:Table:Cell>
                <twig:Table:Cell>{{ invoice.paymentStatus }}</twig:Table:Cell>
                <twig:Table:Cell>{{ invoice.paymentMethod }}</twig:Table:Cell>
                <twig:Table:Cell class="text-right">{{ invoice.totalAmount }}</twig:Table:Cell>
            </twig:Table:Row>
        {% endfor %}
    </twig:Table:Body>
    <twig:Table:Footer>
        <twig:Table:Row>
            <twig:Table:Cell colspan="3">Total</twig:Table:Cell>
            <twig:Table:Cell class="text-right">$1,500.00</twig:Table:Cell>
        </twig:Table:Row>
    </twig:Table:Footer>
</twig:Table>

Installation

Ensure the Symfony UX Toolkit is installed in your Symfony app:

$ composer require --dev symfony/ux-toolkit

Then, run the following command to install the component and its dependencies:

$ bin/console ux:install table --kit shadcn

The UX Toolkit is not mandatory to install a component. You can install it manually by following the next steps:

  1. Copy the following file(s) into your Symfony app:
    templates/components/Table.html.twig
    {# @block content The default block #}
    <div class="relative w-full overflow-auto">
        <table
            class="{{ 'w-full caption-bottom text-sm ' ~ attributes.render('class')|tailwind_merge }}"
            {{ attributes }}
        >
            {%- block content %}{% endblock -%}
        </table>
    </div>
    
    templates/components/Table/Body.html.twig
    {# @block content The default block #}
    <tbody
        class="{{ '[&_tr:last-child]:border-0 ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </tbody>
    
    templates/components/Table/Caption.html.twig
    {# @block content The default block #}
    <caption
        class="{{ 'mt-4 text-sm text-muted-foreground ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </caption>
    
    templates/components/Table/Cell.html.twig
    {# @block content The default block #}
    <td
        class="{{ 'p-4 align-middle [&:has([role=checkbox])]:pr-0 ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </td>
    
    templates/components/Table/Footer.html.twig
    {# @block content The default block #}
    <tfoot
        class="{{ 'border-t bg-muted/50 font-medium [&>tr]:last:border-b-0 ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </tfoot>
    
    templates/components/Table/Head.html.twig
    {# @block content The default block #}
    <th
        class="{{ 'h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </th>
    
    templates/components/Table/Header.html.twig
    {# @block content The default block #}
    <thead
        class="{{ '[&_tr]:border-b ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </thead>
    
    templates/components/Table/Row.html.twig
    {# @block content The default block #}
    <tr
        class="{{ 'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </tr>
    
  2. If necessary, install the following Composer dependencies:
    $ composer require tales-from-a-dev/twig-tailwind-extra:^1.0.0
  3. And the most important, enjoy!

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" },
] -%}
<twig:Table>
    <twig:Table:Caption>A list of your recent invoices.</twig:Table:Caption>
    <twig:Table:Header>
        <twig:Table:Row>
            <twig:Table:Head class="w-[100px]">Invoice</twig:Table:Head>
            <twig:Table:Head>Status</twig:Table:Head>
            <twig:Table:Head>Method</twig:Table:Head>
            <twig:Table:Head class="text-right">Amount</twig:Table:Head>
        </twig:Table:Row>
    </twig:Table:Header>
    <twig:Table:Body>
        {% for invoice in invoices %}
            <twig:Table:Row>
                <twig:Table:Cell class="font-medium">{{ invoice.invoice }}</twig:Table:Cell>
                <twig:Table:Cell>{{ invoice.paymentStatus }}</twig:Table:Cell>
                <twig:Table:Cell>{{ invoice.paymentMethod }}</twig:Table:Cell>
                <twig:Table:Cell class="text-right">{{ invoice.totalAmount }}</twig:Table:Cell>
            </twig:Table:Row>
        {% endfor %}
    </twig:Table:Body>
    <twig:Table:Footer>
        <twig:Table:Row>
            <twig:Table:Cell colspan="3">Total</twig:Table:Cell>
            <twig:Table:Cell class="text-right">$1,500.00</twig:Table:Cell>
        </twig:Table:Row>
    </twig:Table:Footer>
</twig:Table>

Examples

Basic Table

Loading...
{%- 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" },
] -%}
<twig:Table>
    <twig:Table:Caption>A list of your recent invoices.</twig:Table:Caption>
    <twig:Table:Header>
        <twig:Table:Row>
            <twig:Table:Head class="w-[100px]">Invoice</twig:Table:Head>
            <twig:Table:Head>Status</twig:Table:Head>
            <twig:Table:Head>Method</twig:Table:Head>
            <twig:Table:Head class="text-right">Amount</twig:Table:Head>
        </twig:Table:Row>
    </twig:Table:Header>
    <twig:Table:Body>
        {% for invoice in invoices %}
            <twig:Table:Row>
                <twig:Table:Cell class="font-medium">{{ invoice.invoice }}</twig:Table:Cell>
                <twig:Table:Cell>{{ invoice.paymentStatus }}</twig:Table:Cell>
                <twig:Table:Cell>{{ invoice.paymentMethod }}</twig:Table:Cell>
                <twig:Table:Cell class="text-right">{{ invoice.totalAmount }}</twig:Table:Cell>
            </twig:Table:Row>
        {% endfor %}
    </twig:Table:Body>
    <twig:Table:Footer>
        <twig:Table:Row>
            <twig:Table:Cell colspan="3">Total</twig:Table:Cell>
            <twig:Table:Cell class="text-right">$1,500.00</twig:Table:Cell>
        </twig:Table:Row>
    </twig:Table:Footer>
</twig:Table>

API Reference

Table

Block Description
content The default block

Table:Body

Block Description
content The default block

Table:Caption

Block Description
content The default block

Table:Cell

Block Description
content The default block

Table:Footer

Block Description
content The default block

Table:Head

Block Description
content The default block

Table:Header

Block Description
content The default block

Table:Row

Block Description
content The default block