# PromptSuggestions

> Row of prompt pills that cascade in after a reply lands, offering the user a next turn without composing one.

- Package: `fancy-ui-svelte` (Svelte 5 + Tailwind CSS v4)
- Category: AI Chat
- Tags: ai, chat, suggestions, pills
- Docs: https://fancy-ui.rama.app/docs/components/prompt-suggestions
- Source: https://github.com/RamaHerbin/fancy-ui/tree/main/src/lib/fancy-ui/prompt-suggestions

## Import

```svelte
<script lang="ts">
  import { PromptSuggestions } from 'fancy-ui-svelte';
</script>
```

Setup (once per project): `npm install fancy-ui-svelte`, then add `@import "fancy-ui-svelte/tailwind.css";` after `@import "tailwindcss";` in your main CSS file. Full guide: https://fancy-ui.rama.app/llms.txt

React: `import { PromptSuggestions } from 'fancy-ui-react';` (same prop names; `class` becomes `className`, snippets become `ReactNode`).

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `suggestions` (required) | `string[]` | — | Prompt texts offered to the user, in display order |
| `onSelect` | `(suggestion: string, index: number) => void` | — | Called with the chosen prompt and its index when a pill is activated |
| `visible` | `boolean` | `true` | Whether the pills are shown; flipping this to true replays the entrance |
| `staggerMs` | `number` | `60` | Delay between two consecutive pills entering, in milliseconds |
| `label` | `string` | `"Suggestions"` | Accessible name of the group wrapping the pills |
| `sound` | `boolean` | `false` | Plays select when a suggestion is picked, once the user has enabled sound |

## Snippets

| Snippet | Description |
| --- | --- |
| `item` | Custom pill content, receiving the suggestion and its index |

## Examples

### Basic Usage

```svelte
<script lang="ts">
	import { onMount } from "svelte";
	import { PromptSuggestions } from "fancy-ui-svelte";

	const SUGGESTIONS = [
		"Why was the lockfile stale?",
		"Show me the failing job",
		"Turn the cache back on",
		"Summarize this for the team",
	];

	/** How long the reply sits alone before the follow-ups offer themselves. */
	const APPEAR_MS = 700;
	/** The beat the pills spend hidden before replaying, after one is picked. */
	const REPLAY_MS = 260;

	let visible = $state(false);
	let turns = $state<string[]>([]);

	let timer: ReturnType<typeof setTimeout> | undefined;
	let reduced = false;

	onMount(() => {
		reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

		// Nothing to stage when motion is reduced: the follow-ups are simply there,
		// which is the state the delay was building towards anyway.
		if (reduced) {
			visible = true;
			return;
		}

		timer = setTimeout(() => (visible = true), APPEAR_MS);
		return () => clearTimeout(timer);
	});

	function select(suggestion: string) {
		turns = [...turns, suggestion];

		// Hiding and re-showing is what replays the cascade — worth seeing once you
		// have picked one, but only when motion is welcome.
		if (reduced) return;
		visible = false;
		clearTimeout(timer);
		timer = setTimeout(() => (visible = true), REPLAY_MS);
	}
</script>

<div class="flex w-full max-w-xl flex-col gap-3">
	<div class="bg-muted text-foreground mr-auto max-w-[85%] rounded-2xl rounded-bl-sm px-4 py-3">
		<p class="text-sm leading-relaxed">
			The build is green again. The failure came from a stale lockfile in the CI cache rather than
			from anything in your branch — I re-ran the job with the cache disabled and every suite passed
			on the first attempt.
		</p>
	</div>

	{#each turns as turn, i (i)}
		<div
			class="bg-primary text-primary-foreground ml-auto max-w-[85%] rounded-2xl rounded-br-sm px-4 py-2.5"
		>
			<p class="text-sm">{turn}</p>
		</div>
	{/each}

	<PromptSuggestions
		sound
		suggestions={SUGGESTIONS}
		{visible}
		onSelect={select}
		label="Follow-up prompts"
		class="mt-1"
	/>
</div>
```
