Composer

A chat-style input: a focusable shell wrapping an auto-growing textarea and a row of actions.

Basic

On its own the composer is an auto-growing textarea inside a shell that takes the focus ring. Type to watch it grow.

<c-ui.composer placeholder="Write a comment…" />
{% cotton ui.composer placeholder="Write a comment…" /%}

Prompt box

Fill the leading and trailing slots to build a prompt box. The whole shell stays lit while any control inside it is focused.

<c-ui.composer placeholder="Ask anything…">
    <c-slot name="leading">
        <c-ui.button variant="ghost" size="sm" class="!px-2" aria-label="Add">
            <svg><!-- plus --></svg>
        </c-ui.button>
    </c-slot>
    <c-slot name="trailing">
        <span class="px-1 text-sm text-ink-500">Opus 4.8</span>
        <c-ui.button variant="ghost" size="sm" class="!px-2" aria-label="Dictate">
            <svg><!-- mic --></svg>
        </c-ui.button>
        <c-ui.button variant="primary" size="sm" class="!px-2" aria-label="Send">
            <svg><!-- arrow-up --></svg>
        </c-ui.button>
    </c-slot>
</c-ui.composer>
{% cotton ui.composer placeholder="Ask anything…" %}
    {% cotton:slot leading %}
        {% cotton ui.button variant="ghost" size="sm" class="!px-2" aria-label="Add" %}
            <svg><!-- plus --></svg>
        {% endcotton %}
    {% endcotton:slot %}
    {% cotton:slot trailing %}
        <span class="px-1 text-sm text-ink-500">Opus 4.8</span>
        {% cotton ui.button variant="ghost" size="sm" class="!px-2" aria-label="Dictate" %}
            <svg><!-- mic --></svg>
        {% endcotton %}
        {% cotton ui.button variant="primary" size="sm" class="!px-2" aria-label="Send" %}
            <svg><!-- arrow-up --></svg>
        {% endcotton %}
    {% endcotton:slot %}
{% endcotton %}

How it works

  • One focusable surface. The shell shows the focus ring with focus-within, so focusing the textarea (or a button inside) lights the whole box like a single input.
  • Transparent textarea. The textarea is borderless and transparent (--color-input-bg), so it reads as part of the shell rather than a nested field.
  • Auto-grows. A small Alpine helper resizes the textarea to its content as you type, up to a max height, then scrolls.
  • Plain text. It is a real <textarea>, so it submits in forms and stays accessible. For rich content (mentions, inline pills) reach for a dedicated editor instead.

Reference

Props

Name Description Type Options Default
name Form field name for the textarea. str —
placeholder Placeholder text. str — Send a message…
value Initial textarea content. str —
variant raised fills the surface so it sits above the page in both light and dark; flush uses the transparent field fill (flat in light, faintly lifted in dark) to match form inputs. str
raisedflush
raised
rows Initial visible rows before auto-grow takes over. str — 2
:disabled Dim and disable the input. bool
TrueFalse
False

Slots

Name Description Type Options Default
leading Actions on the left of the toolbar row (e.g. an attach button). slot —
trailing Actions on the right of the toolbar row (e.g. a model picker, mic, send). slot —

Any extra attributes (e.g. x-model, maxlength, hx-*) are forwarded to the underlying <textarea>.

Theme
Accent
Ink