# KlipyPicker

**When to use:** GIF picker backed by the Klipy API — chat reactions, message composers, content authoring tools. Renders inline by default; pass `isModal` to open inside a `Modal`.

**Keywords:** gif search, meme picker

**Import:** `import { KlipyPicker } from '@ahrowe/ui'`

**Requires:** a Klipy API token, passed as the `token` prop. There is no built-in key: without one the picker renders but every request fails.

```tsx
import { KlipyPicker } from '@ahrowe/ui';

// Inline picker
<KlipyPicker
  token={process.env.KLIPY_API_KEY}
  onSelect={(preview) => {
    if (preview) {
      attachGif(preview.media_formats.gif.url);
    }
  }}
/>

// Inside a modal trigger
<KlipyPicker
  token={process.env.KLIPY_API_KEY}
  isModal
  selected={currentGifId}
  onSelect={async (preview) => {
    await saveSelection(preview);
  }}
/>
```

**Key props:**

| Prop | Type | Description |
|------|------|-------------|
| `token` | `string` | Klipy API key. No default: without one the picker renders but every request fails |
| `isModal` | `boolean` | Render the picker inside a `Modal` instead of inline |
| `selected` | `string \| null` | Currently selected GIF id (for visual highlight) |
| `onSelect` | `(preview: KlipyResult \| null) => void \| Promise<void>` | Fires when a GIF is picked; `null` when cleared |
| `className` | `string` | Root element class |

**Labels:** `search` — the text this component renders of its own. Pass `labels` to override it, on the component or app-wide through `ConfigProvider`; keys merge individually. Type: `KlipyPickerLabels`.
