Skip to content

Suggestions

<aparte-suggestions>

Prompt starters — a row of suggested prompts a reader clicks instead of typing.

Every chat product opens on three or four of these, and the example app used to hand-roll them: four <button class="chip">, a click handler, a CSS recipe of its own. This element is that pattern done once, wearing the button recipe.

A click goes THROUGH the composer — setValue() then submit() — never a synthetic aparte-send. The composer’s submit() is where every gate lives (disabled, already streaming, requireModelSelection), and a chip that bypassed them once sent a request with an empty model id while the composer was visibly greyed out. So the element needs a composer: the nearest <aparte-composer> ancestor, else the one serving the chat named by target, else the first one in the document.

Tier (a) of ratified decision #8: core honours the click alone, so it is live by default. aparte-suggestion fires first and is cancelable — preventDefault() leaves the composer untouched, for an app that wants the prompt for itself.

It declares no custom property of its own: the gap comes from the global --aparte-space-* tokens and the chips from the aparte-btn recipe, so it inherits a theme rather than exposing knobs to re-set.

Width Open in a tab
The real element, in its own document so this site's CSS cannot reach it. It renders the same example printed below — every framework mounts this same element, so the rendering is what you get in all five; the code is what changes.
<!-- The starters sit above the input, inside the composer; a click fills and sends. -->
<aparte-composer>
<aparte-suggestions empty-only
suggestions='["What is aparté?", {"label": "Write a haiku", "prompt": "Write a haiku about web components."}]'>
</aparte-suggestions>
<div class="aparte-composer-shell">
<div class="aparte-composer-row">
<aparte-composer-input></aparte-composer-input>
<aparte-composer-send></aparte-composer-send>
</div>
</div>
</aparte-composer>
AttributeDescription
suggestionsThe starters, as a JSON array: strings, or { "label", "prompt" } objects when the visible label and the sent text differ. The suggestions PROPERTY takes the same shape without the JSON.
targetThe id of the <aparte-chat> whose composer should receive the click, when the element is not inside that composer.
modesend (default): the click fills the composer and submits. fill: the click fills the composer and focuses it, so the reader edits first.
empty-onlyHides the row (hidden) once its composer has sent something. Remove the attribute, or hidden, to show it again.
data-emptyReflected BY the element while it has no suggestion to show; the stylesheet hides it then. Read-only, do not set it yourself.
PropertyTypeDescription
suggestionsAparteSuggestion[]The starters. Setting it re-renders; the suggestions attribute is the JSON form.
EventTypeDescription
aparte-suggestionCustomEvent&lt;AparteSuggestionEventDetail>A starter was clicked. Bubbles, and is cancelable: preventDefault() stops the composer from being filled or submitted.

The element is the same object everywhere — the tag does not change. What changes is how an attribute is written and how an event reaches you.

<aparte-suggestions empty-only=""></aparte-suggestions>
el.addEventListener('aparte-suggestion', (e) => use(e.detail));

Installation and the framework-specific traps: React · Vue · Svelte · Angular.