icon-system Stinger

SkillDev tools

Icon-system specialist for React/Next.js: library selection (Lucide, Heroicons, Tabler, Phosphor, Iconify), tree-shake-vs-SVG-sprite trade-off, dynamic-import-by-name pattern, custom SVG component authoring, and the accessibility contract (aria-hidden for decorative icons, aria-label for semantic icons, accessible name for icon buttons). Use when choosing an icon library, debugging bundle-size regressions from icon imports, wiring a dynamic icon loader, building a custom SVG wrapper, or auditing icon accessibility. Paired with `icon-system-worker-bee`.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the icon-system Stinger skill

What this skill tells your AI

The instructions your AI receives, as published by legioncodeinc/vibe-coding-tools in src/skills/icon-system-stinger/SKILL.md and read by ahel’s review.

Procedural arsenal for icon-system-worker-bee. Encodes the canonical icon library selection matrix, the tree-shake-vs-SVG-sprite delivery decision, the dynamic-import-by-name pattern, custom SVG component conventions, and the accessibility contract covering the three icon categories (decorative, semantic, interactive).


When this stinger applies

Load when icon-system-worker-bee is invoked. Typical triggers:

  • "Which icon library should we use?"
  • "My icon imports are bloating the bundle"
  • "How do I load an icon by name at runtime?"
  • "Build me a reusable icon component"
  • "Audit our icons for accessibility"
  • "Should I use an SVG sprite?"
  • "Icon button has no accessible name"

Do NOT load for:

  • Icon size and color tokens (ux-ui-svelte-worker-bee owns those)
  • General React component architecture (react-worker-bee)
  • SVG sprite build-pipeline tooling at the bundler level (devops-worker-bee)
  • General bundle-optimization strategies beyond icon imports (devops-worker-bee)

First action when this stinger is loaded

  1. Read guides/00-library-selection-matrix.md: pick the right icon library first.
  2. Read guides/01-tree-shake-vs-sprite.md: choose the delivery strategy.
  3. Read the per-task guide relevant to the request (02 through 04).
  4. Use templates/icon-audit-report.md to structure any output audit report.

Library selection matrix (summary)

LibraryBest forIcon countTree-shaking
LucideDefault React/Next.js apps; best DX1400+Named ESM exports; full
HeroiconsTailwind CSS projects; curated small set~292Named ESM by variant path
TablerAdmin UIs needing extensive coverage5500+Named ESM per icon
PhosphorDesign systems needing weight variants1300+Named ESM; weight is a prop
IconifyMulti-library mixing OR large on-demand sets200,000+Static bundled or CDN

See guides/00-library-selection-matrix.md for the full decision table with edge cases and installation snippets.


Tree-shake vs SVG sprite (summary)

StrategyWhen to choose
Named ESM imports (default)Single app, defined icon set, <200 icons
SVG spriteIcons needed in 3+ separate JS bundles; non-React rendering contexts
Iconify on-demand (CDN)Large icon sets where most icons appear on few pages; admin tools only

See guides/01-tree-shake-vs-sprite.md for the full decision matrix and Vite/Next.js configuration snippets.


Dynamic icon by name (summary)

For cases where the icon name arrives as a string prop at runtime:

// Safe approach: static map built at compile time
import * as LucideIcons from 'lucide-react';
import type { LucideIcon } from 'lucide-react';

const iconMap: Record<string, LucideIcon> = LucideIcons as any;

function DynamicIcon({ name, ...props }: { name: string } & LucideProps) {
  const Icon = iconMap[name];
  if (!Icon) return null;
  return <Icon {...props} />;
}

Do NOT use React.lazy per-icon for above-the-fold content. See guides/02-dynamic-import-icon-name.md for the full pattern, TypeScript safety, and RSC boundary guidance.


Accessibility contract (summary)

Icon categoryRequired attributes
Decorative (has adjacent text)aria-hidden="true" + focusable="false" on SVG
Semantic (standalone, no text)aria-label on container OR role="img" + <title> on SVG
Interactive (icon button)aria-label on <button>; SVG gets aria-hidden="true"

See guides/03-accessibility-contract.md for implementation details and axe-core failure modes. Source: research/external/icon-accessibility.md.


Critical directives

  • Never import from a library's barrel root unless tree-shaking is guaranteed. Barrel imports from some-icon-lib without ESM named exports bundle every icon. Use named imports or path imports. See guides/01-tree-shake-vs-sprite.md.
  • Always apply the decorative-vs-semantic distinction. Every icon must either be hidden from AT (aria-hidden="true") or carry an accessible name. Unlabeled icon buttons are a WCAG 2.1 Level A failure.
  • Never use dynamic-by-name for SSR-critical above-the-fold icons. Dynamic imports introduce loading waterfalls; use static named imports for hero content.
  • Prefer Iconify only when multi-library mixing is genuinely needed. Single-library projects pay Iconify's runtime overhead without benefit.
  • Custom SVG components must set focusable="false" on the <svg> element. Without it, SVGs receive keyboard focus in legacy Edge and some screen readers.

Folder layout

icon-system-stinger/
├── SKILL.md                              (this file)
├── README.md
├── guides/
│   ├── 00-library-selection-matrix.md
│   ├── 01-tree-shake-vs-sprite.md
│   ├── 02-dynamic-import-icon-name.md
│   ├── 03-accessibility-contract.md
│   └── 04-custom-svg-component.md
├── examples/
│   ├── lucide-icon-component.md
│   └── dynamic-icon-loader.md
├── templates/
│   └── icon-audit-report.md
├── reports/
│   └── README.md
└── research/
    ├── research-plan.md
    ├── research-summary.md
    ├── index.md
    ├── internal/
    │   └── command-brief.md
    └── external/
        ├── lucide-react.md
        ├── iconify-react.md
        ├── heroicons-tabler-phosphor.md
        ├── icon-sprite-patterns.md
        └── icon-accessibility.md

Forged by stinger-forge from icon-system-worker-bee-command-brief.md and research/. Part of The Hive by Mario Aldayuz a.k.a @thenotoriousllama.

Signals

GitHub stars
83
Forks
37
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
icon-system-stinger
Source
github.com/legioncodeinc/vibe-coding-tools