# Suggestion chips

Starter prompts as small plates set out under the composer. Each is a real key (the kit’s cap on its skirt) that is allowed to be a line or two of words, left-aligned like a printed legend. Press one and its words are written into the prompt box, with the caret at the end, and the sending is left to you. It fills the composer next to it, or any text area you point it at, and it works on its own as plain buttons with an event when there is no box to fill.

Kit part · Free · https://tactileui.dev/parts/suggestion-chips

- Element: `<div class="tui-suggestions">`
- Needs: `kit.css` and `kit.mjs` ([how to install the kit](https://tactileui.dev/docs/installation#the-kit))
- Categories: AI chats
- Finishes: Aluminium, Graphite, Oak, Walnut, Porcelain, Black, Daylight, Night, Paper, Phosphor, E-paper, AMOLED
- Volumes: Tactile, Quiet

## Variants

### Three prompts

```html
<div style="width:min(460px,calc(100vw - 96px));text-align:left"><div class="tui-suggestions" role="group" aria-labelledby="sg73-l"><p class="tui-label tui-suggestions__label" id="sg73-l">Try asking</p><ul class="tui-suggestions__list" role="list"><li><button class="tui-key tui-key--sm tui-suggestion" type="button">Is Studio A free at three?</button></li><li><button class="tui-key tui-key--sm tui-suggestion" type="button">Which rooms have a piano?</button></li><li><button class="tui-key tui-key--sm tui-suggestion" type="button">Hold Room 2 for Tom until 16:30</button></li></ul><p class="tui-suggestions__said" role="status"></p></div></div>
```

### One long prompt wraps

```html
<div style="width:min(300px,calc(100vw - 96px));text-align:left"><div class="tui-suggestions" role="group" aria-labelledby="sg74-l"><p class="tui-label tui-suggestions__label" id="sg74-l">Try asking</p><ul class="tui-suggestions__list" role="list"><li><button class="tui-key tui-key--sm tui-suggestion" type="button">List every room that is free tomorrow between nine and five, and say which have a window and a piano</button></li></ul><p class="tui-suggestions__said" role="status"></p></div></div>
```

### Words of their own · data-suggestion

```html
<div style="width:min(460px,calc(100vw - 96px));text-align:left"><div class="tui-suggestions" role="group" aria-labelledby="sg75-l"><p class="tui-label tui-suggestions__label" id="sg75-l">Try asking</p><ul class="tui-suggestions__list" role="list"><li><button class="tui-key tui-key--sm tui-suggestion" type="button" data-suggestion="Is Studio A free from 15:00 today?">Studio A at three</button></li><li><button class="tui-key tui-key--sm tui-suggestion" type="button">Which rooms have a piano?</button></li></ul><p class="tui-suggestions__said" role="status"></p></div></div>
```

### On their own, as buttons · no composer

```html
<div style="width:min(460px,calc(100vw - 96px));text-align:left"><div class="tui-suggestions" role="group" aria-labelledby="sg76-l"><p class="tui-label tui-suggestions__label" id="sg76-l">Quick filters</p><ul class="tui-suggestions__list" role="list"><li><button class="tui-key tui-key--sm tui-suggestion" type="button">Open today</button></li><li><button class="tui-key tui-key--sm tui-suggestion" type="button">Needs a piano</button></li><li><button class="tui-key tui-key--sm tui-suggestion" type="button">Ground floor</button></li></ul><p class="tui-suggestions__said" role="status"></p></div></div>
```

### A single line of two

```html
<div style="width:min(360px,calc(100vw - 96px));text-align:left"><div class="tui-suggestions" role="group" aria-labelledby="sg77-l"><p class="tui-label tui-suggestions__label" id="sg77-l">Suggested</p><ul class="tui-suggestions__list" role="list"><li><button class="tui-key tui-key--sm tui-suggestion" type="button">Is Studio A free at three?</button></li><li><button class="tui-key tui-key--sm tui-suggestion" type="button">Which rooms have a piano?</button></li></ul><p class="tui-suggestions__said" role="status"></p></div></div>
```

## Every state

- Rest
- Hover
- Pressed
- Focused
- Disabled

Hover, pressed and focus are forced with `.is-hover`, `.is-down` and `.is-focus`; checked and disabled are real.

## API

| Name | Kind | Values | What it does |
| - | - | - | - |
| div.tui-suggestions[role="group"][aria-labelledby] | element | named | The group of plates, with a printed label above it. |
| [data-for] | attribute | a selector | The composer (a form.tui-composer) or text area the plates fill. Without it the first composer or text area beside the group is used. |
| button.tui-key.tui-key--sm.tui-suggestion | element | a real button | One plate. Its words are the words it writes. May be a line or two; it wraps and stays left-aligned. |
| [data-suggestion] | attribute | on a plate | The words to write when they are not the plate’s own text, for a plate that shows a short name for a long prompt. |
| p.tui-suggestions__said[role="status"] | element | optional | Says what was done (“Wrote “Is Studio A free at three?”. Press Enter to send.”), and says so when it replaced words. |
| tui-suggestion | event | bubbles from the group | Fired after a press, with detail { text, target, replaced }. With no box to fill, target is null and the page decides what the press means. |
| suggestionText() · suggestionSays() | function | pure | The words a plate writes, and the sentence said after a press. |
| fillSuggestion(target, text) | function | needs kit.mjs | Write words into a composer or text area as typing does, and return { filled, replaced }. |

## Markup

```html
<!-- A group of real buttons. data-for points at the composer (or any text area); without it, the first composer beside the group is used. -->
<div class="tui-suggestions" role="group" aria-labelledby="sg-l" data-for="#c1">
  <p class="tui-label tui-suggestions__label" id="sg-l">Try asking</p>
  <ul class="tui-suggestions__list" role="list">
    <li><button class="tui-key tui-key--sm tui-suggestion" type="button">Is Studio A free at three?</button></li>
    <li><button class="tui-key tui-key--sm tui-suggestion" type="button" data-suggestion="Which rooms have a piano?">Rooms with a piano</button></li>
  </ul>
  <p class="tui-suggestions__said" role="status"></p>
</div>
```

```js
import '/kit/kit.mjs';

document.addEventListener('tui-suggestion', (e) => {
  console.log(e.detail.text, e.detail.target, e.detail.replaced);   // the words, the box that was filled (or null), and whether it held words already
});
```

The demo on the page:

```html
<div class="tui-panel" style="width:min(100%,560px);display:grid;gap:16px;text-align:left"><div class="tui-panel__head" style="margin-bottom:0"><span class="tui-label">Studio assistant</span></div><div style="display:grid;gap:14px"><form class="tui-composer" data-limit="300" data-state="ok" data-sg-demo><label class="tui-composer__label" for="sg-cp-demo">Message to the Studio assistant</label><div class="tui-composer__well"><textarea class="tui-composer__input" id="sg-cp-demo" name="message" rows="1" required placeholder="Ask about a room or a time" aria-describedby="sg-cp-demo-help sg-cp-demo-limit"></textarea><div class="tui-composer__files"></div><div class="tui-composer__bar"><button class="tui-key tui-key--flat tui-key--icon tui-key--sm" type="button" data-composer-attach aria-label="Attach a file"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M13 7.4 8 12.4a3.2 3.2 0 0 1-4.6-4.6l5.3-5.3a2.1 2.1 0 0 1 3 3L6.5 10.7a1 1 0 0 1-1.5-1.5L9.8 4.5"/></svg></button><input type="file" name="files" multiple hidden aria-label="Attach files"><div class="tui-composer__tail"><span class="tui-composer__run"><span class="tui-lamp" data-lamp="amber" data-on data-blink aria-hidden="true"></span>Working</span><output class="tui-lcd tui-lcd--sm tui-composer__count" data-ghost="888/888" data-state="ok" aria-hidden="true">000/300</output><span class="tui-composer__unit" aria-hidden="true">tokens</span><button class="tui-key tui-key--primary tui-composer__send" type="submit" disabled><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 13V3.5M3.8 7.5 8 3.3l4.2 4.2"/></svg>Send</button><button class="tui-key tui-composer__stop" type="button" data-composer-stop><svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><rect x="4" y="4" width="8" height="8" rx="1.2"/></svg>Stop</button></div></div></div><p class="tui-composer__help" id="sg-cp-demo-help"><span class="tui-kbd tui-kbd--sm">Enter</span> sends. <span class="tui-kbd tui-kbd--sm">Shift</span> + <span class="tui-kbd tui-kbd--sm">Enter</span> makes a new line.</p><span class="tui-composer__limit" id="sg-cp-demo-limit">0 of 300 tokens used</span><p class="tui-composer__said" role="status"></p></form><div class="tui-suggestions" role="group" aria-labelledby="sg-d-l" data-for="#sg-cp-demo"><p class="tui-label tui-suggestions__label" id="sg-d-l">Try asking</p><ul class="tui-suggestions__list" role="list"><li><button class="tui-key tui-key--sm tui-suggestion" type="button">Is Studio A free at three?</button></li><li><button class="tui-key tui-key--sm tui-suggestion" type="button">Which rooms have a piano?</button></li><li><button class="tui-key tui-key--sm tui-suggestion" type="button">Hold Room 2 for Tom until 16:30</button></li></ul><p class="tui-suggestions__said" role="status"></p></div></div><output class="tui-muted" style="font-size:var(--tui-t-small)" data-sg-out aria-live="polite"></output></div>
```

## Usage notes

Press a plate: its words are written into the prompt box and the caret is at the end. Type something of your own and press another plate: it replaces your words and says so, and Ctrl+Z (or Cmd+Z) brings yours back. Nothing is sent until you press Enter.

## Accessibility

- Each plate is a real button in a list inside a labelled group, so there is one tab stop for each and the label names the group. The words on the plate are its name; the words a long prompt writes are the same unless data-suggestion says otherwise, and then the plate’s short name is what is read.
- A press writes the words as typing does, so the composer counts them, enables its send key and keeps the browser’s undo: if the box held words of the person’s own, they are replaced, it is said so, and Ctrl+Z gives them back. Nothing is ever sent by a press.
- After a press the focus is in the text area with the caret at the end, so the next key typed edits the prompt. What happened is said once, politely: “Wrote …. Press Enter to send.”
- The plates keep the key’s states (hover, pressed, focus ring, disabled), so none of them is told apart by colour. On a phone each is 44px tall and they wrap onto more lines rather than scrolling.

## How it’s built

The kit’s key, small, allowed to wrap, in a list that wraps; there is no new drawing at all. The script is one click handler on the document: it finds the box, selects its words, types the new ones in so the undo history keeps what was there, and puts the caret at the end.

## Rules

Offer a few things worth asking: small plates under the prompt box that write their words into it, and leave the sending to the person.

The full rules are in `suggestion-chips.rules.md` in the brain, which ships with the Kit.

## Related parts

- [Composer](https://tactileui.dev/parts/composer): The prompt box. One deep recess holds the text and the keys sit on its floor: attach at one end; at the other a small LCD that counts tokens, amber near the limit and red over it, and the send key, which becomes a stop key while a reply runs. It is a real form with a labelled text area. Enter sends and Shift and Enter make a new line, and the send key is disabled while there is nothing to send. The text grows as you type, up to a height, then scrolls.
- [Chip group](https://tactileui.dev/parts/chip-group): Small plates you press on and off, laid in a tray that wraps: the filters over a table, the topics on a form, the sizes on a product. Each chip is a native checkbox, or a radio when only one may be down, drawn as a small cap that sinks below the tray with its lamp lit. A limit may be set on how many go down at once.
- [Key](https://tactileui.dev/parts/key): Every button, and every link that acts like one: a cap on a skirt that drops below the plate when pressed.
- [Chat](https://tactileui.dev/parts/chat): An AI chat as a teleprinter, with restraint: what you type sits in a recess; the answer prints on a perforated slip with an amber lamp at the print head; code comes up on display glass. Composer with attachments and a send key that becomes Stop.
