Search in IconDropdown
This page explains how IconDropdown.tsx actually uses the keywords.json files described in Keywords & Translations — from import, to attaching keywords to each icon, to matching what the user types.
Generating keywords.json files does nothing on its own. Every icon set
needs to be explicitly wired into IconDropdown.tsx for its keywords to
actually be searchable — this page covers that wiring.
1. The keywords field on IconOption
Every icon in the dropdown is an IconOption. It has one new, optional field:
interface IconOption {
value: string;
label: string;
displayLabel: string;
iconUrl: string;
keywords?: string[]; // extra search terms - not shown in the UI
}Optional on purpose: an icon set that hasn’t been covered yet (or an icon with no matching word/override) simply has keywords: undefined, and search silently falls back to matching on label only — exactly like before this feature existed.
2. The single filter function: matchesSearch
Before this feature, the filter logic (label.toLowerCase().includes(term)) was duplicated in three places in the file. It’s now one function, used everywhere:
const matchesSearch = (icon: IconOption, term: string): boolean => {
const lower = term.toLowerCase();
if (icon.label.toLowerCase().includes(lower)) return true;
return icon.keywords?.some((kw) => kw.toLowerCase().includes(lower)) ?? false;
};An icon matches if the typed term is found in its technical label, OR in any of its keywords.
3. Wiring per icon library — 4 different key formats
Each icon library stores its mapping.json keys a bit differently, so each one attaches keywords a bit differently too. All four end up doing the same thing conceptually: look up the icon’s key in the imported keywords object, attach the result.
| Library | Icon key example | How keywords is looked up |
|---|---|---|
| font-awesome | "fa fa-adjust" | iconsFontAwesomeKeywords[name] — direct |
| glyphicons-v1 | "glyphicons glyphicons-user-add" | v1KeywordSets[prefix]?.[name] — one keyword file per sub-library (basic, halflings, filetypes, socials), picked by prefix |
| glyphicons-v2 | "glyphicons-v2/halflings verify-check" | v2KeywordSets[prefix]?.[name] — same idea, prefix is "glyphicons-v2/basic" etc. |
| phpc | "phpc/favicons/admin admin-16-ico" | phpcKeywords[key] — direct, see below |
Why phpc is different: one combined file instead of 46
phpc has 46 separate keywords.json files (one per icon subfolder). Importing all 46 in this component would mean 46 import statements. Instead, script/generate-keywords.py combines them at generation time into a single icons/phpc/keywords-with-filepath.json, keyed exactly like icons/phpc/mapping-with-filepath.json already is ("phpc/favicons/admin admin-16-ico"). That means:
import iconsPHPCKeywords from "../../icons/phpc/keywords-with-filepath.json";
// ...
const phpcKeywords = iconsPHPCKeywords as Record<string, string[]>;
Object.entries(iconsPHPC).forEach(([key, path]) => {
iconsArray.push({
value: key,
// ...
keywords: phpcKeywords[key], // same key, no need to split/rebuild it
});
});One import, one direct lookup — no per-prefix table needed, unlike v1/v2.
Full runtime trace, on a real icon
This is the exact trace covered when we built this feature, kept here for reference.
Icon: phpc/favicons/admin admin-16-ico → keywords: ["administration 16 ico", "admin16ico"]
The icon’s technical name never contains “administration” — only keywords-with-filepath.json, consulted at step 1, made the match possible.
Related pages
- How IconDropdown Works — the rest of the component: props, data loading, pagination, selection
- Keywords & Translations — where
keywords.jsonfiles come from - Adding New Icons — what happens (and what’s required) when you add a new icon