Empty

Use the Empty component to display an empty state.

Loading...
<twig:Empty class="border border-dashed">
    <twig:Empty:Header>
        <twig:Empty:Media variant="icon">
            <twig:ux:icon name="tabler:cloud" class="size-5" />
        </twig:Empty:Media>
        <twig:Empty:Title>Cloud storage empty</twig:Empty:Title>
        <twig:Empty:Description>
            Upload files to your cloud storage to access them anywhere.
        </twig:Empty:Description>
    </twig:Empty:Header>
    <twig:Empty:Content>
        <twig:Button variant="outline" size="sm">
            Upload files
        </twig:Button>
    </twig:Empty:Content>
</twig:Empty>

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 empty --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/Empty.html.twig
    {# @block content The default block #}
    <div
        data-slot="empty"
        class="{{ 'flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border-dashed p-6 text-center text-balance md:p-12 ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </div>
    
    templates/components/Empty/Content.html.twig
    {# @block content The default block #}
    <div
        data-slot="empty-content"
        class="{{ 'flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </div>
    
    templates/components/Empty/Description.html.twig
    {# @block content The default block #}
    <div
        data-slot="empty-description"
        class="{{ 'text-muted-foreground [&>a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4 ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </div>
    
    templates/components/Empty/Header.html.twig
    {# @block content The default block #}
    <div
        data-slot="empty-header"
        class="{{ 'flex max-w-sm flex-col items-center gap-2 text-center ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </div>
    
    templates/components/Empty/Media.html.twig
    {# @prop variant 'default'|'icon' The variant, default to `default` #}
    {# @block content The default block #}
    {%- props variant = 'default' -%}
    {%- set style = html_cva(
        base: 'flex shrink-0 items-center justify-center mb-2 [&_svg]:pointer-events-none [&_svg]:shrink-0',
        variants: {
            variant: {
                default: 'bg-transparent',
                icon: "bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6",
            },
        },
        default_variant: {
            variant: 'default',
        },
    ) -%}
    
    <div
        data-slot="empty-icon"
        data-variant="{{ variant }}"
        class="{{ style.apply({variant: variant}, attributes.render('class'))|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </div>
    
    templates/components/Empty/Title.html.twig
    {# @block content The default block #}
    <div
        data-slot="empty-title"
        class="{{ 'text-lg font-medium tracking-tight ' ~ attributes.render('class')|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </div>
    
  2. If necessary, install the following Composer dependencies:
    $ composer require twig/extra-bundle twig/html-extra:^3.12.0 tales-from-a-dev/twig-tailwind-extra:^1.0.0
  3. And the most important, enjoy!

Usage

<twig:Empty class="border border-dashed">
    <twig:Empty:Header>
        <twig:Empty:Media variant="icon">
            <twig:ux:icon name="tabler:cloud" class="size-5" />
        </twig:Empty:Media>
        <twig:Empty:Title>Cloud storage empty</twig:Empty:Title>
        <twig:Empty:Description>
            Upload files to your cloud storage to access them anywhere.
        </twig:Empty:Description>
    </twig:Empty:Header>
    <twig:Empty:Content>
        <twig:Button variant="outline" size="sm">
            Upload files
        </twig:Button>
    </twig:Empty:Content>
</twig:Empty>

Examples

Outline

Loading...
<twig:Empty class="border border-dashed">
    <twig:Empty:Header>
        <twig:Empty:Media variant="icon">
            <twig:ux:icon name="tabler:cloud" class="size-5" />
        </twig:Empty:Media>
        <twig:Empty:Title>Cloud storage empty</twig:Empty:Title>
        <twig:Empty:Description>
            Upload files to your cloud storage to access them anywhere.
        </twig:Empty:Description>
    </twig:Empty:Header>
    <twig:Empty:Content>
        <twig:Button variant="outline" size="sm">
            Upload files
        </twig:Button>
    </twig:Empty:Content>
</twig:Empty>

Background

Loading...
<twig:Empty class="from-muted/50 to-background h-full bg-linear-to-b from-30%">
    <twig:Empty:Header>
        <twig:Empty:Media variant="icon">
            <twig:ux:icon name="lucide:bell" class="size-5" />
        </twig:Empty:Media>
        <twig:Empty:Title>No notifications</twig:Empty:Title>
        <twig:Empty:Description>
            You're all caught up. New notifications will appear here.
        </twig:Empty:Description>
    </twig:Empty:Header>
    <twig:Empty:Content>
        <twig:Button variant="outline" size="sm">
            <twig:ux:icon name="lucide:refresh-ccw" class="size-4" />
            Refresh
        </twig:Button>
    </twig:Empty:Content>
</twig:Empty>

Avatar

Loading...
<twig:Empty>
    <twig:Empty:Header>
        <twig:Empty:Media>
            <twig:Avatar class="size-12">
                <twig:Avatar:Image
                    src="https://github.com/shadcn.png"
                    alt="@shadcn"
                    class="grayscale"
                />
                <twig:Avatar:Text>LR</twig:Avatar:Text>
            </twig:Avatar>
        </twig:Empty:Media>
        <twig:Empty:Title>User offline</twig:Empty:Title>
        <twig:Empty:Description>
            This user is currently offline. You can leave a message to notify them or try again later.
        </twig:Empty:Description>
    </twig:Empty:Header>
    <twig:Empty:Content>
        <twig:Button size="sm">Leave message</twig:Button>
    </twig:Empty:Content>
</twig:Empty>

Avatar group

Loading...
<twig:Empty>
    <twig:Empty:Header>
        <twig:Empty:Media>
            <div class="*:data-[slot=avatar]:ring-background flex -space-x-2 *:data-[slot=avatar]:size-12 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:grayscale">
                <twig:Avatar>
                    <twig:Avatar:Image src="https://github.com/shadcn.png" alt="@shadcn" />
                    <twig:Avatar:Text>CN</twig:Avatar:Text>
                </twig:Avatar>
                <twig:Avatar>
                    <twig:Avatar:Image src="https://github.com/maxleiter.png" alt="@maxleiter" />
                    <twig:Avatar:Text>LR</twig:Avatar:Text>
                </twig:Avatar>
                <twig:Avatar>
                    <twig:Avatar:Image src="https://github.com/evilrabbit.png" alt="@evilrabbit" />
                    <twig:Avatar:Text>ER</twig:Avatar:Text>
                </twig:Avatar>
            </div>
        </twig:Empty:Media>
        <twig:Empty:Title>No team members</twig:Empty:Title>
        <twig:Empty:Description>
            Invite your team to collaborate on this project.
        </twig:Empty:Description>
    </twig:Empty:Header>
    <twig:Empty:Content>
        <twig:Button size="sm">
            <twig:ux:icon name="lucide:plus" class="size-4" />
            Invite members
        </twig:Button>
    </twig:Empty:Content>
</twig:Empty>

API Reference

Empty

Block Description
content The default block

Empty:Content

Block Description
content The default block

Empty:Description

Block Description
content The default block

Empty:Header

Block Description
content The default block

Empty:Media

Prop Type Description
variant 'default'|'icon' The variant, default to default
Block Description
content The default block

Empty:Title

Block Description
content The default block