Skip to content

ToggleGroup

component

Toggles that belong together: radio buttons for one choice, checkboxes for several, submitted with the form, without JavaScript.

Preview

Light

Code
<twig:ToggleGroup name="align" label="Text alignment" value="left" variant="outline">
    <twig:ToggleGroup:Item value="left">Left</twig:ToggleGroup:Item>
    <twig:ToggleGroup:Item value="center">Centre</twig:ToggleGroup:Item>
    <twig:ToggleGroup:Item value="right">Right</twig:ToggleGroup:Item>
</twig:ToggleGroup>

Dark

Code
<twig:ToggleGroup name="align" label="Text alignment" value="left" variant="outline">
    <twig:ToggleGroup:Item value="left">Left</twig:ToggleGroup:Item>
    <twig:ToggleGroup:Item value="center">Centre</twig:ToggleGroup:Item>
    <twig:ToggleGroup:Item value="right">Right</twig:ToggleGroup:Item>
</twig:ToggleGroup>

Try it

Change the props; the example is rendered again by the server.

<twig:ToggleGroup name="align" label="Text alignment" value="left" variant="outline">
    <twig:ToggleGroup:Item value="left">Left</twig:ToggleGroup:Item>
    <twig:ToggleGroup:Item value="center">Centre</twig:ToggleGroup:Item>
    <twig:ToggleGroup:Item value="right">Right</twig:ToggleGroup:Item>
</twig:ToggleGroup>

Variants

type

Whether one toggle or several can be pressed.

type="single"
type="multiple"

variant

The visual style variant of the toggles.

variant="default"
variant="outline"

size

The size of the toggles.

size="default"
size="sm"
size="lg"

disabled

Whether every toggle is disabled.

disabled="false"
disabled="true"

Installation

php bin/console ux:install toggle-group --kit=github.com/parler-haut-interagir-librement/ux-kit

Props

PropTypeDefaultDescription
type 'single'|'multiple' 'single' Whether one toggle or several can be pressed.
value string|list<string>|null null The value or the values pressed on initial render.
variant 'default'|'outline' 'default' The visual style variant of the toggles.
size 'default'|'sm'|'lg' 'default' The size of the toggles.
disabled bool false Whether every toggle is disabled.

Accessibility

The group is named by label. With type="single", the toggles are radio buttons: one Tab reaches them and the arrows move between them. With type="multiple", they are checkboxes, each reached by Tab, their field name ending in [].

Files to copy

templates/components/ToggleGroup.html.twig
{#-
 # Toggles that belong together, on radio buttons for one choice or checkboxes for several: the browser keeps one
 # pressed at a time, moves between them with the arrows and submits them, without JavaScript.
 #}
{%- props
    ## string The name of the form field the toggles share.
    name,
    ## string What the group is about, read by screen readers.
    label,
    ## 'single'|'multiple' Whether one toggle or several can be pressed.
    type = 'single',
    ## string|list<string>|null The value or the values pressed on initial render.
    value = null,
    ## 'default'|'outline' The visual style variant of the toggles.
    variant = 'default',
    ## 'default'|'sm'|'lg' The size of the toggles.
    size = 'default',
    ## bool Whether every toggle is disabled.
    disabled = false
-%}
{%- set _multiple = type is same as('multiple') -%}
{%- do provide('toggleGroup.name', _multiple and not (name ends with '[]') ? name ~ '[]' : name) -%}
{%- do provide('toggleGroup.type', _multiple ? 'checkbox' : 'radio') -%}
{%- do provide('toggleGroup.value', value is null ? [] : (value is iterable ? value : [value])) -%}
{%- do provide('toggleGroup.disabled', disabled) -%}
{%- do provide('toggleGroup.class', 'isToggle' ~ (variant is same as('outline') ? ' isOutline' : '') ~ ({sm: ' isSmall', lg: ' isLarge'}[size] ?? '')) -%}
<div role="group" aria-label="{{ label }}" data-slot="toggle-group" data-type="{{ _multiple ? 'multiple' : 'single' }}"{{ attributes.defaults({class: 'isToggleGroup'}) }}>
{##- The toggles, each a `ToggleGroup:Item`. -#}
{%- block content %}{% endblock -%}
</div>
templates/components/ToggleGroup/Item.html.twig
{%- props
    ## string The value submitted while this toggle is pressed.
    value,
    ## bool Whether this toggle is disabled.
    disabled = false
-%}
<label data-slot="toggle-group-item"{{ attributes.defaults({class: inject('toggleGroup.class')}) }}>
<input type="{{ inject('toggleGroup.type') }}" class="isToggleInput" name="{{ inject('toggleGroup.name') }}" value="{{ value }}"{% if value in inject('toggleGroup.value') %} checked{% endif %}{% if disabled or inject('toggleGroup.disabled') %} disabled{% endif %}>
{##- The label or the icon of the toggle; an icon alone needs a visually hidden text. -#}
{%- block content %}{% endblock -%}
</label>