npm package: @johnmanitaras/react-icon-picker
Description: A beautiful, searchable icon picker component with 180+ Lucide React icons
Author: Your Name
Latest version: 1.1.7

# React Icon Picker

A beautiful, searchable icon picker component built with React, TypeScript, and Tailwind CSS. Features 180+ carefully curated Lucide React icons with intelligent search and category filtering.

![Icon Picker Demo](https://via.placeholder.com/800x400/3B82F6/FFFFFF?text=React+Icon+Picker)

## Features

- 🎨 **Beautiful Design** - Modern, accessible interface with smooth animations
- 🔍 **Smart Search** - Search by icon name, keywords, or category
- 📱 **Responsive** - Works perfectly on desktop, tablet, and mobile
- ⌨️ **Keyboard Support** - Full keyboard navigation and shortcuts
- 🏷️ **Category Filtering** - Browse icons by logical categories
- 🎯 **TypeScript** - Full type safety and IntelliSense support
- ♿ **Accessible** - WCAG compliant with proper ARIA labels
- 🚀 **Production Ready** - Optimized performance and error handling

## Installation

```bash
npm install @your-username/react-icon-picker
```

### Peer Dependencies

Make sure you have the required peer dependencies installed:

```bash
npm install react react-dom
```

## Setup

### 1. Import the Component and Styles

```tsx
import { IconPicker } from '@your-username/react-icon-picker';
import '@your-username/react-icon-picker/styles.css';
```

### 2. Design System Integration

This component is designed to integrate with your app's existing design system. It uses:

- **Your app's colors, typography, and styling** for visual consistency
- **Layout-isolated classes** (`icon-picker-*`) for reliable positioning

#### Required CSS Classes in Your App

The component expects these standard CSS classes to be available in your app:

```css
/* Button styles */
.btn-primary { /* Primary button styling */ }
.btn-secondary { /* Secondary button styling */ }

/* Form elements */
.input { /* Input field styling */ }

/* Card layout */
.card { /* Card container */ }
.card-header { /* Card header */ }
.card-body { /* Card body */ }

/* Badges */
.badge { /* Base badge */ }
.badge-info { /* Info badge variant */ }

/* Theme colors */
.text-theme-primary { /* Primary text color */ }
.bg-theme-primary { /* Primary background color */ }
.border-theme-primary { /* Primary border color */ }
.text-white { /* White text */ }
```

#### CSS Custom Properties (Optional)

For enhanced theming, define these CSS variables in your app:

```css
:root {
  --color-primary: #1d4ed8;
  --color-text: #111827;
  --color-textSecondary: #6b7280;
  --color-border: #e5e7eb;
  --color-background: #f9fafb;
  
  /* Button styling */
  --button-height: 2.5rem;
  --button-padding: 0.75rem 1rem;
  --button-borderRadius: 0.375rem;
  --button-fontSize: 0.875rem;
  --button-fontWeight: 500;
  --button-transition: all 150ms ease;
  
  /* Input styling */
  --input-height: 2.5rem;
  --input-padding: 0.5rem 1rem;
  --input-borderColor: #d3d3d6;
  --input-borderRadius: 0.375rem;
  --input-background: #ffffff;
}
```

#### For JetSetGo Apps

If you're using this component in a JetSetGo app, simply import your standard.css before the component:

```tsx
import './standard.css'; // Your app's design system
import '@your-username/react-icon-picker/styles.css';
```

## Usage

### Basic Usage

```tsx
import React, { useState } from 'react';
import { IconPicker } from '@your-username/react-icon-picker';
import '@your-username/react-icon-picker/styles.css';

function MyComponent() {
  const [selectedIcon, setSelectedIcon] = useState<string>('');
  const [isPickerOpen, setIsPickerOpen] = useState(false);

  return (
    <div>
      {/* Your custom trigger button */}
      <button 
        onClick={() => setIsPickerOpen(true)}
        className="btn-secondary"
      >
        {selectedIcon ? `Selected: ${selectedIcon}` : 'Choose an icon'}
      </button>
      
      {/* Icon picker modal */}
      <IconPicker
        isOpen={isPickerOpen}
        onClose={() => setIsPickerOpen(false)}
        selectedIcon={selectedIcon}
        onIconSelect={setSelectedIcon}
      />
    </div>
  );
}
```

### Advanced Usage with Icon Display

```tsx
import React, { useState } from 'react';
import { IconPicker, getIconByName } from '@your-username/react-icon-picker';
import '@your-username/react-icon-picker/styles.css';

function MyComponent() {
  const [selectedIcon, setSelectedIcon] = useState<string>('Heart');
  const [isPickerOpen, setIsPickerOpen] = useState(false);

  const iconData = selectedIcon ? getIconByName(selectedIcon) : null;
  const IconComponent = iconData?.component;

  return (
    <div className="space-y-4">
      {/* Custom trigger with icon preview */}
      <button 
        onClick={() => setIsPickerOpen(true)}
        className="btn-secondary flex items-center gap-3"
      >
        {IconComponent && (
          <IconComponent size={20} className="text-theme-primary" />
        )}
        {selectedIcon || 'Choose an icon'}
      </button>
      
      {/* Icon picker modal */}
      <IconPicker
        isOpen={isPickerOpen}
        onClose={() => setIsPickerOpen(false)}
        selectedIcon={selectedIcon}
        onIconSelect={setSelectedIcon}
      />
      
      {/* Display selected icon */}
      {IconComponent && (
        <div className="card card-body">
          <div className="flex items-center gap-3">
            <IconComponent size={24} className="text-theme-primary" />
            <span className="font-medium">{selectedIcon}</span>
          </div>
        </div>
      )}
    </div>
  );
}
```

### Form Integration

```tsx
import React, { useState } from 'react';
import { IconPicker, getIconByName } from '@your-username/react-icon-picker';
import '@your-username/react-icon-picker/styles.css';

function CreateItemForm() {
  const [formData, setFormData] = useState({
    name: '',
    icon: '',
    description: ''
  });
  const [isPickerOpen, setIsPickerOpen] = useState(false);

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    console.log('Form data:', formData);
  };

  const iconData = formData.icon ? getIconByName(formData.icon) : null;
  const IconComponent = iconData?.component;

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      <div>
        <label className="block text-sm font-medium mb-2">
          Item Name
        </label>
        <input
          type="text"
          value={formData.name}
          onChange={(e) => setFormData(prev => ({ ...prev, name: e.target.value }))}
          className="input"
        />
      </div>

      <div>
        <label className="block text-sm font-medium mb-2">
          Icon
        </label>
        <button
          type="button"
          onClick={() => setIsPickerOpen(true)}
          className="input flex items-center gap-2 cursor-pointer"
        >
          {IconComponent ? (
            <>
              <IconComponent size={16} className="text-theme-primary" />
              <span>{formData.icon}</span>
            </>
          ) : (
            <span className="text-gray-500">Select an icon</span>
          )}
        </button>
        
        <IconPicker
          isOpen={isPickerOpen}
          onClose={() => setIsPickerOpen(false)}
          selectedIcon={formData.icon}
          onIconSelect={(icon) => setFormData(prev => ({ ...prev, icon }))}
        />
      </div>

      <button
        type="submit"
        className="btn-primary"
      >
        Create Item
      </button>
    </form>
  );
}
```

## API Reference

### IconPicker Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `isOpen` | `boolean` | - | Controls whether the modal is open |
| `onClose` | `() => void` | - | Callback when modal should close |
| `selectedIcon` | `string` | `undefined` | Currently selected icon name |
| `onIconSelect` | `(iconName: string) => void` | - | Callback when an icon is selected |

### Utility Functions

#### `getIconByName(name: string)`

Returns the icon data for a given icon name.

```tsx
import { getIconByName } from '@your-username/react-icon-picker';

const iconData = getIconByName('Heart');
if (iconData) {
  const IconComponent = iconData.component;
  // Use IconComponent in your JSX
}
```

#### `searchIcons(query: string)`

Returns filtered icons based on search query.

```tsx
import { searchIcons } from '@your-username/react-icon-picker';

const results = searchIcons('arrow');
// Returns all icons matching "arrow" in name, keywords, or category
```

### Icon Data Structure

```typescript
interface IconData {
  name: string;
  component: React.ComponentType<{ size?: number; className?: string }>;
  keywords: string[];
  category: string;
}
```

## Available Categories

- **Actions** - Interactive elements (check, plus, edit, etc.)
- **Navigation** - Directional and movement icons
- **Communication** - Messaging and social icons
- **Business** - Professional and office icons
- **Transport** - Vehicles and travel icons
- **Media** - Audio, video, and entertainment icons
- **Files** - Document and file management icons
- **Interface** - UI elements and controls
- **Security** - Protection and privacy icons
- **People** - User and person icons
- **Location** - Maps and places icons
- **Weather** - Climate and conditions icons
- **Health** - Medical and wellness icons
- **Social** - Social media and interaction icons
- **Technology** - Devices and digital icons
- **Lifestyle** - Personal and daily life icons
- **Design** - Creative and artistic icons
- **Office** - Business and workplace icons
- **Alerts** - Warning and notification icons

## Styling

The component uses a **hybrid styling approach** for maximum compatibility:

- **Visual styling** (colors, typography) inherits from your app's design system
- **Layout styling** uses isolated `icon-picker-*` classes for reliable positioning

### Design System Integration

The component automatically adapts to your app's:
- Primary colors via `.text-theme-primary`, `.bg-theme-primary`
- Button styles via `.btn-primary`, `.btn-secondary`
- Form styles via `.input`, `.card`, `.badge`
- Typography and spacing from CSS custom properties

### Layout Customization

To customize layout without breaking functionality, override these classes:

```css
/* Modal sizing */
.icon-picker-content {
  max-width: 600px; /* Default: 480px */
  max-height: 700px; /* Default: 560px */
}

/* Icon grid layout */
.icon-picker-grid {
  grid-template-columns: repeat(6, 1fr); /* Default: 4-5 columns */
  gap: 12px; /* Default: 8px */
}

/* Icon card sizing */
.icon-picker-item {
  height: 64px; /* Default: 56px */
}
```

### CSS Classes Reference

**Layout Classes (safe to customize):**
- `.icon-picker-modal` - Modal overlay positioning
- `.icon-picker-content` - Modal container sizing
- `.icon-picker-grid` - Icon grid layout
- `.icon-picker-item` - Icon button dimensions
- `.icon-picker-header` - Header padding/layout
- `.icon-picker-body` - Body scrolling/padding
- `.icon-picker-footer` - Footer layout

**Visual Classes (inherit from your app):**
- Uses `.btn-primary`, `.btn-secondary` for buttons
- Uses `.input` for search field
- Uses `.card*` for modal styling
- Uses `.badge*` for category pills
- Uses `.text-theme-primary` etc. for colors

## TypeScript Support

The package includes full TypeScript definitions. All components and utilities are fully typed for the best development experience.

```tsx
import type { IconPickerProps, IconData } from '@your-username/react-icon-picker';
```

## Browser Support

- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+

## Architecture

### CSS Isolation Strategy

This component uses a **safe namespacing approach** to prevent CSS conflicts:

```css
/* Layout Control - Component-specific */
.icon-picker-modal { /* Fixed positioning */ }
.icon-picker-grid { /* Grid layout */ }
.icon-picker-item { /* Icon sizing */ }

/* Visual Styling - Inherits from your app */
.btn-secondary { /* Your button styles */ }
.text-theme-primary { /* Your brand colors */ }
.input { /* Your form styling */ }
```

**Benefits:**
- Component layout is **bulletproof** against host app CSS
- Visual styling **automatically matches** your design system
- No CSS conflicts or style bleeding
- Works with any CSS framework (Bootstrap, Tailwind, etc.)

## Performance

- **Bundle size**: ~24KB CSS + ~19KB JS (gzipped ~5KB each)
- **Runtime performance**: Optimized with React.memo and efficient filtering
- **CSS efficiency**: Minimal custom CSS, inherits from parent app
- **Accessibility**: Full keyboard navigation and screen reader support

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests if applicable
5. Submit a pull request

## License

MIT License - feel free to use in personal and commercial projects.

## Publishing to NPM

To publish this package to NPM:

1. **Update package.json**: Replace `@your-username/react-icon-picker` with your actual npm username/organization
2. **Build the library**: Run `npm run build:lib`
3. **Login to NPM**: Run `npm login`
4. **Publish**: Run `npm publish`

### Publishing Steps

```bash
# 1. Update the package name in package.json
# 2. Build the library
npm run build:lib

# 3. Login to NPM (if not already logged in)
npm login

# 4. Publish to NPM
npm publish

# For scoped packages (recommended)
npm publish --access public
```

## Demo

A live demo is available at: [Your Demo URL]

---

Built with ❤️ using React, TypeScript, and Tailwind CSS