Icon Picker
Choose a curated Lucide icon or emoji with recents, ranked search and inline colour swatches.
- Status
- Since
0.23.127- Accessibility pattern
- APG dialog (non-modal) picker
Last updated
Install
Configure registry credentials first using the Quickstart. Before copying this item or any transitive registry dependency, verify the signed manifest and save the exact bytes for Icon Picker before installation. Retain the digest printed by this command.
pnpm exec vegastack-design verify icon-pickerInstall with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.
pnpm dlx shadcn@4.21.0 add @vegastack/icon-pickerRun the exact offline --post-write command printed by the preflight, using its saved item path and independently retained --expected-integrity digest. Use the saved preflight for every transitive registry dependency too; stop on any mismatch before using the components.
The same command installs the registry items it composes: @vegastack/avatar, @vegastack/button, @vegastack/color-picker, @vegastack/emoji-picker, @vegastack/icon-data, @vegastack/icon-glyph, @vegastack/picker-panel, @vegastack/picker-preferences, @vegastack/popover, @vegastack/tabs, @vegastack/tooltip.
Usage
import { IconPicker } from "@/components/ui/icon-picker";
<IconPicker onValueChange={setIcon} />;Examples
Composition
Use modes=icon or modes=emoji for one mode without tabs. Both modes use line tabs. Standard grids have eight columns; compact grids have seven. Recents occupy at most two rows. Both tabs share one popover width, sized to the grid, and both browse eight categories: emoji flags are left out of the category bar and reached through search. In icon mode a sticky footer carries the colour swatches on one row — the first, No colour, clears the hue — with Remove as a compact trash icon button (tooltip "Remove") on the right when onRemove is passed; the emoji tab shows only Remove, and the footer is omitted when it has nothing to show. Opening by pointer or keyboard focuses search, so typing filters at once; touch keeps focus on the popup so no on-screen keyboard appears. Clicks inside the popup never bubble to the trigger's ancestors, so the picker can sit in an InputGroupAddon beside a text field. Category headers stay pinned while the grid scrolls. Use closeOnSelect= when editing an identity, and pass onRemove only where removal is supported. Explicit hue, including null, wins over the remembered preference. Give preferenceKey an account/workspace-scoped namespace. Opening never commits a preference. The catalogue has 160 distinct outline icons; labels, pinned upstream tags and reviewed aliases power local ranked search.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
onValueChange* | (value: IconValue) => void | — | Called after choosing a glyph. |
className | string | — | Additional panel classes. |
closeOnSelect | boolean | true | Close after choosing a glyph. |
disabled | boolean | false | Disable the trigger. |
hue | AvatarHue | null | — | Explicit saved hue. Undefined permits a remembered default; null is explicit No colour. |
modes | readonly IconPickerMode[] | ["icon", "emoji"] | Enabled modes; one mode omits tabs. |
onHueChange | ((hue: AvatarHue | null) => void) | — | Called on explicit hue selection or committing a remembered hue with a new icon. |
onOpenChange | ((open: boolean) => void) | — | Popup state callback. |
onRemove | (() => void) | — | Optional Remove action. |
open | boolean | — | Controlled popup state. |
preferenceKey | string | — | Namespace for account/workspace-scoped convenience preferences. |
ref | React.Ref<HTMLButtonElement> | — | Ref to the trigger. |
showRecents | boolean | true | Display recent choices. |
size | "default" | "sm" | "default" | Grid density. |
trigger | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | — | Custom trigger composed through Base UI. |
triggerLabel | string | "Choose an icon" | Accessible trigger name. |
value | IconValue | null | null | Chosen icon or emoji. |
Data attributes and CSS variables on IconPicker
| Attribute | Values |
|---|---|
data-checked | mirrors a prop or state value |
data-size | mirrors a prop or state value |
data-slot | "icon-picker" | "icon-picker-colours" | "icon-picker-footer" | "icon-picker-swatch" | "icon-picker-tabs" |
Accessibility
| Contract | States tested |
|---|---|
| Behaviour | default, active, disabled, error, pressed, range, selected, success |
| Accessibility | disabled, keyboard, labeled, pressed |
| Visual | default, hover, error, success |
Search is labelled, cells use roving keyboard navigation across visual rows, and result counts use the shared announcer. The footer swatches form one "Icon colour" radiogroup with a single tab stop and arrow-key navigation. Keyboard focus uses the global DS tint; selection uses a persistent 1px primary border — on a grid cell and, rounded, on the checked swatch.