Card

A container that groups related content and actions into a box with optional header, content, and footer sections.

Loading...
<twig:Card class="w-[350px]">
    <twig:Card:Header>
        <twig:Card:Title>Card Title</twig:Card:Title>
        <twig:Card:Description>Card Description</twig:Card:Description>
    </twig:Card:Header>
    <twig:Card:Content>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos.</p>
    </twig:Card:Content>
    <twig:Card:Footer class="justify-between">
        <twig:Button variant="outline">Cancel</twig:Button>
        <twig:Button>Action</twig:Button>
    </twig:Card:Footer>
</twig:Card>

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 card --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/Card.html.twig
    {# @block content The default block #}
    <div
        class="{{ 'rounded-lg border bg-card text-card-foreground shadow-sm ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </div>
    
    templates/components/Card/Content.html.twig
    {# @block content The default block #}
    <div
        class="{{ 'p-6 pt-0 ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </div>
    
    templates/components/Card/Description.html.twig
    {# @block content The default block #}
    <div
        class="{{ 'text-sm text-muted-foreground ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </div>
    
    templates/components/Card/Footer.html.twig
    {# @block content The default block #}
    <div
        class="{{ 'flex items-center p-6 pt-0 ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </div>
    
    templates/components/Card/Header.html.twig
    {# @block content The default block #}
    <div
        class="{{ 'flex flex-col space-y-1.5 p-6 ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </div>
    
    templates/components/Card/Title.html.twig
    {# @block content The default block #}
    <div
        class="{{ 'text-2xl font-semibold leading-none tracking-tight ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </div>
    
  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

<twig:Card class="w-[350px]">
    <twig:Card:Header>
        <twig:Card:Title>Card Title</twig:Card:Title>
        <twig:Card:Description>Card Description</twig:Card:Description>
    </twig:Card:Header>
    <twig:Card:Content>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos.</p>
    </twig:Card:Content>
    <twig:Card:Footer class="justify-between">
        <twig:Button variant="outline">Cancel</twig:Button>
        <twig:Button>Action</twig:Button>
    </twig:Card:Footer>
</twig:Card>

Examples

Default

Loading...
<twig:Card class="w-[350px]">
    <twig:Card:Header>
        <twig:Card:Title>Card Title</twig:Card:Title>
        <twig:Card:Description>Card Description</twig:Card:Description>
    </twig:Card:Header>
    <twig:Card:Content>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quos.</p>
    </twig:Card:Content>
    <twig:Card:Footer class="justify-between">
        <twig:Button variant="outline">Cancel</twig:Button>
        <twig:Button>Action</twig:Button>
    </twig:Card:Footer>
</twig:Card>

With Notifications

Loading...
{% set notifications = [
  { title: "Your call has been confirmed.", description: "1 hour ago"},
  { title: "You have a new message!",  description: "1 hour ago"},
  { title: "Your subscription is expiring soon!", description: "2 hours ago" },
] %}
<twig:Card class="w-[350px]">
    <twig:Card:Header>
        <twig:Card:Title>Notifications</twig:Card:Title>
        <twig:Card:Description>You have 3 unread messages.</twig:Card:Description>
    </twig:Card:Header>
    <twig:Card:Content>
        {%- for notification in notifications -%}
            <div class="mb-4 grid grid-cols-[25px_1fr] items-start pb-4 last:mb-0 last:pb-0">
                <span class="flex h-2 w-2 translate-y-1 rounded-full bg-sky-500"></span>
                <div class="space-y-1">
                    <p class="text-sm font-medium leading-none">
                        {{ notification.title }}
                    </p>
                    <p class="text-sm text-muted-foreground">
                        {{ notification.description }}
                    </p>
                </div>
            </div>
        {%- endfor -%}
    </twig:Card:Content>
    <twig:Card:Footer>
        <twig:Button class="w-full">
            <twig:ux:icon name="lucide:check" />
            Mark all as read
        </twig:Button>
    </twig:Card:Footer>
</twig:Card>

API Reference

Card

Block Description
content The default block

Card:Content

Block Description
content The default block

Card:Description

Block Description
content The default block

Card:Footer

Block Description
content The default block

Card:Header

Block Description
content The default block

Card:Title

Block Description
content The default block