Suggestions
Prompt starters — a row of ready-made prompts above the input that the reader clicks instead of typing.
-
<aparte-suggestions>
On this page
<!-- empty-only: the row is there while the conversation is empty, gone after the first send. -->
<aparte-chat style="height: 24rem">
<aparte-chat-viewport></aparte-chat-viewport>
<aparte-composer placeholder="Or type your own…">
<aparte-suggestions empty-only
suggestions='["Write a haiku", "Show me a table", {"label": "What is the weather?", "prompt": "What is the weather in Lille?"}]'>
</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>
</aparte-chat>An empty chat is a blank page, and three good starters tell a reader what it is for. Each one
is a button: a click puts its prompt in the composer and sends it. With empty-only, the row
is there while the conversation is empty and gone after the first message. Try one above:
the scripted model answers.
The click goes through the composer, as if the prompt had been typed, so it obeys the same rules: nothing is sent while the composer is disabled, a reply is streaming, or no model is selected.
Variants
Section titled “Variants”Fill without sending
Section titled “Fill without sending”<aparte-composer placeholder="Ask anything">
<aparte-suggestions mode="fill"
suggestions='["Summarise this page", "Translate it into French", "List the open questions"]'>
</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>mode="fill" puts the prompt in the input and focuses it, for prompts the reader is meant to
finish or adjust.
Place it inside the composer, before its shell. A suggestion is a
string, or a { label, prompt } pair when the button’s text and the prompt sent differ. The
suggestions attribute takes them as JSON; the property takes the array.
<aparte-suggestions empty-only=""></aparte-suggestions>el.addEventListener('aparte-suggestion', (e) => use(e.detail));<aparte-suggestions empty-only=""></aparte-suggestions>The aparte-* tags are typed JSX intrinsics as soon as you import from @aparte/react. A presence attribute takes '', never true — React stringifies it, and empty-only={false} would render empty-only="false", which hasAttribute reads as on. Events reach you by ref, typed through the DOM.
<template>
<aparte-suggestions empty-only=""
@aparte-suggestion="(e) => use(e.detail)"
></aparte-suggestions>
</template>Declared through Vue’s GlobalComponents, so vue-tsc checks the tag in any template. A presence attribute takes '' to set and null to remove, never false.
<aparte-suggestions empty-only=""
on:aparte-suggestion={(e) => use(e.detail)}
></aparte-suggestions>Declared through SvelteHTMLElements, so svelte-check covers the attributes and the on: handlers. A presence attribute takes '', never false.
import { AparteSuggestionsDirective } from '@aparte/angular';<aparte-suggestions [emptyOnly]="true"
(suggestion)="use($event)"></aparte-suggestions>A standalone directive whose selector IS the tag, so the real element sits in the template — @if, @for and content projection all reach it — and no CUSTOM_ELEMENTS_SCHEMA is needed.
Installation and the framework-specific traps: React · Vue · Svelte · Angular.
To act on a click yourself, listen for aparte-suggestion: it fires first and is cancelable,
and preventDefault() leaves the composer untouched.
Customize
Section titled “Customize”The row has no variables of its own: its spacing comes from the --aparte-space-* scale and
its buttons wear the button recipe, so it follows your theme.
<aparte-suggestions> · class AparteSuggestions
Attributes
| Attribute | Description |
|---|---|
suggestions | The 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. |
target | The id of the <aparte-chat> whose composer should receive the click, when the element is not inside that composer. |
empty-only | Shows the row only while the conversation it serves is empty: hidden (hidden) once a message is in its transcript or on its way — a thread being loaded counts — and shown again when the transcript is cleared, by a new chat for instance. The composer’s send hides it at once, before its message lands. The element sets and lifts hidden itself and never lifts one you set. With no transcript to read — a composer outside any chat — the first send hides it until the attribute is removed. |
mode | send (default): the click fills the composer and submits. fill: the click fills the composer and focuses it, so the reader edits first. |
data-empty | Reflected BY the element while it has no suggestion to show; the stylesheet hides it then. Read-only, do not set it yourself. |
Properties
| Property | Type | Description |
|---|---|---|
suggestions | AparteSuggestion[] | Takes the array, or the JSON string the attribute documents. Both, because both arrive: React 19 and Svelte assign the PROPERTY whenever the element has one of that name, so <aparte-suggestions suggestions='[…]'> — the documented spelling, typed valid by both wrappers — reached this setter as a string, Array.isArray said no, and the row rendered nothing while the attribute (and so attributeChangedCallback) was never written. |
Events
| Event | Type | Description |
|---|---|---|
aparte-suggestion | CustomEvent<AparteSuggestionEventDetail> | A starter was clicked. Bubbles, and is cancelable: preventDefault() stops the composer from being filled or submitted. |
Accessibility
Section titled “Accessibility”- The row is a group named from the
suggestionsLabelkey (“Suggested prompts”); each suggestion is a button that reads as its label.