Studio
2

Composer

Installation

pnpm dlx @mielui/svelte add composer

Usage

The theme setting chrome.borders chooses "single" or "double" framing. Double is the default. Single removes the extra frame while preserving content padding, composition, and inset variants.

Bind the prompt value on Root and handle submission with onSubmit. Composer waits for async handlers and shows the submitting state until they finish. Submit labels its icon as Send, Queue message, or Stop response to match the current action.

If submission rejects, Composer preserves the prompt and shows errorMessage. Use onError to report the failure, then retry with the same submit button. If you set status="error" yourself, your application must clear it.

import * as Composer from '@mielui/svelte/components/composer';

let value = $state('');

async function sendPrompt(prompt: string) {
  await saveMessage(prompt);
  value = '';
}

<Composer.Root bind:value onSubmit={sendPrompt} onError={reportError}>
  <Composer.Input placeholder="Ask anything..." />
  <Composer.Toolbar>
    <Composer.Actions>
      <!-- Add attachment, model, or permission controls here. -->
    </Composer.Actions>
    <Composer.Submit />
  </Composer.Toolbar>
</Composer.Root>

By default, submits and inserts a new line. Set submitOnEnter=false on Input when Enter should always create a new line.

Glass surface

Set surface="glass" on Composer.Root for a frosted frame with a darker input well. Solid is used unless the theme enables glass globally.

Submission and cancellation

Return a promise from onSubmit to keep the submit control pending until your request settles. Reject it to preserve the prompt and display errorMessage. Use controlled status="submitting" or generating for a stoppable response. onStop must cancel your request or timer; it does not cancel application work automatically. The examples below include a real stop action and a failure you can retry.

Examples

Idle

Submitting

Error

Toolbar inset

The toolbar defaults to the frame chrome outside the input well. Set variant="inset" to merge it into the same inset surface as the input.

API reference

Composer.Root

Manages prompt submission.

Prop Type Default
surface "solid" | "glass" | undefined —
value Bindable string | undefined ''
status ComposerStatus | undefined 'idle'
generating boolean | undefined

Whether a response is being generated independently of submission state.

—
disabled boolean | undefined false
allowEmpty boolean | undefined false
onSubmit Required (value: string, event: SubmitEvent) => void | Promise<void> —
errorMessage string | undefined 'Message could not be sent.'
onError ((error: unknown) => void) | undefined —
onStop (() => void) | undefined —
class string | undefined —
children Snippet<[]> | undefined —

Composer.Actions

Groups composer actions.

Prop Type Default
class string | undefined —
children Snippet<[]> | undefined —

Composer.Input

Accepts the prompt text.

Prop Type Default
submitOnEnter boolean | undefined true
element Bindable HTMLTextAreaElement | undefined —
class string | undefined —

Composer.Submit

Submits or stops the prompt.

Prop Type Default
label string | undefined 'Send'
queueLabel string | undefined 'Queue message'
stopLabel string | undefined 'Stop response'
loadingLabel string | undefined 'Sending'
children Snippet<[Readonly<{ action: ComposerSubmitAction; generating: boolean; empty: boolean; }>]> | undefined —
element Bindable HTMLButtonElement | HTMLAnchorElement | undefined —
onclick ((event: MouseEvent) => void) | undefined —
class string | undefined —

Composer.Toolbar

Groups composer controls.

Prop Type Default
variant "chrome" | "inset" | undefined 'chrome'
class string | undefined —
children Snippet<[]> | undefined —