Skip to main content

Icon Explorer

Dev-only Import

IconExplorer and related utilities are exported from rn-iconify/dev to keep production bundles lean.

The Icon Explorer provides a powerful interface for browsing, searching, and discovering icons from over 200+ icon sets.

Basic Usageโ€‹

import { IconExplorer } from 'rn-iconify/dev';

function App() {
return (
<IconExplorer
onIconSelect={(iconName) => {
console.log('Selected:', iconName);
}}
/>
);
}

Propsโ€‹

IconExplorer extends ExplorerConfig with additional display props:

PropTypeDefaultDescription
visiblebooleantrueWhether the explorer is visible
onClose() => void-Callback when explorer is closed
styleViewStyle-Container style
iconSetsstring[]allIcon set prefixes to include
initialQuerystring''Initial search query
maxResultsnumber100Maximum search results to display
previewPartial<PreviewConfig>-Preview configuration
onIconSelect(iconName: string) => void-Called when an icon is selected
onCopyCode(code: string) => void-Called when code is copied
keyboardShortcutsbooleantrueEnable keyboard shortcuts

Filter by Icon Setโ€‹

Limit to specific icon sets:

<IconExplorer
iconSets={['mdi', 'heroicons']}
onIconSelect={(icon) => console.log(icon)}
/>

Custom Stylingโ€‹

<IconExplorer
style={{
backgroundColor: '#f5f5f5',
borderRadius: 12,
}}
preview={{
sizes: [24, 32, 48],
colors: ['#333', '#6366f1', '#ef4444'],
}}
onIconSelect={handleSelect}
/>

useExplorer Hookโ€‹

Access explorer state and actions programmatically:

import { useExplorer } from 'rn-iconify/dev';

function CustomExplorer() {
const {
// State
query,
results, // SearchResult[] - not string[]!
isLoading,
selectedIcon,
activeIconSet,
iconSets,
totalIcons,
collectionsLoaded,
// Actions
setQuery,
selectIcon, // not setSelectedIcon
filterByIconSet, // not setActiveIconSet
} = useExplorer();

return (
<View>
<TextInput
value={query}
onChangeText={setQuery}
placeholder="Search icons..."
/>

{isLoading ? (
<ActivityIndicator />
) : (
<FlatList
data={results}
keyExtractor={(item) => item.fullName}
renderItem={({ item }) => (
<IconItem
name={item.fullName}
onPress={() => selectIcon(item.fullName)}
/>
)}
/>
)}
</View>
);
}

Return Valuesโ€‹

PropertyTypeDescription
querystringCurrent search query
setQuery(query: string) => voidUpdate search query
resultsSearchResult[]Search results (SearchResult objects)
isLoadingbooleanWhether search is in progress
selectedIconstring | nullCurrently selected icon
selectIcon(icon: string | null) => voidSelect an icon
activeIconSetstring | nullCurrently filtered icon set
filterByIconSet(prefix: string | null) => voidFilter by icon set
iconSetsIconSetInfo[]Available icon sets
totalIconsnumberTotal icons available
collectionsLoadedbooleanWhether collections have loaded

Icon Set Functionsโ€‹

getAllIconSetsโ€‹

Get information about all available icon sets:

import { getAllIconSets } from 'rn-iconify/dev';

const iconSets = getAllIconSets();

iconSets.forEach(set => {
console.log({
prefix: set.prefix, // 'mdi'
name: set.name, // 'Material Design Icons'
total: set.total, // 7000
author: set.author, // 'Austin Andrews' (string)
license: set.license, // 'Apache 2.0' (string)
category: set.category, // 'general'
samples: set.samples, // ['home', 'account', 'settings', ...]
});
});

getIconSetByPrefixโ€‹

Get details for a specific icon set:

import { getIconSetByPrefix } from 'rn-iconify/dev';

const mdi = getIconSetByPrefix('mdi');

if (mdi) {
console.log(`${mdi.name} has ${mdi.total} icons`);
}

getIconSetsByCategoryโ€‹

Filter icon sets by category:

import { getIconSetsByCategory } from 'rn-iconify/dev';

// Get all general-purpose icon sets
const generalSets = getIconSetsByCategory('general');

// Get all brand icon sets
const brandSets = getIconSetsByCategory('brand');

// Get all emoji icon sets
const emojiSets = getIconSetsByCategory('emoji');

// Get all flag icon sets
const flagSets = getIconSetsByCategory('flags');

// Get all weather icon sets
const weatherSets = getIconSetsByCategory('weather');

Available categories:

  • 'general' - General purpose icons (MDI, Heroicons, etc.)
  • 'brand' - Brand and social media icons
  • 'emoji' - Emoji and emoticon sets
  • 'flags' - Maps and flag icons
  • 'weather' - Weather icons
  • 'other' - Other themed icon sets

searchIconSetsโ€‹

Search for icon sets by name or prefix:

import { searchIconSets } from 'rn-iconify/dev';

// Search by name
const results = searchIconSets('material');
// Returns: [mdi, material-symbols, ic, ...]

// Search by prefix
const heroResults = searchIconSets('hero');
// Returns: [heroicons]

Code Generationโ€‹

generateImportStatementโ€‹

Generate import code for an icon:

import { generateImportStatement } from 'rn-iconify/dev';

const importCode = generateImportStatement('mdi:home');
// "import { Mdi } from 'rn-iconify';"

const heroImport = generateImportStatement('heroicons:user');
// "import { Heroicons } from 'rn-iconify';"

generateIconJSXโ€‹

Generate JSX code for an icon:

import { generateIconJSX } from 'rn-iconify/dev';

const jsx = generateIconJSX('mdi:home', 24, '#333');
// '<Mdi name="home" size={24} color="#333" />'

const customJsx = generateIconJSX('heroicons:user', 32, 'blue');
// '<Heroicons name="user" size={32} color="blue" />'

Parameters:

ParameterTypeDefaultDescription
iconNamestring-Full icon name (e.g., 'mdi:home')
sizenumber24Icon size
colorstring'currentColor'Icon color

Pre-defined list of popular icon sets with full metadata:

import { POPULAR_ICON_SETS } from 'rn-iconify/dev';

// Array of IconSetInfo objects
console.log(POPULAR_ICON_SETS);
// [{ prefix: 'mdi', name: 'Material Design Icons', total: 7000, ... }, ...]

// Access icon set data directly
POPULAR_ICON_SETS.forEach(set => {
console.log(`${set.name} (${set.prefix}): ${set.total} icons`);
});

// Use to display popular icon sets
function PopularIconSets() {
return (
<View>
{POPULAR_ICON_SETS.map(set => (
<IconSetCard key={set.prefix} iconSet={set} />
))}
</View>
);
}

ExplorerContextโ€‹

Access explorer state from any component:

import { ExplorerContext, useExplorerContext } from 'rn-iconify/dev';

// Using the hook (recommended)
function IconGrid() {
const { results, selectedIcon, selectIcon } = useExplorerContext();

return (
<FlatList
data={results}
keyExtractor={(item) => item.fullName}
renderItem={({ item }) => (
<Pressable onPress={() => selectIcon(item.fullName)}>
<Icon name={item.fullName} />
</Pressable>
)}
/>
);
}

// Using context directly
function CustomComponent() {
const context = useContext(ExplorerContext);

if (!context) {
return <Text>Not inside IconExplorer</Text>;
}

return <Text>Found {context.results.length} icons</Text>;
}

Context Valueโ€‹

interface ExplorerContextValue {
// State
query: string;
results: SearchResult[];
selectedIcon: string | null;
activeIconSet: string | null;
isLoading: boolean;
error: string | null;
previewSize: number;
previewColor: string;
iconSets: IconSetInfo[];
totalIcons: number;
collectionsLoaded: boolean;

// Actions
setQuery: (query: string) => void;
selectIcon: (iconName: string | null) => void;
filterByIconSet: (prefix: string | null) => void;
setPreviewSize: (size: number) => void;
setPreviewColor: (color: string) => void;
copyIconCode: (iconName: string, format?: 'jsx' | 'import') => void;
reset: () => void;
}

IconSetInfo Typeโ€‹

interface IconSetInfo {
/** Icon set prefix (e.g., 'mdi') */
prefix: string;

/** Display name (e.g., 'Material Design Icons') */
name: string;

/** Total number of icons */
total: number;

/** Author name (e.g., 'Austin Andrews') */
author?: string;

/** License name (e.g., 'Apache 2.0', 'MIT') */
license?: string;

/** Sample icon names for preview */
samples?: string[];

/** Icon set category */
category?: 'general' | 'brand' | 'emoji' | 'flags' | 'weather' | 'other';
}

Example Dataโ€‹

const mdiIconSet: IconSetInfo = {
prefix: 'mdi',
name: 'Material Design Icons',
total: 7000,
author: 'Austin Andrews',
license: 'Apache 2.0',
samples: ['home', 'account', 'settings', 'menu', 'close'],
category: 'general',
};

Building a Custom Explorerโ€‹

Create a fully custom icon explorer:

import {
useExplorer,
getAllIconSets,
getIconSetByPrefix,
generateIconJSX,
POPULAR_ICON_SETS,
} from 'rn-iconify/dev';

function CustomIconExplorer({ onSelect }) {
const {
query,
setQuery,
results,
isLoading,
activeIconSet,
filterByIconSet,
} = useExplorer();

const [copied, setCopied] = useState(false);

const handleCopyCode = async (iconName) => {
const jsx = generateIconJSX(iconName, 24);
await Clipboard.setString(jsx);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};

return (
<View style={styles.container}>
{/* Search */}
<TextInput
value={query}
onChangeText={setQuery}
placeholder="Search 200,000+ icons..."
style={styles.searchInput}
/>

{/* Icon Set Filter */}
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
<Chip
selected={!activeIconSet}
onPress={() => filterByIconSet(null)}
>
All
</Chip>
{POPULAR_ICON_SETS.map(set => (
<Chip
key={set.prefix}
selected={activeIconSet === set.prefix}
onPress={() => filterByIconSet(set.prefix)}
>
{set.name}
</Chip>
))}
</ScrollView>

{/* Results */}
{isLoading ? (
<ActivityIndicator size="large" />
) : (
<FlatList
data={results}
numColumns={5}
keyExtractor={(item) => item.fullName}
renderItem={({ item }) => (
<Pressable
onPress={() => onSelect(item.fullName)}
onLongPress={() => handleCopyCode(item.fullName)}
style={styles.iconCell}
>
<Icon name={item.fullName} size={32} />
<Text style={styles.iconName}>
{item.name}
</Text>
</Pressable>
)}
/>
)}

{copied && (
<Toast message="Code copied to clipboard!" />
)}
</View>
);
}

Integration Examplesโ€‹

With Modalโ€‹

function IconPickerModal({ visible, onClose, onSelect }) {
return (
<Modal visible={visible} animationType="slide">
<SafeAreaView style={{ flex: 1 }}>
<View style={styles.header}>
<Text style={styles.title}>Select Icon</Text>
<Pressable onPress={onClose}>
<Mdi name="close" size={24} />
</Pressable>
</View>

<IconExplorer
onIconSelect={(icon) => {
onSelect(icon);
onClose();
}}
/>
</SafeAreaView>
</Modal>
);
}

With Formโ€‹

function IconFormField({ value, onChange }) {
const [showPicker, setShowPicker] = useState(false);

return (
<View>
<Text>Select an icon:</Text>

<Pressable
onPress={() => setShowPicker(true)}
style={styles.iconPreview}
>
{value ? (
<Icon name={value} size={48} />
) : (
<Text>Tap to select</Text>
)}
</Pressable>

<IconPickerModal
visible={showPicker}
onClose={() => setShowPicker(false)}
onSelect={onChange}
/>
</View>
);
}

Best Practicesโ€‹

1. Lazy Load Collectionsโ€‹

function App() {
const [explorerReady, setExplorerReady] = useState(false);

// Only load explorer when needed
return (
<View>
{explorerReady ? (
<IconExplorer onIconSelect={handleSelect} />
) : (
<Button
title="Browse Icons"
onPress={() => setExplorerReady(true)}
/>
)}
</View>
);
}

2. Cache Search Resultsโ€‹

function useSearchWithCache() {
const cache = useRef(new Map());
const { setQuery, results } = useExplorer();

const search = useCallback((query) => {
if (cache.current.has(query)) {
return cache.current.get(query);
}

setQuery(query);
// Results will update via hook
}, [setQuery]);

useEffect(() => {
if (query && results.length > 0) {
cache.current.set(query, results);
}
}, [query, results]);

return { search, results };
}

3. Debounce Search Inputโ€‹

function DebouncedSearch() {
const [input, setInput] = useState('');
const { setQuery } = useExplorer();

useEffect(() => {
const timer = setTimeout(() => {
setQuery(input);
}, 300);

return () => clearTimeout(timer);
}, [input, setQuery]);

return (
<TextInput
value={input}
onChangeText={setInput}
placeholder="Search..."
/>
);
}

Next Stepsโ€‹