{"id":35568555,"url":"https://github.com/lindemannrock/craft-icon-manager","last_synced_at":"2026-06-07T09:01:28.930Z","repository":{"id":312753528,"uuid":"1048617340","full_name":"LindemannRock/craft-icon-manager","owner":"LindemannRock","description":"A comprehensive Craft CMS plugin for icon management supporting SVG files, sprites, Font Awesome, and Material Icons with  searchable picker and template integration","archived":false,"fork":false,"pushed_at":"2026-04-05T09:49:23.000Z","size":833,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-05T11:23:30.694Z","etag":null,"topics":["cms","craft","craft-cms","craft-cms-plugin","craft-plugin","craftcms","field-type","fontawesome","icon","icon-management","icon-manager","icon-picker","material-icons","php","svg"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LindemannRock.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-01T18:28:39.000Z","updated_at":"2026-04-05T09:49:07.000Z","dependencies_parsed_at":null,"dependency_job_id":"b271c545-c1e6-462d-8fa1-ce01dcfd803a","html_url":"https://github.com/LindemannRock/craft-icon-manager","commit_stats":null,"previous_names":["lindemannrock/icon-manager","lindemannrock/craft-icon-manager"],"tags_count":68,"template":false,"template_full_name":null,"purl":"pkg:github/LindemannRock/craft-icon-manager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LindemannRock%2Fcraft-icon-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LindemannRock%2Fcraft-icon-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LindemannRock%2Fcraft-icon-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LindemannRock%2Fcraft-icon-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LindemannRock","download_url":"https://codeload.github.com/LindemannRock/craft-icon-manager/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LindemannRock%2Fcraft-icon-manager/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32690536,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-06T08:33:17.875Z","status":"ssl_error","status_checked_at":"2026-05-06T08:33:17.221Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cms","craft","craft-cms","craft-cms-plugin","craft-plugin","craftcms","field-type","fontawesome","icon","icon-management","icon-manager","icon-picker","material-icons","php","svg"],"created_at":"2026-01-04T16:17:46.412Z","updated_at":"2026-06-07T09:01:28.774Z","avatar_url":"https://github.com/LindemannRock.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Icon Manager for Craft CMS\n\n[![Latest Version](https://img.shields.io/packagist/v/lindemannrock/craft-icon-manager.svg)](https://packagist.org/packages/lindemannrock/craft-icon-manager)\n[![Craft CMS](https://img.shields.io/badge/Craft%20CMS-5.0+-orange.svg)](https://craftcms.com/)\n[![PHP](https://img.shields.io/badge/PHP-8.3+-blue.svg)](https://php.net/)\n[![Logging Library](https://img.shields.io/badge/Logging%20Library-5.0+-green.svg)](https://github.com/LindemannRock/craft-logging-library)\n[![License](https://img.shields.io/packagist/l/lindemannrock/craft-icon-manager.svg)](LICENSE)\n\nA comprehensive icon management field supporting SVG libraries and icon fonts for Craft CMS 5.x.\n\n## License\n\nThis is a commercial plugin licensed under the [Craft License](https://craftcms.github.io/license/). It will be available on the [Craft Plugin Store](https://plugins.craftcms.com) soon. See [LICENSE.md](LICENSE.md) for details.\n\n## ⚠️ Pre-Release\n\nThis plugin is in active development and not yet available on the Craft Plugin Store. Features and APIs may change before the initial public release.\n\n## Table of Contents\n\n- [Icon Manager for Craft CMS](#icon-manager-for-craft-cms)\n  - [Table of Contents](#table-of-contents)\n  - [Quick Start](#quick-start)\n  - [Features](#features)\n  - [Development Status](#development-status)\n  - [Requirements](#requirements)\n  - [Installation](#installation)\n    - [Via Composer](#via-composer)\n    - [Using DDEV](#using-ddev)\n    - [Via Control Panel](#via-control-panel)\n  - [Configuration](#configuration)\n    - [Plugin Settings](#plugin-settings)\n    - [Config File](#config-file)\n      - [Available Configuration Options](#available-configuration-options)\n      - [Scan Control Settings](#scan-control-settings)\n    - [Creating Icon Sets](#creating-icon-sets)\n      - [SVG Folder](#svg-folder)\n      - [SVG Sprite](#svg-sprite)\n      - [Font Awesome](#font-awesome)\n      - [Material Icons](#material-icons)\n      - [Web Font](#web-font)\n  - [Usage](#usage)\n    - [Field Type](#field-type)\n    - [Template Variables](#template-variables)\n      - [Basic Icon Rendering](#basic-icon-rendering)\n      - [Working with Icon Objects](#working-with-icon-objects)\n      - [List Icons from a Set](#list-icons-from-a-set)\n      - [Search Icons](#search-icons)\n      - [Working with Icon Sets](#working-with-icon-sets)\n    - [Rendering Options](#rendering-options)\n  - [Icon Metadata](#icon-metadata)\n    - [Basic Structure](#basic-structure)\n    - [Advanced Structure with Multilingual Support](#advanced-structure-with-multilingual-support)\n    - [Label Resolution Priority](#label-resolution-priority)\n    - [Supported Metadata Properties](#supported-metadata-properties)\n  - [Security](#security)\n    - [Automatic Sanitization](#automatic-sanitization)\n    - [How It Works](#how-it-works)\n    - [What's Not Sanitized](#whats-not-sanitized)\n    - [Template Safety](#template-safety)\n  - [Field Settings](#field-settings)\n    - [Icon Size](#icon-size)\n    - [Show Labels](#show-labels)\n    - [Enable Search](#enable-search)\n  - [Caching](#caching)\n    - [Configuration](#configuration-1)\n    - [Cache Management](#cache-management)\n  - [Logging](#logging)\n  - [Permissions](#permissions)\n  - [Environment-Specific Paths](#environment-specific-paths)\n  - [SVG Optimization](#svg-optimization)\n    - [Console Help](#console-help)\n    - [Enabling/Disabling Optimization](#enablingdisabling-optimization)\n    - [Optimization Features](#optimization-features)\n    - [Issue Detection](#issue-detection)\n    - [PHP Optimizer (Default)](#php-optimizer-default)\n    - [SVGO (Advanced)](#svgo-advanced)\n    - [Scan Controls vs SVGO Configuration](#scan-controls-vs-svgo-configuration)\n  - [Missing Icon Handling](#missing-icon-handling)\n  - [Performance Tips](#performance-tips)\n    - [For Large Icon Sets (500+ icons)](#for-large-icon-sets-500-icons)\n    - [For Material Icons](#for-material-icons)\n    - [Cache Strategy by Environment](#cache-strategy-by-environment)\n  - [Troubleshooting](#troubleshooting)\n    - [Icons Not Showing in Picker](#icons-not-showing-in-picker)\n    - [Icons Not Rendering in Templates](#icons-not-rendering-in-templates)\n    - [Optimization Not Working](#optimization-not-working)\n    - [Performance Issues with Large Icon Sets](#performance-issues-with-large-icon-sets)\n    - [Config File Not Working](#config-file-not-working)\n  - [Examples](#examples)\n  - [Support](#support)\n  - [License](#license)\n\n## Quick Start\n\nGet up and running with Icon Manager in 5 minutes:\n\n**1. Install the plugin**\n```bash\ncomposer require lindemannrock/icon-manager\n./craft plugin/install icon-manager\n```\n\n**2. Create your first icon set**\n- Go to **Icon Manager → Icon Sets** in the Control Panel\n- Click **\"New Icon Set\"**\n- Choose **\"SVG Folder\"** as the type\n- Select a folder containing SVG files (or use the default `/icons` folder)\n- Save the icon set\n\n**3. Add an icon field to your section**\n- Go to **Settings → Fields**\n- Create a new **\"Icon Manager\"** field\n- Add it to your entry type\n- Start selecting icons in your entries!\n\n**That's it!** Icons are now available in your templates via `{{ entry.iconField.render() }}`.\n\nSee [Usage](#usage) below for template examples and advanced features.\n\n## Features\n\n- **Multiple Icon Formats**: Support for SVG files, SVG sprites, Font Awesome, Material Icons, and custom web fonts\n- **Intuitive Interface**: Searchable icon picker with preview, tabs/dropdown for multiple sets\n- **Flexible Configuration**: Configure icon sets and field settings (size, labels, search)\n- **Performance Optimized**: File or Redis caching for fast icon loading\n- **Security**: SVG sanitization to prevent XSS attacks\n- **Twig Integration**: Easy icon rendering in templates with automatic HTML safety\n- **GraphQL Support**: Icon fields expose structured icon data in Craft GraphQL schemas\n\n## Development Status\n\n⚠️ **Beta Features** - The following features are currently in testing and finalization:\n- **SVG Sprite support** - Basic functionality implemented, advanced features pending\n- **Material Icons** - Core integration complete, variable fonts being refined\n- **Font Awesome** - Free icons working, Pro/Kit support in development\n- **Web Font** - Custom icon font support (TTF, WOFF, OTF) with glyph extraction\n\nSVG folder icons are fully stable and production-ready.\n\n## Requirements\n\n- Craft CMS 5.0 or greater\n- PHP 8.3 or greater\n- [Logging Library](https://github.com/LindemannRock/craft-logging-library) 5.0 or greater (installed automatically as dependency)\n\n## Installation\n\n### Via Composer\n\n```bash\ncd /path/to/project\n```\n\n```bash\ncomposer require lindemannrock/craft-icon-manager\n```\n\n```bash\n./craft plugin/install icon-manager\n```\n\n### Using DDEV\n\n```bash\ncd /path/to/project\n```\n\n```bash\nddev composer require lindemannrock/craft-icon-manager\n```\n\n```bash\nddev craft plugin/install icon-manager\n```\n\n### Via Control Panel\n\nIn the Control Panel, go to Settings → Plugins and click \"Install\" for Icon Manager.\n\n## Configuration\n\n### Plugin Settings\n\nSettings can be configured in the Control Panel at Settings → Icon Manager, or via a config file.\n\n1. **Icon Sets Path**: Set the path to your icon files (default: `@root/icons`)\n2. **Cache Settings**: Configure caching for better performance\n3. **Display Settings**: Set default display options\n4. **Icon Types**: Enable/disable different icon set types\n\n### Config File\n\nCreate a `config/icon-manager.php` file to override default settings:\n\n```bash\ncp vendor/lindemannrock/craft-icon-manager/src/config.php config/icon-manager.php\n```\n\n```php\n\u003c?php\n\nuse craft\\helpers\\App;\n\nreturn [\n    // Global settings\n    '*' =\u003e [\n        // Plugin display name\n        'pluginName' =\u003e 'Icon Manager',\n\n        // Default icons path\n        'iconSetsPath' =\u003e '@root/src/icons',\n\n        // Icon types to enable\n        'enabledIconTypes' =\u003e [\n            'svg-folder' =\u003e true,\n            'svg-sprite' =\u003e true,\n            'font-awesome' =\u003e false,\n            'material-icons' =\u003e false,\n            'web-font' =\u003e false,\n        ],\n\n        // SVG Optimization\n        'enableOptimization' =\u003e true,\n        'enableOptimizationBackup' =\u003e true,\n\n        // Scan Controls (what scanner detects - PHP optimizer only, SVGO uses svgo.config.js)\n        'scanClipPaths' =\u003e true,              // Detect empty/unused clip-paths (used ones preserved)\n        'scanMasks' =\u003e true,                  // Detect empty/unused masks (used ones preserved)\n        'scanFilters' =\u003e true,                // Detect filter effects\n        'scanComments' =\u003e true,               // Detect regular comments (legal \u003c!--! ... --\u003e preserved)\n        'scanInlineStyles' =\u003e true,           // Detect convertible styles (CSS-only properties preserved)\n        'scanLargeFiles' =\u003e true,             // Detect files \u003e10KB (warning only)\n        'scanWidthHeight' =\u003e true,            // Detect width/height without viewBox (critical)\n        'scanWidthHeightWithViewBox' =\u003e false, // Detect width/height with viewBox (optional)\n    ],\n\n    // Dev environment settings\n    'dev' =\u003e [\n        // Use source icons in dev\n        'iconSetsPath' =\u003e '@root/src/icons',\n\n        // Cache settings for dev\n        'cacheStorageMethod' =\u003e 'file',\n        'enableCache' =\u003e true,\n        'cacheDuration' =\u003e 3600, // 1 hour\n\n        // Detailed logging for development\n        'logLevel' =\u003e 'debug',\n\n        // Allow all icon types for testing\n        'enabledIconTypes' =\u003e [\n            'svg-folder' =\u003e true,\n            'svg-sprite' =\u003e true,\n            'font-awesome' =\u003e true,\n            'material-icons' =\u003e true,\n            'web-font' =\u003e true,\n        ],\n    ],\n\n    // Staging environment settings\n    'staging' =\u003e [\n        // Production-ready icons path\n        'iconSetsPath' =\u003e '@webroot/dist/assets/icons',\n\n        // Optimize for staging\n        'enableCache' =\u003e true,\n        'cacheDuration' =\u003e 86400, // 1 day\n    ],\n\n    // Production environment settings\n    'production' =\u003e [\n        // Production icons path\n        'iconSetsPath' =\u003e '@webroot/dist/assets/icons',\n\n        // Optimize for production\n        'cacheStorageMethod' =\u003e 'redis',  // Use Redis in production\n        'enableCache' =\u003e true,\n        'cacheDuration' =\u003e 2592000, // 30 days\n\n        // Minimal logging for production\n        'logLevel' =\u003e 'warning',\n\n        // Only stable icon types in production\n        'enabledIconTypes' =\u003e [\n            'svg-folder' =\u003e true,\n            'svg-sprite' =\u003e false, // Beta\n            'font-awesome' =\u003e false, // Beta\n            'material-icons' =\u003e false, // Beta\n            'web-font' =\u003e false, // Beta\n        ],\n    ],\n];\n```\n\nSettings defined in the config file will override CP settings and show a warning message in the settings UI.\n\nSee [Configuration Documentation](docs/CONFIGURATION.md) for all available options.\n\n#### Available Configuration Options\n\n- **pluginName** - Customize the plugin display name in navigation and settings\n- **iconSetsPath** - Path to icon files (supports `@root`, `@storage`, `@webroot`, absolute paths inside those roots, and environment variables that resolve inside those roots)\n- **enableCache** - Whether to cache icon data for better performance\n- **cacheDuration** - How long to cache icon data, in seconds\n- **itemsPerPage** - Number of icon sets per page in CP index (10-500, default: 100)\n- **enabledIconTypes** - Enable/disable specific icon set types\n- **enableOptimization** - Enable/disable SVG optimization features (default: true)\n- **enableOptimizationBackup** - Automatically create backups before optimization (default: true)\n- **Scan Controls** - Granular control over what the scanner detects (see Scan Control Settings below)\n- **logLevel** - Logging verbosity: error, warning, info, or debug\n\n#### Scan Control Settings (Detection Only)\n\nThese settings control what the scanner **detects and reports** in the UI. They do NOT control what gets optimized.\n\n```php\n// config/icon-manager.php\nreturn [\n    'scanClipPaths' =\u003e true,              // Detect empty/unused clip-paths\n    'scanMasks' =\u003e true,                  // Detect empty/unused masks\n    'scanFilters' =\u003e true,                // Detect filter effects\n    'scanComments' =\u003e true,               // Detect comments (excludes legal \u003c!--! ... --\u003e)\n    'scanInlineStyles' =\u003e true,           // Detect convertible inline styles\n    'scanLargeFiles' =\u003e false,            // Detect files \u003e10KB (informational)\n    'scanWidthHeight' =\u003e true,            // Detect width/height without viewBox (critical)\n    'scanWidthHeightWithViewBox' =\u003e false, // Detect width/height with viewBox (optional)\n];\n```\n\n**What each scan detects:**\n\n- **scanClipPaths**: Flags empty or unreferenced clip-paths. Used clip-paths are not flagged.\n- **scanMasks**: Flags empty or unreferenced masks. Used masks are not flagged.\n- **scanFilters**: Flags `\u003cfilter\u003e` elements (informational - may slow rendering).\n- **scanComments**: Flags regular comments (legal comments `\u003c!--! --\u003e` preserved).\n- **scanInlineStyles**: Flags convertible styles (CSS-only properties like `isolation` preserved).\n- **scanLargeFiles**: Informational for files \u003e10KB (use as file size monitoring guide - may be normal for complex icons, optimization may reduce size but not always).\n- **scanWidthHeight**: Flags width/height without viewBox (responsive SVG issue).\n- **scanWidthHeightWithViewBox**: Flags width/height even with viewBox (optional optimization).\n\n#### PHP Optimizer Settings (What Gets Applied)\n\nControl which optimization rules are applied during PHP optimization:\n\n```php\n// config/icon-manager.php\nreturn [\n    // Risky rule gate\n    'optimizeAllowRiskyRules' =\u003e true,\n\n    // Conversion rules\n    'optimizeConvertColorsToHex' =\u003e true,\n    'optimizeConvertCssClasses' =\u003e true,\n    'optimizeConvertEmptyTags' =\u003e true,\n    'optimizeConvertInlineStyles' =\u003e true,\n    'optimizeFixAttributeNames' =\u003e true,\n\n    // Minification rules\n    'optimizeMinifyCoordinates' =\u003e true,\n    'optimizeMinifyTransformations' =\u003e true,\n\n    // Removal rules\n    'optimizeRemoveAriaAndRole' =\u003e false,\n    'optimizeRemoveComments' =\u003e true,\n    'optimizeRemoveDataAttributes' =\u003e false,\n    'optimizeRemoveDefaultAttributes' =\u003e true,\n    'optimizeRemoveDeprecatedAttributes' =\u003e true,\n    'optimizeRemoveDoctype' =\u003e true,\n    'optimizeRemoveDuplicateElements' =\u003e true,\n    'optimizeRemoveEnableBackground' =\u003e true,\n    'optimizeRemoveEmptyAttributes' =\u003e true,\n    'optimizeRemoveEmptyGroups' =\u003e true,\n    'optimizeRemoveEmptyTextElements' =\u003e true,\n    'optimizeRemoveInkscapeFootprints' =\u003e true,\n    'optimizeRemoveInvisibleCharacters' =\u003e true,\n    'optimizeRemoveMetadata' =\u003e true,\n    'optimizeRemoveNonStandardAttributes' =\u003e false,\n    'optimizeRemoveNonStandardTags' =\u003e false,\n    'optimizeRemoveTitleAndDesc' =\u003e false,\n    'optimizeRemoveUnsafeElements' =\u003e true,\n    'optimizeRemoveWhitespace' =\u003e true,\n    'optimizeRemoveUnusedNamespaces' =\u003e true,\n    'optimizeRemoveUnusedMasks' =\u003e true,\n    'optimizeRemoveWidthHeight' =\u003e true,\n\n    // Structure rules\n    'optimizeFlattenGroups' =\u003e true,\n    'optimizeScopeSvgStyles' =\u003e false,\n    'optimizeSortAttributes' =\u003e true,\n];\n```\n\nMost cleanup rules default to `true`. Some v8 rules are intentionally more conservative by default, especially risky or security-sensitive rules.\n\n### Creating Icon Sets\n\n1. Navigate to Icon Manager → Icon Sets in the CP\n2. Click \"New Icon Set\"\n3. Choose the type and configure settings:\n\n#### SVG Folder\n- Point to a folder containing SVG files\n- Optionally include subfolders\n- Supports metadata.json for keywords\n- Works great with icon libraries like:\n  - [Lucide](https://lucide.dev/) - 1,600+ open source icons\n  - [Heroicons](https://heroicons.com/) - Beautiful hand-crafted SVG icons\n  - [Tabler Icons](https://tabler-icons.io/) - 3,000+ free SVG icons\n  - Any other SVG icon library\n\n#### SVG Sprite\n- Point to an SVG sprite file containing multiple `\u003csymbol\u003e` elements\n- Set optional ID prefix for icon references\n- **Performance**: Sprite file is loaded once and injected into the page DOM, allowing all icons to reference the same sprite\n- **Best for**: Projects using many icons from the same set (e.g., 10+ icons)\n- Supports standard SVG sprite format with `\u003csymbol id=\"icon-name\"\u003e` structure\n\n#### Font Awesome\n- Supports Font Awesome v7 (latest)\n- Configure styles (solid, regular, brands)\n- Icons loaded from predefined lists\n- Kit support planned for future release\n\n#### Material Icons\n- Material Icons (classic) with all styles\n- Material Symbols with variable font support\n- Configurable axes (weight, fill, optical size)\n- **Performance Note**: Automatically loads Google Fonts font file (~3.7 MB) containing all 3,800+ icons. The font file is cached by the browser after first load, but represents a significant initial download.\n  - **Alternative**: For better performance, download SVG versions of only the icons you need from [Google Fonts](https://fonts.google.com/icons) and add them to an SVG folder or sprite icon set instead.\n\n#### Web Font\n- Custom icon fonts (TTF, WOFF, OTF supported)\n- Automatic glyph extraction with unicode mapping\n- @font-face CSS generation and serving\n- Configurable CSS prefix for icon classes\n- **Performance**: Font file is served through Craft and cached by the browser after first load. Font size depends on the number of glyphs in your custom font.\n- **Note**: WOFF2 not currently supported - use TTF or WOFF formats\n\n## Usage\n\n### Field Type\n\nAdd an Icon field to any element:\n\n1. Create a new field of type \"Icon Manager\"\n2. Configure field settings:\n   - **Enable Search**: Show search box in picker\n   - **Show Labels**: Display icon names in picker\n   - **Icon Size**: Small (32px), Medium (48px), or Large (64px)\n   - **Icon Sets**: Choose which sets are available\n   - **Allow Multiple Selection**: Enable selecting multiple icons (returns array)\n   - **Allow Custom Labels**: Let users add custom labels for icons\n   - **Icons Per Page**: Number of icons displayed in picker (10-500)\n\n3. Use in templates:\n\n```twig\n{# Single icon field #}\n{% if entry.iconField %}\n    {{ entry.iconField.render({ size: 32, class: 'my-icon' }) }}\n{% endif %}\n\n{# Multiple icons field #}\n{% if entry.multipleIconsField %}\n    {% for icon in entry.multipleIconsField %}\n        {{ icon.render({ size: 24, class: 'icon-item' }) }}\n        \u003cspan\u003e{{ icon.displayLabel }}\u003c/span\u003e\n    {% endfor %}\n{% endif %}\n\n{# displayLabel provides smart label resolution:\n   1. Site-specific custom label (if set)\n   2. General custom label (if set)\n   3. JSON metadata label\n   4. Database label\n   5. Translation\n   6. Formatted filename (fallback)\n#}\n```\n\nNote: The `|raw` filter is not needed - icons are automatically rendered safely.\n\n### GraphQL\n\nIcon Manager fields expose GraphQL types for both single-select and multi-select field values.\n\nAvailable GraphQL fields:\n- `name`\n- `label`\n- `type`\n- `value`\n- `iconSetHandle`\n- `customLabel`\n- `svg`\n- `content`\n\nSingle-select fields resolve to one icon object. Multi-select fields resolve to a list of icon objects.\n\n### Template Variables\n\n#### Basic Icon Rendering\n\n```twig\n{# Render an icon directly #}\n{{ craft.iconManager.renderIcon('myIconSet', 'arrow-right') }}\n\n{# With options (size, class, etc.) #}\n{{ craft.iconManager.renderIcon('myIconSet', 'arrow-right', {\n    width: 24,\n    height: 24,\n    class: 'text-blue-500'\n}) }}\n```\n\n#### Working with Icon Objects\n\n```twig\n{# Get icon object for more control #}\n{% set icon = craft.iconManager.getIcon('myIconSet', 'star') %}\n\n{% if icon %}\n    {# Render with default settings #}\n    {{ icon.render() }}\n\n    {# Render with custom attributes #}\n    {{ icon.render({\n        width: 32,\n        height: 32,\n        class: 'icon-custom',\n        'aria-label': 'Star rating'\n    }) }}\n\n    {# Get raw SVG content #}\n    {{ icon.getContent() }}\n\n    {# Access icon properties #}\n    \u003cdiv data-icon=\"{{ icon.name }}\" data-set=\"{{ icon.iconSet.handle }}\"\u003e\n        {{ icon.render() }}\n    \u003c/div\u003e\n{% endif %}\n```\n\n#### List Icons from a Set\n\n```twig\n{# Get all icons from a set #}\n{% set icons = craft.iconManager.getIcons('myIconSet') %}\n\n\u003cdiv class=\"icon-grid\"\u003e\n    {% for icon in icons %}\n        \u003cdiv class=\"icon-item\"\u003e\n            {{ icon.render({ width: 24, height: 24 }) }}\n            \u003cspan\u003e{{ icon.name }}\u003c/span\u003e\n        \u003c/div\u003e\n    {% endfor %}\n\u003c/div\u003e\n```\n\n#### Search Icons\n\n```twig\n{# Search for icons across all sets #}\n{% set searchResults = craft.iconManager.searchIcons('arrow') %}\n\n{# Search within specific sets #}\n{% set searchResults = craft.iconManager.searchIcons('arrow', ['myIconSet', 'fontAwesome']) %}\n\n{% for icon in searchResults %}\n    \u003cdiv class=\"search-result\"\u003e\n        {{ icon.render({ width: 20, height: 20 }) }}\n        \u003cspan\u003e{{ icon.name }} ({{ icon.iconSet.name }})\u003c/span\u003e\n    \u003c/div\u003e\n{% endfor %}\n```\n\n#### Working with Icon Sets\n\n```twig\n{# Get all enabled icon sets #}\n{% set iconSets = craft.iconManager.getEnabledIconSets() %}\n\n{# Get a specific icon set #}\n{% set iconSet = craft.iconManager.getIconSet('myIconSet') %}\n\n{% if iconSet %}\n    \u003ch3\u003e{{ iconSet.name }}\u003c/h3\u003e\n    \u003cp\u003eType: {{ iconSet.type }}\u003c/p\u003e\n    \u003cp\u003eIcon count: {{ iconSet.icons|length }}\u003c/p\u003e\n{% endif %}\n```\n\n### Rendering Options\n\n```twig\n{{ icon.render({\n    # Dimensions\n    width: 24,\n    height: 24,\n\n    # CSS class\n    class: 'custom-icon-class',\n\n    # Additional attributes\n    'data-icon': icon.name,\n    'aria-label': 'Icon description',\n    'role': 'img',\n\n    # Style attribute\n    style: 'fill: currentColor;'\n}) }}\n```\n\n## Icon Metadata\n\nAdd a `metadata.json` file in your icon folders to provide enhanced metadata:\n\n### Basic Structure\n\n```json\n{\n    \"star\": {\n        \"keywords\": [\"favorite\", \"rating\", \"bookmark\"]\n    },\n    \"heart\": {\n        \"keywords\": [\"love\", \"like\", \"favorite\"]\n    }\n}\n```\n\n### Advanced Structure with Multilingual Support\n\n```json\n{\n    \"freshly-baked\": {\n        \"label\": \"Freshly Baked\",\n        \"label_en\": \"Freshly Baked\",\n        \"label_ar\": \"مخبوز طازج\",\n        \"label_fr\": \"Fraîchement Cuit\",\n        \"label_de\": \"Frisch Gebacken\",\n        \"label_es\": \"Recién Horneado\",\n        \"label_it\": \"Appena Sfornato\",\n        \"search\": {\n            \"terms\": [\"fresh\", \"baked\", \"bread\", \"bakery\", \"طازج\", \"مخبوز\", \"خبز\", \"frais\", \"cuit\", \"frisch\", \"gebacken\"]\n        },\n        \"category\": \"product-features\",\n        \"description\": \"Icon representing freshly baked products\"\n    }\n}\n```\n\n**Language Code Format:**\n- Use `label_{languageCode}` where `{languageCode}` is the site's language code\n- **Use underscore `_` not hyphen `-`**: `label_en`, `label_ar`, `label_fr` (correct) vs `label-en` (wrong)\n- Supports any language: `label_en`, `label_ar`, `label_fr`, `label_de`, `label_es`, `label_it`, etc.\n- Legacy format (`labelEn`, `labelAr`) still supported for backward compatibility\n- Primary language codes only (e.g., `en-US` → uses `label_en`, `ar-AE` → uses `label_ar`)\n\n**Label Resolution in Control Panel:**\n- Uses the `?site=` URL parameter to determine which language to show\n- Example: When editing `?site=fr`, shows `label_fr` from JSON\n- Falls back gracefully: `label_fr` → `labelFr` → `label` → filename\n\n**Custom Labels (Per-Site):**\n- Custom labels are stored per-site using `customLabels[siteId]` object\n- Each site can have different custom labels for the same icon\n- Translation Method \"Translate for each site\" recommended for independent icon selection per site\n- Custom labels take priority over JSON labels when set\n\n### Label Resolution Priority\n\nThe plugin resolves icon labels in this order:\n1. **Site-specific custom label** (highest priority) - set via field's custom label input for current site\n2. **JSON metadata label** - from `label_fr`, `label_ar`, `label_en`, or legacy `labelFr`, `labelAr` based on editing site\n3. **Database label** - stored label from icon set\n4. **Translation system** - Craft's translation files\n5. **Propagated custom label** - custom label from another site (as last resort)\n6. **Filename** (fallback) - formatted from the SVG filename\n\n**Important Notes:**\n- In Control Panel: Uses `?site=` URL parameter to determine language (not user's CP language)\n- On Frontend: Uses the current site being viewed\n- Custom labels with \"Translate for each site\" field setting work correctly per-site\n- JSON labels always use the editing site's language, ensuring correct translations in CP\n\n### Supported Metadata Properties\n\n- **`label`** - Default display label (fallback)\n- **`label_{languageCode}`** - Language-specific labels (e.g., `label_en`, `label_ar`, `label_fr`, `label_de`)\n  - Supports any Craft site language dynamically\n  - Use primary language code only (e.g., `en-US` → `label_en`)\n- **`labelEn`, `labelAr`** - Legacy format (still supported for backward compatibility)\n- **`search.terms`** - Additional search keywords (supports multilingual)\n- **`category`** - Icon category for organization\n- **`description`** - Icon description for accessibility\n- **`keywords`** - Legacy search terms (still supported)\n\n## Security\n\nIcon Manager provides automatic SVG sanitization to protect against XSS (Cross-Site Scripting) attacks and malicious code injection.\n\n### Automatic Sanitization\n\nAll SVG content is automatically sanitized at render time to remove potentially malicious code:\n\n- **Script Tags**: All `\u003cscript\u003e` tags are removed\n- **Event Handlers**: JavaScript event handlers (onclick, onmouseover, onload, etc.) are stripped\n- **JavaScript Protocols**: `javascript:` protocols in hrefs are blocked and replaced with `#`\n- **Malicious Data URLs**: Data URLs containing script content are prevented\n- **External Scripts**: Remote script references are removed\n\n### How It Works\n\nSanitization occurs when SVG content is rendered via:\n- `{{ icon.render() }}` - Full icon rendering with attributes\n- `{{ icon.svg }}` - Raw SVG content\n- `{{ icon.content }}` - Alias for SVG content\n\nThe original SVG files remain unchanged on disk. Sanitization is applied only at render time, ensuring your source files are preserved while output is safe.\n\n### What's Not Sanitized\n\nIcon Manager focuses on security sanitization. The following are **not** automatically removed as they don't pose security risks:\n\n- Clip-paths and masks (visual elements)\n- Filters and effects (visual styling)\n- Embedded fonts (typography)\n- Metadata and comments (documentation)\n\nThese elements are preserved because they're part of the SVG's visual design and don't execute code.\n\n### Template Safety\n\nBecause sanitization is automatic, you **do not need** to use Twig's `|raw` filter:\n\n```twig\n{# ✓ Correct - automatically safe #}\n{{ icon.render() }}\n\n{# ✗ Not needed - redundant #}\n{{ icon.render()|raw }}\n```\n\nThe plugin automatically marks output as safe using Twig's `Template::raw()` after sanitization is complete.\n\n## Field Settings\n\n### Icon Size\nControls the display size of icons in both the field preview and picker:\n- **Small**: 32x32 pixels\n- **Medium**: 48x48 pixels (default)\n- **Large**: 64x64 pixels\n\nNote: Font-based icons (Material Icons, Font Awesome, Web Fonts) are rendered 10px smaller than SVG icons for visual balance, as they typically have less padding in their bounding boxes.\n\n### Show Labels\nWhen enabled, displays icon names below icons in the picker and field preview.\n\n### Enable Search\nShows a search box in the icon picker for filtering icons by name or keywords.\n\n## Caching\n\nIcon Manager includes a comprehensive caching system for better performance:\n\n### Configuration\n```php\n// config/icon-manager.php\nreturn [\n    'cacheStorageMethod' =\u003e 'file',  // 'file' or 'redis'\n    'enableCache' =\u003e true,           // Enable/disable caching\n    'cacheDuration' =\u003e 86400,        // Cache duration in seconds (24 hours)\n];\n```\n\n**Storage Methods:**\n- **File** - Default, stores cache in `storage/runtime/icon-manager/cache/`\n- **Redis** - For load-balanced or cloud hosting (Servd, AWS, Platform.sh)\n\n### Cache Management\n- **Clear Icon Cache Utility**: Go to Utilities → Clear Icon Cache\n- **Integrated with Craft**: Available in Utilities → Clear Caches\n- **Automatic**: Cache clears when refreshing icon sets\n- **Redis Support**: All cache clearing methods work with both file and Redis storage\n\n## Environment-Specific Paths\n\nConfigure different icon paths per environment:\n\n```php\n// config/icon-manager.php\nreturn [\n    'dev' =\u003e [\n        'iconSetsPath' =\u003e '@root/src/icons',     // Development\n    ],\n    'production' =\u003e [\n        'iconSetsPath' =\u003e '@webroot/assets/icons', // Production\n    ],\n];\n```\n\nIcons are stored with relative paths in the database, so changing `iconSetsPath` instantly updates all icon locations without rescanning.\n\n## SVG Optimization\n\nIcon Manager supports two SVG optimization engines with intelligent issue detection.\n\n### Console Help\n\nIcon Manager includes a plugin-level console help command that lists the available CLI commands and explains the options that matter for each workflow:\n\n```bash\nddev craft icon-manager/help\nddev craft icon-manager/help optimize\nddev craft icon-manager/help optimize/verify\n```\n\nCraft's native help is still available for exact command signatures:\n\n```bash\nddev craft help icon-manager/optimize\nddev craft help icon-manager/optimize/verify\n```\n\n### Enabling/Disabling Optimization\n\nSVG optimization can be controlled globally via settings or config file:\n\n**Via Control Panel:**\n1. Go to Icon Manager → Settings → SVG Optimization\n2. Toggle \"Enable Optimization\" and \"Enable Automatic Backups\"\n\n**Via Config File:**\n```php\n// config/icon-manager.php\nreturn [\n    'enableOptimization' =\u003e true,          // Enable optimization features\n    'enableOptimizationBackup' =\u003e true,    // Auto-backup before optimization\n];\n```\n\nWhen disabled:\n- Optimization tab hidden in Icon Sets\n- Optimize column hidden in Icon Sets table\n- CLI commands show instructions on how to enable\n- Utilities page displays disabled message with settings link\n\n### Optimization Features\n\n### Issue Detection\n\nThe plugin scans SVG files and identifies:\n\n**Real Issues (Red):**\n- **Unused Clip-Paths**: Empty or unreferenced clip-path definitions that can be removed\n- **Unused Masks**: Empty or unreferenced mask definitions that can be removed\n- **Comments**: Metadata and comments that increase file size\n- **Filters**: Complex effects that may slow rendering\n- **Inline Styles**: Styles that are harder to override with CSS\n- **Width/Height Attributes**: Should use viewBox for responsive SVGs\n\n**Warnings (Yellow):**\n- **Large Files**: Files over 10KB (may be normal for complex icons)\n\n**Not Flagged as Issues:**\n- Functional clip-paths and masks that are actually used in the SVG\n- ViewBox attributes (these are good for responsiveness)\n\n### PHP Optimizer (Default)\n\nUses [mathiasreker/php-svg-optimizer v8](https://github.com/mathiasreker/php-svg-optimizer) with 32 user-controlled optimization rules plus explicit risky-rule handling. Available in the Control Panel via Icon Manager → Icon Sets → [Set] → Optimize.\n\n**Features:**\n- No additional installation required\n- Works in CP interface\n- 32 toggleable optimization rules organized in 5 categories:\n  - **Risky Rules**: Explicit opt-in required by v8 before risky rules are applied\n  - **Conversion**: Colors to hex, CSS classes/styles to attributes, empty tags to self-closing, attribute-name fixes\n  - **Minification**: Coordinates, transformations\n  - **Removal**: Comments, metadata, deprecated attributes, duplicate elements, unsafe elements, whitespace, unused masks/namespaces, width/height, and more\n  - **Structure**: Flatten groups, scope styles, sort attributes\n- Risky rules are grouped in the CP and hidden when `Allow Risky Rules` is disabled\n- Current risky rules in `php-svg-optimizer` v8.5.x:\n  - `removeDataAttributes`\n  - `removeEnableBackgroundAttribute`\n  - `removeWidthHeightAttributes`\n  - `scopeSvgStyles`\n- Control which rules to apply via Settings → SVG Optimization → PHP Optimizer\n- Supports 77 SVG properties for CSS-to-attribute conversion\n- Auto-preserves legal comments (`\u003c!--! --\u003e`)\n\n**Configuration:**\nControl optimization behavior in Icon Manager → Settings → SVG Optimization:\n- **General tab**: Enable optimization, automatic backups\n- **Scan Controls tab**: What issues to detect in scans (8 detection rules)\n- **PHP Optimizer tab**: What optimizations to apply (32 optimization rules plus risky-rule switch)\n\n**Important:** Scan Controls and PHP Optimizer Settings are separate:\n- **Scan Controls**: What scanner detects and displays in UI\n- **PHP Optimizer**: What actually gets applied during optimization\n- Optimization may modify files even when scan shows 0 issues (applies all enabled rules)\n- `Unused Clip-Paths` is still scan-only in the PHP optimizer path because upstream does not currently expose a clip-path cleanup rule\n\n### SVGO (Advanced)\n\nUses [SVGO](https://github.com/svg/svgo) for advanced optimization with full configuration control. Requires Node.js installation.\n\n**Installation:**\n\n```bash\n# Using npm\nnpm install --save-dev svgo\n\n# Using yarn\nyarn add --dev svgo\n\n# Using pnpm\npnpm add -D svgo\n```\n\n**Usage:**\n\n```bash\n# Interactive mode - prompts for icon set, engine, and optimization preset\nddev craft icon-manager/optimize\n\n# Check if SVGO is available\nddev craft icon-manager/optimize/check\n\n# Direct command with specific icon set\nddev craft icon-manager/optimize --set=3 --engine=svgo\n\n# Use custom config file\nddev craft icon-manager/optimize --set=3 --engine=svgo --config=my-svgo.config.js\n\n# Skip backup creation\nddev craft icon-manager/optimize --set=3 --engine=svgo --no-backup\n\n# Dry run (see what would be optimized without making changes)\nddev craft icon-manager/optimize --set=3 --engine=svgo --dry-run\n```\n\n**Interactive Mode:**\n\nWhen running `ddev craft icon-manager/optimize` without flags, the command will:\n1. List available SVG folder icon sets\n2. Let you choose an icon set\n3. Show available engines (PHP or SVGO)\n4. If SVGO is selected and no config file exists, offer optimization presets:\n   - **Safe**: Remove metadata, comments (preserves visual elements)\n   - **Balanced**: Safe + cleanup IDs, remove hidden elements\n   - **Aggressive**: Balanced + merge paths, convert colors (may affect styling)\n   - **Default**: Use SVGO defaults\n5. Ask if you want to create a backup before optimization\n6. Show real-time progress during optimization\n\n**Configuration:**\n\nCreate a `svgo.config.js` file in your project root for custom optimization:\n\n```javascript\nexport default {\n    plugins: [\n        {\n            name: 'preset-default',\n            params: {\n                overrides: {\n                    convertColors: false,  // Preserve colors\n                    mergePaths: false,     // Don't merge paths\n                    removeViewBox: false,  // Keep viewBox\n                },\n            },\n        },\n        'removeDimensions',        // Remove width/height\n        'removeEmptyContainers',   // Clean up empty elements\n        'removeEditorsNSData',     // Remove editor metadata\n    ],\n};\n```\n\nSee `docs/svgo.config.example.js` for a complete configuration example.\n\n**Auto-Configuration:**\n\nIf no `svgo.config.js` is found:\n- **Interactive mode**: Prompts you to choose an optimization preset\n- **Direct command mode**: Automatically uses the \"Safe\" preset to prevent breaking SVGs\n\n**Progress Output:**\n\nSVGO shows real-time progress during optimization:\n```\nProcessing (1/123): icon-name.svg...\n  ✓ Optimized\nProcessing (2/123): another-icon.svg...\n  - Skipped (already optimized)\n```\n\n**Automatic Backups:**\n\nBefore optimization, a backup is automatically created (unless `--no-backup` is used):\n- Stored in `storage/runtime/icon-manager/backups/`\n- Named with timestamp: `icon-set-name_YYYY-MM-DD_HH-MM-SS`\n- Can be restored from Icon Manager → Icon Sets → [Set] → Optimize tab (dev mode only)\n\n**When to Use SVGO:**\n- Need to optimize clip-paths, masks, or file size\n- Want custom configuration per project\n- Running optimization in CI/CD pipelines\n- Have complex SVGs that need specific handling\n- PHP optimizer finds \"nothing to optimize\"\n\n**When to Use PHP Optimizer:**\n- Want to optimize directly in the CP\n- Don't have Node.js in your environment\n- Need simple, reliable optimization\n- Only need basic cleanup (comments, metadata)\n\n### Optimizer Verification Fixtures\n\nIcon Manager can verify an SVG fixture directory against either optimizer engine. Use this after optimizer dependency upgrades or when validating a custom SVGO configuration against representative project icons.\n\n**Purpose:**\n- Exercise intentionally problematic SVGs against the installed `php-svg-optimizer`\n- Validate risky-rule handling\n- Run the same fixtures through SVGO\n- Confirm optimized output remains parseable SVG\n\nPrepare a fixture directory with SVG files that represent the icon shapes and SVG features used by the project.\n\n**Run PHP optimizer verification:**\n\n```bash\nddev craft icon-manager/optimize/verify --engine=php --path=path/to/svg-fixtures --keep-outputs=1\n```\n\n**Run SVGO verification:**\n\n```bash\nddev craft icon-manager/optimize/verify --engine=svgo --path=path/to/svg-fixtures --config=path/to/svgo.config.mjs --keep-outputs=1\n```\n\n**Notes:**\n- Verification outputs are written to `storage/runtime/icon-manager/verify/`\n- This verifies structural integrity and rule execution, not pixel-perfect visual equivalence\n- After dependency upgrades, run the fixture pack and then spot-check a few real-world icons\n\n### Understanding the Three Settings Areas\n\nIcon Manager has three separate configuration areas for SVG optimization:\n\n#### 1. Scan Controls\n**Purpose:** What issues to detect and display in scan reports\n**Location:** Settings → SVG Optimization → Scan Controls tab\n**Affects:** UI reporting only (what you see in the \"Issues Found\" section)\n\n#### 2. PHP Optimizer Settings\n**Purpose:** Which optimization rules to apply when using PHP optimizer\n**Location:** Settings → SVG Optimization → PHP Optimizer tab\n**Affects:** Actual file modifications when using \"Apply Optimizations\" button or `--engine=php`\n\n**Available via config file:**\n```php\n// config/icon-manager.php\nreturn [\n    // Scan controls (what to detect)\n    'scanComments' =\u003e true,\n    'scanInlineStyles' =\u003e true,\n    // ... 8 scan settings\n\n    // PHP optimizer rules (what to apply)\n    'optimizeAllowRiskyRules' =\u003e true,\n    'optimizeRemoveComments' =\u003e true,\n    'optimizeConvertInlineStyles' =\u003e true,\n    // ... 32 optimization rules\n];\n```\n\n#### 3. SVGO Configuration\n**Purpose:** Custom SVGO optimization rules\n**Location:** `svgo.config.js` in project root\n**Affects:** What SVGO optimizes when using `--engine=svgo`\n\n**Example:**\n```javascript\n// svgo.config.js\nexport default {\n    plugins: [\n        'removeComments',\n        'removeMetadata',\n        // ... SVGO plugins\n    ],\n};\n```\n\n#### Key Differences\n\n**Scan Controls vs PHP Optimizer:**\n- **Scan Controls** = Detection/reporting (shows issues in UI)\n- **PHP Optimizer** = Action (what gets fixed)\n- These are **independent** - you can scan for things you don't optimize, or optimize things you don't scan for\n\n**PHP Optimizer vs SVGO:**\n- **PHP Optimizer**: Uses settings from Icon Manager (32 toggles in CP plus risky-rule gating)\n- **SVGO**: Uses `svgo.config.js` file (independent of Icon Manager settings)\n\n**Example Scenario:**\n```php\n// config/icon-manager.php\n'scanComments' =\u003e false,              // Don't show in scan results\n'optimizeRemoveComments' =\u003e true,     // But still remove during optimization\n```\n\nResult:\n- Scanner won't flag comments as issues\n- PHP optimizer will still remove them (rule is enabled)\n- Files with comments won't show in \"Issue Breakdown\" but will be optimized\n\nFor SVGO: Icon Manager settings don't affect it - use `svgo.config.js` instead.\n\n## Missing Icon Handling\n\nWhen an icon file cannot be found:\n- **In templates**: Returns `null` (no errors thrown)\n- **In CP field**: Shows warning icon with tooltip\n- **In logs**: Records warning with full path details\n\nCheck if an icon exists:\n```twig\n{% if icon.exists() %}\n    {{ icon.render() }}\n{% else %}\n    {# Handle missing icon #}\n{% endif %}\n```\n\n## Performance Tips\n\n### For Large Icon Sets (500+ icons)\n\n**1. Enable Caching**\n```php\n'enableCache' =\u003e true,\n'cacheDuration' =\u003e 86400, // 24 hours\n```\n\n**2. Optimize Icon Files**\n- Run SVGO on your icon sets to reduce file sizes\n- Remove unnecessary metadata and comments\n- Use viewBox instead of width/height for responsive scaling\n\n**3. Limit Field Icon Sets**\n- Configure fields to show only relevant icon sets\n- Reduces picker loading time and improves UX\n\n**4. Use SVG Sprites for Repeated Icons**\n- If using 10+ icons from the same set on a page\n- Sprite loads once, all icons reference it\n- Significant performance improvement over individual SVG files\n\n### For Material Icons\n\nMaterial Icons loads a ~3.7MB font file containing all 3,800+ icons. For better performance:\n- Use only the icons you need as SVG files instead\n- Download specific icons from [Google Fonts](https://fonts.google.com/icons)\n- Add them to an SVG folder icon set\n\n### Cache Strategy by Environment\n\n```php\n'dev' =\u003e [\n    'cacheStorageMethod' =\u003e 'file',\n    'cacheDuration' =\u003e 3600,     // 1 hour - quick iteration\n],\n'staging' =\u003e [\n    'cacheStorageMethod' =\u003e 'file',\n    'cacheDuration' =\u003e 86400,    // 1 day - balance updates/performance\n],\n'production' =\u003e [\n    'cacheStorageMethod' =\u003e 'redis',  // Use Redis in production\n    'cacheDuration' =\u003e 2592000,       // 30 days - maximum performance\n],\n```\n\n## Logging\n\nIcon Manager uses the [LindemannRock Logging Library](https://github.com/LindemannRock/craft-logging-library) for centralized logging.\n\n### Log Levels\n- **Error**: Critical errors only (default)\n- **Warning**: Errors and warnings\n- **Info**: General information\n- **Debug**: Detailed debugging (includes performance metrics, requires devMode)\n\n### Configuration\n```php\n// config/icon-manager.php\nreturn [\n    'logLevel' =\u003e 'error', // error, warning, info, or debug\n];\n```\n\n**Note:** Debug level requires Craft's `devMode` to be enabled. If set to debug with devMode disabled, it automatically falls back to info level.\n\n### Log Files\n- **Location**: `storage/logs/icon-manager-YYYY-MM-DD.log`\n- **Retention**: 30 days (automatic cleanup via Logging Library)\n- **Format**: Structured JSON logs with context data\n- **Web Interface**: View and filter logs in CP at Icon Manager → Logs\n\n### Log Management\nAccess logs through the Control Panel:\n1. Navigate to Icon Manager → Logs\n2. Filter by date, level, or search terms\n3. Download log files for external analysis\n4. View file sizes and entry counts\n5. Auto-cleanup after 30 days (configurable via Logging Library)\n\n**Requires:** `lindemannrock/craft-logging-library` plugin (installed automatically as dependency)\n\nSee [docs/LOGGING.md](docs/LOGGING.md) for detailed logging documentation.\n\n## Permissions\n\nIcon Manager provides granular permissions for controlling access to plugin features. Permissions can be assigned to user groups or individual users in **Settings → Users → User Groups** or **Users → [User] → Permissions**.\n\n### Available Permissions\n\n| Permission | Description |\n|------------|-------------|\n| **View icon sets** | View the icon sets list in the Control Panel |\n| **Create icon sets** | Create new icon sets |\n| **Edit icon sets** | Edit existing icon sets, enable/disable sets, refresh icons |\n| **Delete icon sets** | Delete icon sets |\n| **Manage SVG optimization** | Access the SVG Optimization tab, apply optimizations, manage backups |\n| **Clear cache** | Clear icon caches (also controls visibility in Craft's Clear Caches utility) |\n| **View logs** | View plugin logs in the Control Panel |\n| ↳ **Download logs** | Download log files (nested under View logs) |\n| **Manage settings** | Access and modify plugin settings |\n\n### Permission Behavior\n\n**Icon Sets Access:**\n- Users with **any** icon set permission (view, create, edit, delete, or manage optimization) can see the Icon Sets navigation item\n- The \"New Icon Set\" button only appears for users with **Create icon sets** permission\n- Icon set names are only clickable (linking to edit page) for users with **Edit icon sets** permission\n- Delete buttons and bulk delete actions require **Delete icon sets** permission\n- The SVG Optimization tab on icon set edit pages requires **Manage SVG optimization** permission\n\n**Cache Management:**\n- The \"Icon Manager caches\" option in Craft's Clear Caches utility only appears for users with **Clear cache** permission\n- The Clear Icon Cache utility page respects this permission\n\n**Logs:**\n- The Logs navigation item only appears for users with **View logs** permission\n- The Download button in the logs viewer requires **Download logs** permission\n\n**Settings:**\n- The Settings navigation item only appears for users with **Manage settings** permission\n\n### Example Permission Configurations\n\n**Content Editor** (can use icons but not manage them):\n- ✗ No Icon Manager permissions needed\n- They can select icons in fields but cannot access the Icon Manager CP section\n\n**Icon Manager** (can manage icon sets):\n- ✓ View icon sets\n- ✓ Create icon sets\n- ✓ Edit icon sets\n- ✓ Delete icon sets\n- ✗ Manage SVG optimization (optional)\n- ✓ Clear cache\n\n**Developer** (full access):\n- ✓ All permissions\n\n**Support Staff** (can view logs only):\n- ✓ View icon sets\n- ✓ View logs\n- ✓ Download logs\n\n## Troubleshooting\n\n### Icons Not Showing in Picker\n\n**Check icon set is enabled:**\n- Go to Icon Manager → Icon Sets\n- Ensure the icon set has the green \"enabled\" status\n- Click the set and verify it's enabled in settings\n\n**Refresh icon cache:**\n- Go to Utilities → Clear Icon Cache\n- Click \"Refresh All Icons\"\n- Or go to the icon set and click \"Refresh Icons\"\n\n**Check file paths:**\n```php\n// In config/icon-manager.php\n'iconSetsPath' =\u003e '@root/icons', // Make sure this path exists\n```\n\nVerify the path exists:\n```bash\nls /path/to/your/project/icons\n```\n\n### Refresh Icons Doesn't Update the Count or Preview\n\nYou changed SVG files on disk (added new files, deleted files, removed a whole subfolder), clicked **Refresh Icons** on the icon set's edit page, but the **Icons** count and the **Preview** tab still show the pre-change state.\n\n**Force-wipe the cache:**\n- Go to **Utilities → Clear Icon Cache**. This works regardless of storage method and iterates the tracked Redis keys + per-set file caches.\n\n**Check your Cache Storage Method:**\n- Icon Manager → Settings → Cache → **Cache Storage Method**\n- If set to **Redis/Database**, verify Redis is reachable: `ddev redis ping` or your platform's equivalent.\n\n**Check the plugin log for cache-component warnings:**\n- Look for lines like `icon-manager: cacheStorageMethod=redis configured, but Craft's cache component is …`\n- This means Redis is selected as the storage method but Craft's `cache` component is not a Redis-backed Yii cache. Icon Manager logs this warning and skips Redis-specific cache operations until the cache component is fixed. Either configure Redis in `config/app.php`, or switch the plugin's storage method to **File**.\n\n**Quick workaround for a single set:**\n- Temporarily switch Cache Storage Method to **File**, save settings, click **Refresh Icons** on the set, then switch back to Redis if you want.\n\n### Settings Save Shows a Validation Error\n\nNumeric settings such as cache duration and items per page must be whole numbers within the allowed range. If a value is invalid, Icon Manager keeps you on the same settings page and shows the field error inline.\n\nWhen a setting is overridden in `config/icon-manager.php`, the Control Panel field is skipped during save. Change the config file value instead.\n\n### Icons Not Rendering in Templates\n\n**Check the icon exists:**\n```twig\n{% set icon = craft.iconManager.getIcon('mySet', 'iconName') %}\n{% if icon %}\n    {{ icon.render() }}\n{% else %}\n    Icon not found\n{% endif %}\n```\n\n**Check icon set handle:**\n- Icon set handles are case-sensitive\n- Verify the handle in Icon Manager → Icon Sets\n\n**Clear Craft cache:**\n```bash\n./craft clear-caches/all\n```\n\n### Optimization Not Working\n\n**Check optimization is enabled:**\n- Icon Manager → Settings → SVG Optimization\n- Ensure \"Enable Optimization\" is toggled on\n\n**For CLI optimization, check environment:**\n- Apply Optimizations button only works in dev/local\n- CLI commands work in all environments\n\n**SVGO not found:**\n```bash\n# Install SVGO\nnpm install --save-dev svgo\n\n# Or verify it's installed\nddev craft icon-manager/optimize/check\n```\n\n### Performance Issues with Large Icon Sets\n\n**Enable caching:**\n```php\n'enableCache' =\u003e true,\n'cacheDuration' =\u003e 86400,\n```\n\n**Limit icons per page in field:**\n- Edit the Icon Manager field\n- Set \"Icons Per Page\" to 50-100 instead of 500\n\n**Optimize SVG files:**\n- Large, unoptimized SVGs slow down the picker\n- Run optimization on your icon sets\n\n### Config File Not Working\n\n**Check file location:**\n```bash\n# Should be at:\nconfig/icon-manager.php\n\n# NOT:\nvendor/lindemannrock/icon-manager/src/config.php\n```\n\n**Verify environment:**\n```php\n// Check current environment\necho Craft::$app-\u003eenv; // Should match your config keys\n```\n\n**Check for syntax errors:**\n```bash\nphp -l config/icon-manager.php\n```\n\n## Examples\n\nFor more real-world template examples, see [docs/EXAMPLES.md](docs/EXAMPLES.md) including:\n\n- Navigation menus with icons\n- Feature cards and icon grids\n- Social media links\n- Button components with loading states\n- Dynamic icon selection\n- Multi-site and RTL support\n- Tailwind CSS integration\n- Performance optimization techniques\n- Accessibility best practices\n\n## Support\n\n- **Documentation**: [https://github.com/LindemannRock/craft-icon-manager](https://github.com/LindemannRock/craft-icon-manager)\n- **Issues**: [https://github.com/LindemannRock/craft-icon-manager/issues](https://github.com/LindemannRock/craft-icon-manager/issues)\n- **Email**: [support@lindemannrock.com](mailto:support@lindemannrock.com)\n\n## License\n\nThis plugin is licensed under the [Craft License](https://craftcms.github.io/license/). See [LICENSE.md](LICENSE.md) for details.\n\n---\n\nDeveloped by [LindemannRock](https://lindemannrock.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flindemannrock%2Fcraft-icon-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flindemannrock%2Fcraft-icon-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flindemannrock%2Fcraft-icon-manager/lists"}