Problem
Icon.tsx is 1,268 lines / 66KB containing 61 inline SVGs in a single switch statement. Additionally, 19 separate SVG components exist in web/components/svg/ and ~35 icons use @ionic/react IonIcon across 42 files (#7022) — 3 icon systems total.
Performance impact
- 66KB parsed on every page load even if only a few icons are used
- Not tree-shakable — bundler includes all 61 icons regardless of usage
- No lazy loading — heavy icons (GitHub SVGs) load on pages that don't need them
For non-frontend context
Think of it like importing an entire Python library when you only need one function. Tree-shaking (the bundler excluding unused code) only works with proper module imports, not giant switch statements.
Solution
- Extract each icon to its own file (e.g.
components/icons/CloseIcon.tsx)
- Integrate the 19
svg/ components into the same system
- Keep the
<Icon name="..." /> API as a convenience wrapper that dynamically imports
- Bundlers tree-shake unused icons automatically
// Before: 66KB loaded regardless
<Icon name="close" />
// After: only this icon is bundled
import { CloseIcon } from 'components/icons/CloseIcon'
<CloseIcon />
Acceptance criteria
Related
Part of the Design System Audit (#6606) · Epic: #6882
Problem
Icon.tsxis 1,268 lines / 66KB containing 61 inline SVGs in a single switch statement. Additionally, 19 separate SVG components exist inweb/components/svg/and ~35 icons use@ionic/reactIonIcon across 42 files (#7022) — 3 icon systems total.Performance impact
For non-frontend context
Think of it like importing an entire Python library when you only need one function. Tree-shaking (the bundler excluding unused code) only works with proper module imports, not giant switch statements.
Solution
components/icons/CloseIcon.tsx)svg/components into the same system<Icon name="..." />API as a convenience wrapper that dynamically importsAcceptance criteria
svg/components integrated<Icon name="..." />API still worksRelated
Part of the Design System Audit (#6606) · Epic: #6882