Button Group
A layout helper for grouping buttons and related controls with shared borders and separators.
Loading...
<twig:ButtonGroup> <twig:ButtonGroup class="hidden sm:flex"> <twig:Button variant="outline" size="icon" aria-label="Go back"> <twig:ux:icon name="lucide:arrow-left" class="size-4" /> </twig:Button> </twig:ButtonGroup> <twig:ButtonGroup> <twig:Button variant="outline">Archive</twig:Button> <twig:Button variant="outline">Report</twig:Button> </twig:ButtonGroup> <twig:ButtonGroup> <twig:Button variant="outline"> <twig:ux:icon name="lucide:clock" class="size-4" /> Snooze </twig:Button> <twig:Button variant="outline" size="icon" aria-label="More options"> <twig:ux:icon name="lucide:more-horizontal" class="size-4" /> </twig:Button> </twig:ButtonGroup> </twig:ButtonGroup>
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 button-group --kit shadcn
The UX Toolkit is not mandatory to install a component. You can install it manually by following the next steps:
- Copy the following file(s) into your Symfony app:
templates/components/ButtonGroup.html.twig{# @prop orientation 'horizontal'|'vertical' The orientation, default to `horizontal` #} {# @block content The default block #} {%- props orientation = 'horizontal' -%} {%- set style = html_cva( base: 'flex w-fit items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=select-trigger]:not([class*=\'w-\'])]:w-fit [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2', variants: { orientation: { horizontal: '[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none', vertical: 'flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none', }, }, default_variant: { orientation: 'horizontal', }, ) -%} <div role="group" data-slot="button-group" data-orientation="{{ orientation }}" class="{{ style.apply({orientation: orientation}, attributes.render('class'))|tailwind_merge }}" {{ attributes }} > {%- block content %}{% endblock -%} </div>
templates/components/ButtonGroup/Separator.html.twig{# @prop orientation 'horizontal'|'vertical' The orientation of the separator, default to `vertical` #} {# @block content The default block #} {%- props orientation = 'vertical' -%} <twig:Separator orientation="{{ orientation }}" data-slot="button-group-separator" class="bg-input relative m-0! self-stretch {{ orientation == 'vertical' ? 'h-auto' }} {{ attributes.render('class')|tailwind_merge }}" {{ ...attributes }} />
templates/components/ButtonGroup/Text.html.twig{# @prop as 'div' The HTML tag to use, default to `div` #} {# @block content The default block #} {%- props as = 'div' -%} <{{ as }} data-slot="button-group-text" class="{{ 'bg-muted flex items-center gap-2 rounded-md border px-4 text-sm font-medium shadow-xs [&_svg]:pointer-events-none [&_svg:not([class*=\'size-\'])]:size-4 ' ~ attributes.render('class')|tailwind_merge }}" {{ attributes }} > {%- block content %}{% endblock -%} </{{ as }}>
templates/components/Separator.html.twig{# @prop orientation 'horizontal'|'vertical' The orientation of the separator, default to `horizontal` #} {# @prop decorative boolean Whether the separator is decorative or not, default to `true` #} {%- props orientation = 'horizontal', decorative = true -%} {%- set style = html_cva( base: 'shrink-0 bg-border', variants: { orientation: { horizontal: 'h-[1px] w-full', vertical: 'h-full w-[1px]', }, }, ) -%} <div class="{{ style.apply({orientation: orientation, decorative: decorative}, attributes.render('class'))|tailwind_merge }}" {{ attributes.defaults({ role: decorative ? 'none' : 'separator', 'aria-orientation': decorative ? false : orientation, }) }} ></div>
- 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
- And the most important, enjoy!
Usage
<twig:ButtonGroup> <twig:ButtonGroup class="hidden sm:flex"> <twig:Button variant="outline" size="icon" aria-label="Go back"> <twig:ux:icon name="lucide:arrow-left" class="size-4" /> </twig:Button> </twig:ButtonGroup> <twig:ButtonGroup> <twig:Button variant="outline">Archive</twig:Button> <twig:Button variant="outline">Report</twig:Button> </twig:ButtonGroup> <twig:ButtonGroup> <twig:Button variant="outline"> <twig:ux:icon name="lucide:clock" class="size-4" /> Snooze </twig:Button> <twig:Button variant="outline" size="icon" aria-label="More options"> <twig:ux:icon name="lucide:more-horizontal" class="size-4" /> </twig:Button> </twig:ButtonGroup> </twig:ButtonGroup>
Examples
Default
Loading...
<twig:ButtonGroup> <twig:ButtonGroup class="hidden sm:flex"> <twig:Button variant="outline" size="icon" aria-label="Go back"> <twig:ux:icon name="lucide:arrow-left" class="size-4" /> </twig:Button> </twig:ButtonGroup> <twig:ButtonGroup> <twig:Button variant="outline">Archive</twig:Button> <twig:Button variant="outline">Report</twig:Button> </twig:ButtonGroup> <twig:ButtonGroup> <twig:Button variant="outline"> <twig:ux:icon name="lucide:clock" class="size-4" /> Snooze </twig:Button> <twig:Button variant="outline" size="icon" aria-label="More options"> <twig:ux:icon name="lucide:more-horizontal" class="size-4" /> </twig:Button> </twig:ButtonGroup> </twig:ButtonGroup>
Orientation
Loading...
<twig:ButtonGroup orientation="vertical" aria-label="Media controls" class="h-fit"> <twig:Button variant="outline" size="icon"> <twig:ux:icon name="lucide:plus" class="size-4" /> </twig:Button> <twig:Button variant="outline" size="icon"> <twig:ux:icon name="lucide:minus" class="size-4" /> </twig:Button> </twig:ButtonGroup>
Size
Loading...
<div class="flex flex-col items-start gap-8"> <twig:ButtonGroup> <twig:Button variant="outline" size="sm">Small</twig:Button> <twig:Button variant="outline" size="sm">Button</twig:Button> <twig:Button variant="outline" size="sm">Group</twig:Button> <twig:Button variant="outline" size="icon-sm"> <twig:ux:icon name="lucide:plus" class="size-4" /> </twig:Button> </twig:ButtonGroup> <twig:ButtonGroup> <twig:Button variant="outline">Default</twig:Button> <twig:Button variant="outline">Button</twig:Button> <twig:Button variant="outline">Group</twig:Button> <twig:Button variant="outline" size="icon"> <twig:ux:icon name="lucide:plus" class="size-4" /> </twig:Button> </twig:ButtonGroup> <twig:ButtonGroup> <twig:Button variant="outline" size="lg">Large</twig:Button> <twig:Button variant="outline" size="lg">Button</twig:Button> <twig:Button variant="outline" size="lg">Group</twig:Button> <twig:Button variant="outline" size="icon-lg"> <twig:ux:icon name="lucide:plus" class="size-5" /> </twig:Button> </twig:ButtonGroup> </div>
Input
Loading...
<twig:ButtonGroup class="max-w-md"> <twig:Input placeholder="Search..." /> <twig:Button size="icon-lg" variant="outline" aria-label="Search"> <twig:ux:icon name="lucide:search" class="size-4" /> </twig:Button> </twig:ButtonGroup>
Nested
Loading...
<twig:ButtonGroup> <twig:ButtonGroup> <twig:Button variant="outline" size="sm">1</twig:Button> <twig:Button variant="outline" size="sm">2</twig:Button> <twig:Button variant="outline" size="sm">3</twig:Button> <twig:Button variant="outline" size="sm">4</twig:Button> <twig:Button variant="outline" size="sm">5</twig:Button> </twig:ButtonGroup> <twig:ButtonGroup> <twig:Button variant="outline" size="icon-sm" aria-label="Previous"> <twig:ux:icon name="lucide:arrow-left" class="size-4" /> </twig:Button> <twig:Button variant="outline" size="icon-sm" aria-label="Next"> <twig:ux:icon name="lucide:arrow-right" class="size-4" /> </twig:Button> </twig:ButtonGroup> </twig:ButtonGroup>
Separator
Loading...
<twig:ButtonGroup> <twig:Button variant="secondary" size="sm">Copy</twig:Button> <twig:ButtonGroup:Separator /> <twig:Button variant="secondary" size="sm">Paste</twig:Button> </twig:ButtonGroup>
Split
Loading...
<twig:ButtonGroup> <twig:Button variant="secondary">Button</twig:Button> <twig:ButtonGroup:Separator /> <twig:Button size="icon" variant="secondary"> <twig:ux:icon name="tabler:plus" class="size-4" /> </twig:Button> </twig:ButtonGroup>
API Reference
ButtonGroup
| Prop | Type | Description |
|---|---|---|
orientation |
'horizontal'|'vertical' |
The orientation, default to horizontal |
| Block | Description |
|---|---|
content |
The default block |
ButtonGroup:Separator
| Prop | Type | Description |
|---|---|---|
orientation |
'horizontal'|'vertical' |
The orientation of the separator, default to vertical |
| Block | Description |
|---|---|
content |
The default block |
ButtonGroup:Text
| Prop | Type | Description |
|---|---|---|
as |
'div' |
The HTML tag to use, default to div |
| Block | Description |
|---|---|
content |
The default block |