View as Markdown

Native Select

A styled native HTML select element with consistent design system integration.

100%
Loading...
<twig:NativeSelect>
    <twig:NativeSelect:Option value="">Select status</twig:NativeSelect:Option>
    <twig:NativeSelect:Option value="todo">Todo</twig:NativeSelect:Option>
    <twig:NativeSelect:Option value="in-progress">In Progress</twig:NativeSelect:Option>
    <twig:NativeSelect:Option value="done">Done</twig:NativeSelect:Option>
    <twig:NativeSelect:Option value="cancelled">Cancelled</twig:NativeSelect:Option>
</twig:NativeSelect>

Installation

php bin/console ux:install native-select --kit shadcn

Install the following Composer dependencies:

composer require symfony/ux-icons tales-from-a-dev/twig-tailwind-extra:^1.0.0

Copy the following file(s) into your app:

templates/components/NativeSelect.html.twig
{# @prop size 'default'|'sm' The select size. #}
{# @block content The select options, typically `NativeSelect:Option` and `NativeSelect:OptGroup` components. #}
{%- props size = 'default' -%}
<div
    data-slot="native-select-wrapper"
    data-size="{{ size }}"
    class="{{ ('group/native-select relative w-fit has-[select:disabled]:opacity-50 ' ~ attributes.render('class'))|tailwind_merge }}"
>
    <select
        data-slot="native-select"
        data-size="{{ size }}"
        class="h-9 w-full min-w-0 appearance-none rounded-md border border-input bg-transparent px-3 py-2 pe-9 text-sm shadow-xs transition-[color,box-shadow] outline-none select-none selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/40 data-[size=sm]:h-8 data-[size=sm]:py-1 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 dark:[color-scheme:dark] [&_option]:bg-background [&_option]:text-foreground [&_optgroup]:bg-background [&_optgroup]:text-foreground"
        {{ attributes.without('class') }}
    >
        {%- block content %}{% endblock -%}
    </select>
    <twig:ux:icon name="lucide:chevron-down" class="pointer-events-none absolute top-1/2 end-3.5 size-4 -translate-y-1/2 text-muted-foreground opacity-50 select-none" aria-hidden="true" data-slot="native-select-icon" />
</div>
templates/components/NativeSelect/OptGroup.html.twig
{# @block content The `NativeSelect:Option` components in this group. #}
<optgroup data-slot="native-select-optgroup" {{ attributes }}>
    {%- block content %}{% endblock -%}
</optgroup>
templates/components/NativeSelect/Option.html.twig
{# @block content The option label. #}
<option data-slot="native-select-option" {{ attributes }}>{%- block content %}{% endblock -%}</option>

Usage

<twig:NativeSelect>
    <twig:NativeSelect:Option value="">Select a fruit</twig:NativeSelect:Option>
    <twig:NativeSelect:Option value="apple">Apple</twig:NativeSelect:Option>
    <twig:NativeSelect:Option value="banana">Banana</twig:NativeSelect:Option>
    <twig:NativeSelect:Option value="blueberry">Blueberry</twig:NativeSelect:Option>
</twig:NativeSelect>

Examples

Groups

Use NativeSelect:OptGroup to organize options into labeled groups.

100%
Loading...
<twig:NativeSelect>
    <twig:NativeSelect:Option value="">Select department</twig:NativeSelect:Option>
    <twig:NativeSelect:OptGroup label="Engineering">
        <twig:NativeSelect:Option value="frontend">Frontend</twig:NativeSelect:Option>
        <twig:NativeSelect:Option value="backend">Backend</twig:NativeSelect:Option>
        <twig:NativeSelect:Option value="devops">DevOps</twig:NativeSelect:Option>
    </twig:NativeSelect:OptGroup>
    <twig:NativeSelect:OptGroup label="Sales">
        <twig:NativeSelect:Option value="sales-rep">Sales Rep</twig:NativeSelect:Option>
        <twig:NativeSelect:Option value="account-manager">Account Manager</twig:NativeSelect:Option>
        <twig:NativeSelect:Option value="sales-director">Sales Director</twig:NativeSelect:Option>
    </twig:NativeSelect:OptGroup>
    <twig:NativeSelect:OptGroup label="Operations">
        <twig:NativeSelect:Option value="support">Customer Support</twig:NativeSelect:Option>
        <twig:NativeSelect:Option value="product-manager">Product Manager</twig:NativeSelect:Option>
        <twig:NativeSelect:Option value="ops-manager">Operations Manager</twig:NativeSelect:Option>
    </twig:NativeSelect:OptGroup>
</twig:NativeSelect>

Disabled

100%
Loading...
<twig:NativeSelect disabled>
    <twig:NativeSelect:Option value="">Disabled</twig:NativeSelect:Option>
    <twig:NativeSelect:Option value="apple">Apple</twig:NativeSelect:Option>
    <twig:NativeSelect:Option value="banana">Banana</twig:NativeSelect:Option>
    <twig:NativeSelect:Option value="blueberry">Blueberry</twig:NativeSelect:Option>
</twig:NativeSelect>

Invalid

Set aria-invalid="true" to display the error state.

100%
Loading...
<twig:NativeSelect aria-invalid="true">
    <twig:NativeSelect:Option value="">Error state</twig:NativeSelect:Option>
    <twig:NativeSelect:Option value="apple">Apple</twig:NativeSelect:Option>
    <twig:NativeSelect:Option value="banana">Banana</twig:NativeSelect:Option>
    <twig:NativeSelect:Option value="blueberry">Blueberry</twig:NativeSelect:Option>
</twig:NativeSelect>

RTL

To enable RTL support, set the dir="rtl" attribute on the root element.

100%
Loading...
<div class="flex flex-col items-center gap-4">
    {# Arabic #}
    <div dir="rtl">
        <twig:NativeSelect>
            <twig:NativeSelect:Option value="">اختر الحالة</twig:NativeSelect:Option>
            <twig:NativeSelect:Option value="todo">مهام</twig:NativeSelect:Option>
            <twig:NativeSelect:Option value="in-progress">قيد التنفيذ</twig:NativeSelect:Option>
            <twig:NativeSelect:Option value="done">منجز</twig:NativeSelect:Option>
            <twig:NativeSelect:Option value="cancelled">ملغي</twig:NativeSelect:Option>
        </twig:NativeSelect>
    </div>

    {# Hebrew #}
    <div dir="rtl">
        <twig:NativeSelect>
            <twig:NativeSelect:Option value="">בחר סטטוס</twig:NativeSelect:Option>
            <twig:NativeSelect:Option value="todo">לעשות</twig:NativeSelect:Option>
            <twig:NativeSelect:Option value="in-progress">בתהליך</twig:NativeSelect:Option>
            <twig:NativeSelect:Option value="done">הושלם</twig:NativeSelect:Option>
            <twig:NativeSelect:Option value="cancelled">בוטל</twig:NativeSelect:Option>
        </twig:NativeSelect>
    </div>
</div>

API Reference

<twig:NativeSelect>

Prop Type Default
size 
'default'|'sm' 'default'
Block Description
content The select options, typically NativeSelect:Option and NativeSelect:OptGroup components.

<twig:NativeSelect:OptGroup>

Block Description
content The NativeSelect:Option components in this group.

<twig:NativeSelect:Option>

Block Description
content The option label.