---
title: "IconPicker"
description: "A picker that returns an icon identifier string."
category: Form
status: beta
since: 0.6.0
tags: [icon, picker, emoji, brand, file]
syncStatus: reviewed
verified: true
---

## Usage

### Trigger and Inline
`inline` renders the panel directly, and `sections` limits the sections it offers.
:::TuffDemoWrapper{demo="IconPickerIconPickerDemo" code-lang="vue"}
---
code: |
  <script setup lang="ts">
  import type { IconPickerShape } from '@talex-touch/tuffex/icon-picker'
  import { TxIconPicker } from '@talex-touch/tuffex/icon-picker'
  import { ref } from 'vue'

  const identifier = ref('emoji:🚀')
  const shape = ref<IconPickerShape>('rounded')
  </script>

  <template>
    <TxIconPicker v-model="identifier" v-model:shape="shape" shape-selectable />
    <TxIconPicker v-model="identifier" inline :sections="['icon', 'brand']" />
  </template>
---
:::

### Best Practices

- Store the identifier as-is and resolve it at render time with `parseIconIdentifier`; don't split it into two columns that can disagree.
- In modules that only read a stored value, import `parseIconIdentifier` from `@talex-touch/tuffex/icon-picker` without loading the panel.
- Turn `shapeSelectable` off when the host draws its own plate, or users pick a shape they never see.
- Use `TxIconChip` to display a small icon plate; this component only chooses one.

## API Reference

### Props

| Prop | Type | Default | Description |
|------|------|---------|------|
| `modelValue` | `string` | `''` | The icon identifier, bound with `v-model`. |
| `shape` | `'circle' \| 'rounded' \| 'square'` | `'rounded'` | Plate shape, bound with `v-model:shape`. |
| `sections` | `IconPickerSection[]` | all four | Sections to offer, in tab order; `file` appears as a choose-file button. |
| `catalog` | `Partial<Record<'emoji' \| 'icon' \| 'brand', IconPickerEntry[]>>` | - | Replaces a section's bundled rows; hosts with their own icon set replace them whole. |
| `shapeSelectable` | `boolean` | `true` | Shows the shape row; turn off when the host draws its own plate. |
| `fileChooser` | `() => Promise<string \| null>` | - | Host file dialog resolving to an absolute path, or `null` on cancel. |
| `accept` | `string` | `'image/*'` | Accept list for the file dialog and the fallback input. |
| `disabled` | `boolean` | `false` | Disables the trigger and the panel. |
| `size` | `number` | `44` | Edge length of the trigger plate, in px. |
| `placeholder` | `string` | `''` | The trigger's `aria-label`; falls back to the search label. |
| `inline` | `boolean` | `false` | Renders the panel directly instead of behind a trigger. |
| `labels` | `Partial<IconPickerLabels>` | English defaults | Section labels, search placeholder, and the clear and choose-file actions. |

### Events

| Event | Payload | Description |
|-------|---------|------|
| `update:modelValue` | `string` | Fires on a pick, with `''` when cleared. |
| `update:shape` | `IconPickerShape` | Fires when the shape changes. |
| `change` | `string` | Fires together with `update:modelValue`. |
| `file-error` | `unknown` | Fires when the chooser throws or the fallback input can't read the file. |

### Exposed Methods

| Name | Type | Description |
|------|------|-------------|
| `toggle(value?)` | `(value?: boolean) => void` | Opens or closes the panel per `value`, or flips it when omitted; an `inline` panel always shows. |

## The Identifier

A pick is a `<type>:<value>` string. It splits at the *first* colon, so a value may contain colons (`url:`, a Windows `file:C:/…`).

```
emoji:🚀
class:i-ri-rocket-line
file:/Users/me/a.png
url:https://example.com/y.svg
builtin:star
```

`parseIconIdentifier` and `formatIconIdentifier` convert both ways. An unprefixed string is not guessed at and returns `null`; a bare emoji is the one exception.

```ts
import { parseIconIdentifier } from '@talex-touch/tuffex/icon-picker'

parseIconIdentifier('class:i-ri-rocket-line') // { type: 'class', value: 'i-ri-rocket-line' }
parseIconIdentifier('rocket.png')             // null
parseIconIdentifier('🚀')                      // { type: 'emoji', value: '🚀' }
```

## Safelisting the Catalog

Hosts on a utility-CSS engine must safelist `ICON_CATALOG_CLASSES`, or every icon in the grid renders as an empty box. Spread the module export rather than copying the strings.

```ts
import { ICON_CATALOG_CLASSES } from '@talex-touch/tuffex/icon-picker'

export default defineConfig({
  safelist: [...ICON_CATALOG_CLASSES],
})
```

## Overview

- The file section depends on the host: pass `fileChooser` (for example an Electron `dialog.showOpenDialog` bridge); without it, a hidden `<input type="file">` yields a data URL.
- Search matches `keywords`, not the id; the bundled keywords are bilingual (English and Chinese).
- `shape` is presentational and stored separately; it is not part of the identifier.

## Technologies

- Identifier helpers: `src/identifier.ts`.
- Source: `packages/tuffex/packages/components/src/icon-picker/`.
