npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

lucide-icon-picker

v1.0.1

Published

Flexible, composable React icon picker for Lucide icons. No extra UI library required.

Downloads

219

Readme

npm License: MIT React lucide-react



  • Search across 1500+ Lucide icons with live filtering
  • Paginated icon grid — no lag, no virtual-scroll dependency
  • Optional color picker, size slider, and stroke width slider — all hidden by default
  • Live preview strip inside the panel before confirming selection
  • Auto-flip placement — repositions when near the viewport edge
  • Mobile drawer mode — slides up from the bottom on narrow screens
  • Headless mode — plug in your own popup component
  • <RenderIcon /> renders any icon by name safely — returns null for unknown names, never crashes
  • Zero runtime dependencies beyond React and lucide-react
  • Full CSS variable system for theming without overrides
  • Works with CJS and ESM bundlers

npm install lucide-icon-picker

Peer dependencies — install if not already present:

npm install react react-dom lucide-react

Import the stylesheet once in your app entry point:

import 'lucide-icon-picker/dist/lucide-icon-picker.css';

Quick Start

The simplest possible usage — three lines:

import IconPicker from 'lucide-icon-picker';
import { useState } from 'react';

function App() {
  const [icon, setIcon] = useState('Star');

  return <IconPicker value={icon} onChange={setIcon} />;
}

Click the trigger, search, pick. Done.


Render an Icon Anywhere

import { RenderIcon } from 'lucide-icon-picker';

// Renders the icon by name — no configuration needed
<RenderIcon name="Star" />

// With custom appearance
<RenderIcon name="Heart" color="#e11d48" size={32} stroke={1.5} />

// Safe with any input — returns null instead of crashing
<RenderIcon name={untrustedUserInput} size={20} />

stroke is a short alias for strokeWidth. Both work.


With Optional Sections

import IconPicker from 'lucide-icon-picker';

function App() {
  const [config, setConfig] = useState({
    name:        'Star',
    color:       '#3b82f6',
    size:        24,
    strokeWidth: 2,
  });

  return (
    <IconPicker
      value={config.name}
      onChange={(name, meta) =>
        setConfig(prev => ({ ...prev, name, ...meta }))
      }
      colorPicker
      sizeControl
      strokeControl
      defaultColor={config.color}
      defaultSize={config.size}
      defaultStroke={config.strokeWidth}
      placement="bottomLeft"
    />
  );
}

onChange receives (name, { color, size, strokeWidth }).


Headless Mode — Bring Your Own Popup

import { useIconPicker, IconPickerPanel, RenderIcon } from 'lucide-icon-picker';

function MyPicker({ value, onChange }) {
  const { open, setOpen, ...pickerProps } = useIconPicker({ value, onChange });

  return (
    <YourPopover
      open={open}
      onOpenChange={setOpen}
      content={<IconPickerPanel {...pickerProps} colorPicker />}
    >
      <button onClick={() => setOpen(v => !v)}>
        <RenderIcon name={value} size={16} />
        {value ?? 'Pick icon'}
      </button>
    </YourPopover>
  );
}

Programmatic Control via Ref

const ref = useRef(null);

<IconPicker ref={ref} value={icon} onChange={setIcon} />

ref.current.open();
ref.current.close();
ref.current.focus();

Non-JSX Contexts

For props that expect a React element rather than a component:

import { renderIcon } from 'lucide-icon-picker';

<Avatar icon={renderIcon('User', { size: 20 })} />

Props — IconPicker

| Prop | Type | Default | Description | |---|---|---|---| | value | string | — | Controlled icon name (PascalCase) | | onChange | (name, meta) => void | — | Called on selection | | colorPicker | boolean | false | Show color section | | sizeControl | boolean | false | Show size slider | | strokeControl | boolean | false | Show stroke width slider | | defaultColor | string | #000000 | Starting color | | defaultSize | number | 24 | Starting size in px | | defaultStroke | number | 2 | Starting stroke width | | placement | string | bottomLeft | bottomLeft bottomRight bottom topLeft topRight top left right | | panelWidth | number | 288 | Panel width in px | | gridColumns | number | 8 | Icons per row | | pageSize | number | 32 | Icons per page | | mobileMode | string | drawer | drawer panel none | | trigger | ReactNode | — | Replace the default trigger with your own element | | triggerClassName | string | — | Extra class on the default trigger button | | disabled | boolean | false | Disables the picker | | className | string | — | Class on the outer wrapper |


Props — RenderIcon

| Prop | Type | Default | Description | |---|---|---|---| | name | string | required | Lucide icon name in PascalCase | | color | string | #000000 | #hex rgb() hsl() | | size | number | 24 | px — clamped 8–128 | | strokeWidth | number | 2 | Clamped 0.5–4 | | stroke | number | — | Alias for strokeWidth |


CSS Customisation

Every visual detail is a CSS variable. Set them on .lip-wrapper or any ancestor:

/* Purple theme */
.lip-wrapper {
  --lip-primary:       #7c3aed;
  --lip-primary-bg:    #f3e8ff;
}

/* Wider panel, more columns */
.lip-wrapper {
  --lip-panel-width:   360px;
  --lip-grid-columns:  10;
}

/* Higher stacking order */
.lip-wrapper {
  --lip-z-index: 9999;
}

All variables:

| Variable | Default | Controls | |---|---|---| | --lip-primary | #3b82f6 | Accent — selected cell, focus ring, sliders | | --lip-primary-bg | #eff6ff | Selected cell background | | --lip-panel-width | 288px | Panel width | | --lip-grid-columns | 8 | Icon columns in grid | | --lip-panel-radius | 8px | Panel corner radius | | --lip-z-index | 1050 | Panel stacking order | | --lip-border | rgba(0,0,0,.10) | All borders | | --lip-text | #111827 | Primary text | | --lip-text-muted | #9ca3af | Labels and secondary text | | --lip-bg | #ffffff | Panel and trigger background | | --lip-bg-hover | #f3f4f6 | Icon cell hover state | | --lip-shadow | — | Panel drop shadow |

Target any .lip- class directly for surgical changes:

/* Circular selected cells */
.lip-grid__item--selected { border-radius: 50%; }

/* Square trigger */
.lip-trigger { border-radius: 0; }

/* Taller pagination buttons */
.lip-pagination__btn { height: 34px; }

| Platform | Support | Notes | |---|---|---| | React web | Supported | React 17 and 18 | | Next.js | Supported | App Router and Pages Router | | Remix | Supported | SSR-safe — DOM APIs are inside useEffect | | Vite + React | Supported | Recommended setup | | Create React App | Supported | | | Gatsby | Supported | Use dynamic import if needed | | Storybook | Supported | Import the CSS in .storybook/preview.js |


| Platform | Reason | |---|---| | React Native | This package uses lucide-react which renders SVG via the DOM. React Native uses lucide-react-native with a different rendering model — the two are incompatible. | | Expo | Same reason as React Native. |


Version Compatibility

| lucide-icon-picker | lucide-react | |---|---| | 1.x | >= 0.400.0 — tracks latest |

Icons added in newer versions of lucide-react appear automatically. Icons removed return null from <RenderIcon /> — nothing crashes.


License

MIT