Select

Native HTML select by default, with an optional rich listbox variant for advanced features.

Native Select (Default)

By default, select uses the native HTML <select> element. This is perfect for most use cases - it works great on mobile, has built-in accessibility, and requires no JavaScript.

<div class="w-full max-w-64">
    <c-ui.select name="country" placeholder="Select a country">
        <c-ui.select.option value="us">United States</c-ui.select.option>
        <c-ui.select.option value="uk">United Kingdom</c-ui.select.option>
        <c-ui.select.option value="ca">Canada</c-ui.select.option>
        <c-ui.select.option value="au">Australia</c-ui.select.option>
        <c-ui.select.option value="de">Germany</c-ui.select.option>
    </c-ui.select>
</div>
<div class="w-full max-w-64">
    {% cotton ui.select name="country" placeholder="Select a country" %}
        {% cotton ui.select.option value="us" %}United States{% endcotton %}
        {% cotton ui.select.option value="uk" %}United Kingdom{% endcotton %}
        {% cotton ui.select.option value="ca" %}Canada{% endcotton %}
        {% cotton ui.select.option value="au" %}Australia{% endcotton %}
        {% cotton ui.select.option value="de" %}Germany{% endcotton %}
    {% endcotton %}
</div>

Listbox Variant

Use variant="listbox" when you need custom styling, icons, descriptions, or search functionality. This provides a rich, fully customizable dropdown experience.

<div class="w-full max-w-64">
    <c-ui.select name="plan" variant="listbox" placeholder="Choose a plan">
        <c-ui.menu.item value="free">Free</c-ui.menu.item>
        <c-ui.menu.item value="starter">Starter</c-ui.menu.item>
        <c-ui.menu.item value="pro">Professional</c-ui.menu.item>
        <c-ui.menu.item value="enterprise">Enterprise</c-ui.menu.item>
    </c-ui.select>
</div>
<div class="w-full max-w-64">
    {% cotton ui.select name="plan" variant="listbox" placeholder="Choose a plan" %}
        {% cotton ui.menu.item value="free" %}Free{% endcotton %}
        {% cotton ui.menu.item value="starter" %}Starter{% endcotton %}
        {% cotton ui.menu.item value="pro" %}Professional{% endcotton %}
        {% cotton ui.menu.item value="enterprise" %}Enterprise{% endcotton %}
    {% endcotton %}
</div>

Grouped Options

Organize options into logical groups with labels.

<div class="w-full max-w-64">
    <c-ui.select name="region" variant="listbox" placeholder="Select a region">
        <c-ui.menu.group label="North America">
            <c-ui.menu.item value="us" group="North America">United States</c-ui.menu.item>
            <c-ui.menu.item value="ca" group="North America">Canada</c-ui.menu.item>
            <c-ui.menu.item value="mx" group="North America">Mexico</c-ui.menu.item>
        </c-ui.menu.group>
        <c-ui.menu.group label="Europe">
            <c-ui.menu.item value="uk" group="Europe">United Kingdom</c-ui.menu.item>
            <c-ui.menu.item value="de" group="Europe">Germany</c-ui.menu.item>
            <c-ui.menu.item value="fr" group="Europe">France</c-ui.menu.item>
        </c-ui.menu.group>
        <c-ui.menu.group label="Asia">
            <c-ui.menu.item value="jp" group="Asia">Japan</c-ui.menu.item>
            <c-ui.menu.item value="cn" group="Asia">China</c-ui.menu.item>
            <c-ui.menu.item value="in" group="Asia">India</c-ui.menu.item>
        </c-ui.menu.group>
    </c-ui.select>
</div>
<div class="w-full max-w-64">
    {% cotton ui.select name="region" variant="listbox" placeholder="Select a region" %}
        {% cotton ui.menu.group label="North America" %}
            {% cotton ui.menu.item value="us" group="North America" %}United States{% endcotton %}
            {% cotton ui.menu.item value="ca" group="North America" %}Canada{% endcotton %}
            {% cotton ui.menu.item value="mx" group="North America" %}Mexico{% endcotton %}
        {% endcotton %}
        {% cotton ui.menu.group label="Europe" %}
            {% cotton ui.menu.item value="uk" group="Europe" %}United Kingdom{% endcotton %}
            {% cotton ui.menu.item value="de" group="Europe" %}Germany{% endcotton %}
            {% cotton ui.menu.item value="fr" group="Europe" %}France{% endcotton %}
        {% endcotton %}
        {% cotton ui.menu.group label="Asia" %}
            {% cotton ui.menu.item value="jp" group="Asia" %}Japan{% endcotton %}
            {% cotton ui.menu.item value="cn" group="Asia" %}China{% endcotton %}
            {% cotton ui.menu.item value="in" group="Asia" %}India{% endcotton %}
        {% endcotton %}
    {% endcotton %}
</div>

Options with Icons

Add icons to options for better visual context.

<div class="w-full max-w-64">
    <c-ui.select name="payment" variant="listbox" placeholder="Select payment method">
        <c-ui.menu.item value="card" label="Credit Card">
            <c-slot name="icon">
                <svg>...</svg>
            </c-slot>
        </c-ui.menu.item>
        <c-ui.menu.item value="paypal" label="PayPal">
            <c-slot name="icon">
                <svg>...</svg>
            </c-slot>
        </c-ui.menu.item>
        <c-ui.menu.item value="bank" label="Bank Transfer">
            <c-slot name="icon">
                <svg>...</svg>
            </c-slot>
        </c-ui.menu.item>
    </c-ui.select>
</div>
<div class="w-full max-w-64">
    {% cotton ui.select name="payment" variant="listbox" placeholder="Select payment method" %}
        {% cotton ui.menu.item value="card" label="Credit Card" %}
            {% cotton:slot icon %}
                <svg>...</svg>
            {% endcotton:slot %}
        {% endcotton %}
        {% cotton ui.menu.item value="paypal" label="PayPal" %}
            {% cotton:slot icon %}
                <svg>...</svg>
            {% endcotton:slot %}
        {% endcotton %}
        {% cotton ui.menu.item value="bank" label="Bank Transfer" %}
            {% cotton:slot icon %}
                <svg>...</svg>
            {% endcotton:slot %}
        {% endcotton %}
    {% endcotton %}
</div>

Options with Descriptions

Add descriptions to provide additional context for each option.

<div class="w-full max-w-64">
    <c-ui.select name="plan" variant="listbox" placeholder="Choose your plan">
        <c-ui.menu.item value="free" label="Free" description="Perfect for personal projects" />
        <c-ui.menu.item value="starter" label="Starter" description="Great for small teams • $9/month" />
        <c-ui.menu.item value="pro" label="Professional" description="For growing businesses • $29/month" />
        <c-ui.menu.item value="enterprise" label="Enterprise" description="Advanced features & support • $99/month" />
    </c-ui.select>
</div>
<div class="w-full max-w-64">
    {% cotton ui.select name="plan" variant="listbox" placeholder="Choose your plan" %}
        {% cotton ui.menu.item value="free" label="Free" description="Perfect for personal projects" /%}
        {% cotton ui.menu.item value="starter" label="Starter" description="Great for small teams • $9/month" /%}
        {% cotton ui.menu.item value="pro" label="Professional" description="For growing businesses • $29/month" /%}
        {% cotton ui.menu.item value="enterprise" label="Enterprise" description="Advanced features & support • $99/month" /%}
    {% endcotton %}
</div>

Options with Icons and Descriptions

Combine icons and descriptions for maximum context.

<div class="w-full max-w-64">
    <c-ui.select name="integration" variant="listbox" placeholder="Select integration">
        <c-ui.menu.group label="Development">
            <c-ui.menu.item value="github" label="GitHub" description="Version control and collaboration" group="Development">
                <c-slot name="icon">
                    <svg>...</svg>
                </c-slot>
            </c-ui.menu.item>
            <c-ui.menu.item value="gitlab" label="GitLab" description="DevOps platform" group="Development">
                <c-slot name="icon">
                    <svg>...</svg>
                </c-slot>
            </c-ui.menu.item>
        </c-ui.menu.group>
        <c-ui.menu.group label="Communication">
            <c-ui.menu.item value="slack" label="Slack" description="Team messaging" group="Communication">
                <c-slot name="icon">
                    <svg>...</svg>
                </c-slot>
            </c-ui.menu.item>
        </c-ui.menu.group>
    </c-ui.select>
</div>
<div class="w-full max-w-64">
    {% cotton ui.select name="integration" variant="listbox" placeholder="Select integration" %}
        {% cotton ui.menu.group label="Development" %}
            {% cotton ui.menu.item value="github" label="GitHub" description="Version control and collaboration" group="Development" %}
                {% cotton:slot icon %}
                    <svg>...</svg>
                {% endcotton:slot %}
            {% endcotton %}
            {% cotton ui.menu.item value="gitlab" label="GitLab" description="DevOps platform" group="Development" %}
                {% cotton:slot icon %}
                    <svg>...</svg>
                {% endcotton:slot %}
            {% endcotton %}
        {% endcotton %}
        {% cotton ui.menu.group label="Communication" %}
            {% cotton ui.menu.item value="slack" label="Slack" description="Team messaging" group="Communication" %}
                {% cotton:slot icon %}
                    <svg>...</svg>
                {% endcotton:slot %}
            {% endcotton %}
        {% endcotton %}
    {% endcotton %}
</div>

Sizes

Select components run from size="xs" to size="2xl", defaulting to md.

<div class="w-full max-w-64 space-y-4">
    <c-ui.select name="size-sm" variant="listbox" placeholder="Small select" size="sm">
        <c-ui.menu.item value="1">Option 1</c-ui.menu.item>
        <c-ui.menu.item value="2">Option 2</c-ui.menu.item>
    </c-ui.select>

    <c-ui.select name="size-default" variant="listbox" placeholder="Default select">
        <c-ui.menu.item value="1">Option 1</c-ui.menu.item>
        <c-ui.menu.item value="2">Option 2</c-ui.menu.item>
    </c-ui.select>

    <c-ui.select name="size-lg" variant="listbox" placeholder="Large select" size="lg">
        <c-ui.menu.item value="1">Option 1</c-ui.menu.item>
        <c-ui.menu.item value="2">Option 2</c-ui.menu.item>
    </c-ui.select>
</div>
<div class="w-full max-w-64 space-y-4">
    {% cotton ui.select name="size-sm" variant="listbox" placeholder="Small select" size="sm" %}
        {% cotton ui.menu.item value="1" %}Option 1{% endcotton %}
        {% cotton ui.menu.item value="2" %}Option 2{% endcotton %}
    {% endcotton %}

    {% cotton ui.select name="size-default" variant="listbox" placeholder="Default select" %}
        {% cotton ui.menu.item value="1" %}Option 1{% endcotton %}
        {% cotton ui.menu.item value="2" %}Option 2{% endcotton %}
    {% endcotton %}

    {% cotton ui.select name="size-lg" variant="listbox" placeholder="Large select" size="lg" %}
        {% cotton ui.menu.item value="1" %}Option 1{% endcotton %}
        {% cotton ui.menu.item value="2" %}Option 2{% endcotton %}
    {% endcotton %}
</div>

Disabled State

Disable the select to prevent interaction, or disable specific options.

<div class="w-full max-w-64 space-y-4">
    <!-- Disabled select -->
    <c-ui.select name="disabled" variant="listbox" placeholder="Disabled select" disabled>
        <c-ui.menu.item value="1">Option 1</c-ui.menu.item>
        <c-ui.menu.item value="2">Option 2</c-ui.menu.item>
    </c-ui.select>

    <!-- Disabled options -->
    <c-ui.select name="disabled-options" variant="listbox" placeholder="Select an option">
        <c-ui.menu.item value="available">Available</c-ui.menu.item>
        <c-ui.menu.item value="sold-out" disabled>Sold Out</c-ui.menu.item>
        <c-ui.menu.item value="coming-soon" disabled>Coming Soon</c-ui.menu.item>
        <c-ui.menu.item value="in-stock">In Stock</c-ui.menu.item>
    </c-ui.select>
</div>
<div class="w-full max-w-64 space-y-4">
    <!-- Disabled select -->
    {% cotton ui.select name="disabled" variant="listbox" placeholder="Disabled select" disabled %}
        {% cotton ui.menu.item value="1" %}Option 1{% endcotton %}
        {% cotton ui.menu.item value="2" %}Option 2{% endcotton %}
    {% endcotton %}

    <!-- Disabled options -->
    {% cotton ui.select name="disabled-options" variant="listbox" placeholder="Select an option" %}
        {% cotton ui.menu.item value="available" %}Available{% endcotton %}
        {% cotton ui.menu.item value="sold-out" disabled %}Sold Out{% endcotton %}
        {% cotton ui.menu.item value="coming-soon" disabled %}Coming Soon{% endcotton %}
        {% cotton ui.menu.item value="in-stock" %}In Stock{% endcotton %}
    {% endcotton %}
</div>

Responsive positioning

The listbox flips above the trigger when there isn't room below, keeping the options in view. Drag the handle to shorten the viewport and watch it flip. (Native selects are positioned by the browser.)

As a field

Give it any field attribute (label, description, error or badge) and the select wraps itself in a Field component, giving you the label, helper text and error styling with no extra markup.

Where are you based?
<c-ui.select
    name="country"
    label="Country"
    placeholder="Select a country"
    description="Where are you based?"
>
    <c-ui.select.option value="us">United States</c-ui.select.option>
    <c-ui.select.option value="uk">United Kingdom</c-ui.select.option>
    <c-ui.select.option value="ca">Canada</c-ui.select.option>
</c-ui.select>
{% cotton ui.select
    name="country"
    label="Country"
    placeholder="Select a country"
    description="Where are you based?"
%}
    {% cotton ui.select.option value="us" %}United States{% endcotton %}
    {% cotton ui.select.option value="uk" %}United Kingdom{% endcotton %}
    {% cotton ui.select.option value="ca" %}Canada{% endcotton %}
{% endcotton %}

API Reference

Props

Select (Main Component)

Name Description Type Options Default
name Form field name for submission. str
placeholder Placeholder text when no option selected. str Select an option
disabled Disable the entire select. bool False
required Make the field required. bool False

Select.Trigger

Name Description Type Options Default
size Size variant from xs to 2xl. str
xssmmdlgxl2xl
md

Select.Search

Name Description Type Options Default
placeholder Search input placeholder text. str Search...

Select.Group

Name Description Type Options Default
label Group label text displayed above grouped options. str

Select.Option

Name Description Type Options Default
value Option value (required). Submitted with the form. str
label Option label. Defaults to slot content if not provided. str
description Secondary description text displayed below the option label. str
group Group identifier for filtering. Should match the group label. str
disabled Disable this specific option. bool False

Slots

Name Description Type Options Default
slot (default) Main select content including trigger, search, groups, and options.
icon (Option only) Icon or avatar displayed before option label. Provide an SVG element. slot

Events

Name Description Type Options Default
select-change Fired when selection changes. Detail: { value, label } CustomEvent