# Iconify Setup and Usage

Complete guide to using Iconify icons with Grimoire v3.

---

## 🎯 Overview

Grimoire uses [Iconify](https://iconify.design/) for powerful, flexible icon management. You can:

- ✅ Use 200,000+ icons from popular icon sets
- ✅ Build custom icon bundles from your SVG files
- ✅ Create colored and monotone variants
- ✅ Use icons in any component
- ✅ Inherit text color for theme consistency

---

## 📦 Quick Start

### 1. Using Pre-Built Icon Collections

The simplest way to get started:

```bash
# Install Iconify JSON collections
pnpm add -D @iconify/json
```

```javascript
// main.ts
import { createApp } from 'vue';
import { GrimoirePlugin } from '@twentyfourg/grimoire/plugin';
import App from './App.vue';

// Import specific icon collections
import materialIcons from '@iconify/json/json/mdi.json';
import heroIcons from '@iconify/json/json/heroicons.json';

const app = createApp(App);

// Register icon collections
app.use(GrimoirePlugin, {
  icons: {
    mdi: materialIcons,
    heroicons: heroIcons,
  },
});

app.mount('#app');
```

```vue
<template>
  <GIcon icon="mdi:home" />
  <GIcon icon="heroicons:star" />
</template>

<script setup>
import { GIcon } from '@twentyfourg/grimoire';
</script>
```

---

## 🛠️ Building Custom Icon Bundles

Build optimized icon bundles from your SVG files.

### Step 1: Install Dependencies

```bash
pnpm add -D @iconify/tools @iconify/utils prettier
```

### Step 2: Organize Your Icons

```
project/
├── icons/
│   ├── plus.svg
│   ├── close.svg
│   ├── search.svg
│   └── arrow.svg
└── vite.config.ts
```

### Step 3: Configure Vite Plugin

```typescript
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { viteIconBundlePlugin } from '@twentyfourg/grimoire/build-tools';

export default defineConfig({
  plugins: [
    vue(),
    viteIconBundlePlugin({
      sources: [
        {
          type: 'folder',
          path: 'icons',
          prefix: 'app',
          variants: 'both', // Creates both colored and monotone versions
        },
      ],
      outputPath: 'src/icons-bundle.js',
      verbose: true, // See build logs
    }),
  ],
});
```

### Step 4: Register Icons

```typescript
// main.ts
import { createApp } from 'vue';
import { GrimoirePlugin } from '@twentyfourg/grimoire/plugin';
import { icons } from './icons-bundle.js'; // Auto-generated
import App from './App.vue';

const app = createApp(App);

app.use(GrimoirePlugin, { icons });

app.mount('#app');
```

### Step 5: Use Icons

```vue
<template>
  <!-- Colored version (original colors) -->
  <GIcon icon="app:plus" />

  <!-- Monotone version (inherits text color) -->
  <div class="text-blue-500">
    <GIcon icon="mono-app:plus" />
  </div>
</template>
```

---

## 🎨 Icon Variants

### `variants: 'both'` (Default)

Creates two versions of each icon:

- **Colored**: `app:icon-name` - Preserves original colors
- **Monotone**: `mono-app:icon-name` - All colors → `currentColor`

```vue
<template>
  <!-- Original colors -->
  <GIcon icon="app:logo" />

  <!-- Inherits parent text color -->
  <div class="text-red-500">
    <GIcon icon="mono-app:logo" />
    <!-- Red -->
  </div>
</template>
```

### `variants: 'colored'`

Only creates colored version with original colors:

```typescript
viteIconBundlePlugin({
  sources: [
    {
      type: 'folder',
      path: 'icons/logos',
      prefix: 'logo',
      variants: 'colored',
    },
  ],
});
```

### `variants: 'monotone'`

Only creates monotone version (great for UI icons):

```typescript
viteIconBundlePlugin({
  sources: [
    {
      type: 'folder',
      path: 'icons/ui',
      prefix: 'ui',
      variants: 'monotone',
    },
  ],
});
```

---

## 🔧 Advanced Configuration

### Multiple Icon Sources

```typescript
viteIconBundlePlugin({
  sources: [
    // Your app icons
    {
      type: 'folder',
      path: 'icons/app',
      prefix: 'app',
      variants: 'both',
    },

    // Brand logos (keep colors)
    {
      type: 'folder',
      path: 'icons/brands',
      prefix: 'brand',
      variants: 'colored',
    },

    // UI icons (monotone for theming)
    {
      type: 'folder',
      path: 'icons/ui',
      prefix: 'ui',
      variants: 'monotone',
    },

    // Pre-built Iconify collection
    {
      type: 'json',
      path: 'node_modules/@iconify/json/json/mdi.json',
      prefix: 'mdi',
    },
  ],
  outputPath: 'src/icons-bundle.js',
  verbose: true,
});
```

### Custom Output Path

```typescript
viteIconBundlePlugin({
  sources: [{ type: 'folder', path: 'icons', prefix: 'app' }],
  outputPath: 'src/generated/icons.js', // Custom path
});
```

### Prettier Configuration

```typescript
viteIconBundlePlugin({
  sources: [{ type: 'folder', path: 'icons', prefix: 'app' }],
  prettierConfig: {
    semi: true,
    singleQuote: true,
    tabWidth: 2,
  },
});
```

---

## 🧩 Using Icons in Components

### GIcon Component

```vue
<template>
  <!-- Basic usage -->
  <GIcon icon="app:home" />

  <!-- With size -->
  <GIcon icon="app:home" :width="24" :height="24" />

  <!-- With color -->
  <GIcon icon="app:home" color="#007bff" />

  <!-- Inline (inherits font size) -->
  <p>Home <GIcon icon="app:home" inline /></p>

  <!-- Using Iconify object -->
  <GIcon :icon="{ name: 'home', collection: 'app' }" />
</template>

<script setup>
import { GIcon } from '@twentyfourg/grimoire';
</script>
```

### GButton with Icons

```vue
<template>
  <!-- Icon only -->
  <GButton icon="app:plus" />

  <!-- Icon + text -->
  <GButton icon-left="app:save">Save</GButton>
  <GButton icon-right="app:arrow">Next</GButton>

  <!-- Both sides -->
  <GButton icon-left="app:edit" icon-right="app:check"> Edit </GButton>
</template>

<script setup>
import { GButton } from '@twentyfourg/grimoire';
</script>
```

### GInput with Icons

```vue
<template>
  <GInput v-model="search" icon-left="app:search" placeholder="Search..." />
  <GInput v-model="phone" icon-right="app:phone" placeholder="Phone" />
</template>
```

### Other Components with Icon Support

Many Grimoire components accept icon props:

- **GButton**: `icon`, `iconLeft`, `iconRight`
- **GInput**: `iconLeft`, `iconRight`, `clearIcon`, `passwordIcon`
- **GTable**: Icons for sorting indicators
- **GPagination**: Icons for navigation arrows
- **GCollapsible**: Icons for expand/collapse
- **GCheckbox**: Icon for checkmark

---

## 📁 Source Types

### Folder (SVG Directory)

```typescript
{
  type: 'folder',
  path: 'icons',       // Path to SVG directory
  prefix: 'app',       // Prefix for icon names
  variants: 'both',    // 'colored' | 'monotone' | 'both'
}
```

**What it does:**

- Scans directory for `.svg` files
- Cleans and optimizes SVGs
- Generates icon bundles
- Creates variants based on config

**Example structure:**

```
icons/
├── home.svg       → app:home, mono-app:home
├── search.svg     → app:search, mono-app:search
└── close.svg      → app:close, mono-app:close
```

### JSON (Pre-Built Collections)

```typescript
{
  type: 'json',
  path: 'node_modules/@iconify/json/json/mdi.json',
  prefix: 'mdi',
}
```

**What it does:**

- Loads pre-optimized icon sets
- No processing needed
- Faster builds

**Popular collections:**

- Material Design Icons: `mdi.json`
- Heroicons: `heroicons.json`
- Feather: `feather.json`
- Font Awesome: `fa-solid.json`, `fa-regular.json`
- Bootstrap Icons: `bi.json`

**Example:**

```bash
pnpm add -D @iconify/json
```

```typescript
import mdiIcons from '@iconify/json/json/mdi.json';
import heroIcons from '@iconify/json/json/heroicons.json';

app.use(GrimoirePlugin, {
  icons: {
    mdi: mdiIcons,
    heroicons: heroIcons,
  },
});
```

---

## 🎨 Best Practices

### 1. Use Short Prefixes

```typescript
// ✅ Good - short and memorable
{
  prefix: 'app';
} // app:icon-name
{
  prefix: 'ui';
} // ui:icon-name
{
  prefix: 'brand';
} // brand:icon-name

// ❌ Bad - too verbose
{
  prefix: 'my-application';
} // my-application:icon-name
```

### 2. Organize by Purpose

```
icons/
├── app/          → prefix: 'app'
├── brand/        → prefix: 'brand'
└── ui/           → prefix: 'ui'
```

### 3. Use Monotone for UI Elements

```typescript
// UI icons that should match theme colors
{
  type: 'folder',
  path: 'icons/ui',
  prefix: 'ui',
  variants: 'monotone', // Inherits text color
}
```

### 4. Use Colored for Logos/Branding

```typescript
// Brand assets that should keep original colors
{
  type: 'folder',
  path: 'icons/brands',
  prefix: 'brand',
  variants: 'colored',
}
```

### 5. Combine Custom and Pre-Built Icons

```typescript
viteIconBundlePlugin({
  sources: [
    // Your custom icons
    { type: 'folder', path: 'icons', prefix: 'app' },

    // Supplement with Material Design Icons
    { type: 'json', path: 'node_modules/@iconify/json/json/mdi.json', prefix: 'mdi' },
  ],
});
```

---

## 🐛 Troubleshooting

### Icons Not Showing

**Cause**: Icons not registered with plugin.

**Fix**:

```typescript
// Make sure to import and register
import { icons } from './icons-bundle.js';
app.use(GrimoirePlugin, { icons });
```

### Icons Not Updating

**Cause**: Vite not rebuilding icon bundle.

**Fix**:

1. Set `verbose: true` to see build logs
2. Restart dev server
3. Check SVG files are valid

### TypeScript Errors

**Cause**: Missing peer dependencies.

**Fix**:

```bash
pnpm add -D @iconify/tools @iconify/utils prettier
```

### Import Errors

**Cause**: Build configuration issues.

**Fix**:

1. Build Grimoire: `pnpm --filter @twentyfourg/grimoire build`
2. Check `tsconfig.json`:

```json
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "bundler"
  }
}
```

### Icons Wrong Color

**Cause**: Using colored variant when you want monotone.

**Fix**:

```vue
<!-- Wrong: colored version -->
<GIcon icon="app:home" />

<!-- Right: monotone version (inherits color) -->
<GIcon icon="mono-app:home" />
```

---

## 💡 Tips

### Viewing Available Icons

Add debug output to see what's registered:

```typescript
// main.ts
import { icons } from './icons-bundle.js';

console.log('Registered icons:', Object.keys(icons));

app.use(GrimoirePlugin, { icons });
```

### Dynamic Icon Names

```vue
<template>
  <GIcon :icon="`app:${iconName}`" />
</template>

<script setup>
import { ref } from 'vue';

const iconName = ref('home');

// Change dynamically
setTimeout(() => {
  iconName.value = 'search';
}, 2000);
</script>
```

### Icon Components Library

Create reusable icon components:

```vue
<!-- components/icons/HomeIcon.vue -->
<template>
  <GIcon icon="app:home" v-bind="$attrs" />
</template>

<script setup>
import { GIcon } from '@twentyfourg/grimoire';
</script>
```

---

## 📚 Related Documentation

- **[Component Usage](./component-usage.md)** - Using GIcon in components
- **[Styling Guide](./styling-guide.md)** - Styling icons
- **[Build Tools README](../../src/build-tools/README.md)** - Detailed build tools docs
- **[Iconify Documentation](https://iconify.design/)** - Official Iconify docs

---

## 🔗 External Resources

- [Iconify Icon Sets](https://icon-sets.iconify.design/) - Browse 200,000+ icons
- [Iconify for Vue](https://iconify.design/docs/icon-components/vue/) - Official Vue docs
- [SVG Optimization](https://jakearchibald.github.io/svgomg/) - Optimize SVGs before bundling

---

**For advanced usage and examples, see [`build-tools/ADVANCED_USAGE.md`](../../src/build-tools/ADVANCED_USAGE.md).**



