An icon picker is a text field that holds a Material Symbols name. A panel opens on top of it with instant search over all icons, Recent and Popular.
Tokens, dimensions, states and requirements. There is no Figma component: values come from the live token package and the specification skill.
Resolved from the live token package.
| State | Part | Token | Value |
|---|
Open points: no Figma component. The dimensions were decided in code. Colors, shadow and spacing in the picker are tokens only.
| Part | Value |
|---|---|
| Panel | Top of the field, same width, 12px padding |
| Search box | 42px high |
| Icon cell | 40px |
| Grid height | 176px (it scrolls) |
| Results | Up to 60 |
The same on every breakpoint.
Padding of the open panel. The shaded area is the 12px padding; the lines show its value. The panel is a static copy here.
| Attribute | Value |
|---|---|
| Panel padding | 12px on every side |
| Gap between the parts | 12px |
| Search box | 42px high, full width, 1px border |
| Icon cell | 40px high; the grid fits as many 40px columns as the width allows |
| Gap between cells | 4px |
| Grid | Up to 176px high, then it scrolls |
| Panel position | Top and sides 12px outside the field (top: -12px; left: -12px; right: -12px) |
| Corners | Square |
The same padding and gaps as spacing tokens.
| Part | Value |
|---|---|
| Panel padding and gap between the parts | space-12 |
| Gap between icon cells | space-4 |
| Search box padding | space-8 above and below, space-12 left and right |
The field is an Input and has the Input states. The panel and its icons have the states below. Hover and focus come from the browser and are described here.
| State | Part | Look |
|---|
| Part | Size / line height | Letter spacing | Weight |
|---|---|---|---|
| Search text | 16/24 | inherited | Regular |
| Group label | 12/18 | 0.24px | 600 |
| Icon | 24px Material Symbols, Outlined, Fill 0, Weight 300, Grade 0 | — | — |
| No match message | 14/20 | inherited | Regular |
The sizes are set in the script’s CSS in pixels. Open point: bind them to type tokens if the picker moves into a design token pass.
| Element | Class | Notes |
|---|---|---|
| Anchor | ip-wrap | Added to the .input-wrap of the field, or to a wrapper made around a bare input. |
| Panel | ip-panel | Hidden until the field opens. ip-mouse when opened with the mouse. |
| Search box | ip-search | A text input with aria-label="Search icons". |
| Group label | ip-label | Recent, Popular or Results. |
| Grid and cell | ip-grid, ip-btn | aria-pressed on the picked icon. |
| No match | ip-empty | The message under Results. |
There is one type.
The panel has the width of the field.
| Topic | Detail |
|---|---|
| Script | components/icon-picker/icon-picker.js. It loads icon-picker-data.js (all names and search tags, sorted by popularity) from its own folder 0.5 s after page load. Never add the data file by hand. |
| Data size | 1.4 MB, a copy of the Google Fonts Material Symbols metadata (August 2026). Fine for a prototype; serve a smaller list or search on the server in production. |
| Refresh | Download https://fonts.google.com/metadata/icons?key=material_symbols&incomplete=true and rewrite the file as window.ECO_ICONS=[[name,"tags"],…] sorted by popularity. |
| Font | The page needs the Material Symbols Outlined font (in both page templates). |
None. The panel opens and closes at once, with no transition and no animation.
| Moment | What happens |
|---|---|
| Click or Tab into the field | A panel opens on top of the field (same width, 12px padding). The search box comes first and has focus. |
| Search box empty | Recent (the last 8 picks, kept in localStorage and shared by all pages) and Popular (the top 60). |
| Typing | Instant search over all icons. Ranked: name starts with, then a name word starts with, then a tag word starts with; each group by popularity. Up to 60 shown; the header says Results (n). No match: “No icons match …”. |
| Click an icon | The name goes into the field, an input event fires, the panel closes and focus returns to the field. |
| Esc, click outside | Closes without changing the value. |
| Focus ring on the search box | Hidden when the panel was opened with the mouse, shown when opened with Tab. |
| Topic | Requirement |
|---|---|
| Field | A visible label with for and id, as for every Input. |
| Search box | aria-label="Search icons". |
| Icons | Real button elements named by the icon name (aria-label and title), with aria-pressed on the picked one. The glyph is aria-hidden="true". |
| Focus | 2px ring border-focus on the search box and the icons on keyboard focus (WCAG 2.4.7, 1.4.11). |
| Dismissal | Esc closes the panel and keeps the value. |
| Open point | The panel is not announced as a dialog or a combobox listbox. Open point: add the roles if the picker is used outside back-office forms. |