--- title: Iconography tags: [design-system, icons, iconify] created: 2026-05-23 --- # Iconography Icons come from **Iconify** — a unified SVG icon library aggregating 100k+ icons from dozens of icon sets, loaded on-demand. > [!important] > Per cursor rules (`backend/.cursor/rules/ui-development-standards.mdc`), Iconify is the **only** icon system. Do NOT import from `@mui/icons-material`, `react-icons`, or inline SVG files unless you're building a wholly custom illustration. --- ## 1. Library Installed as `@iconify/react`. Wrapped by `frontend/src/components/iconify/`: ```tsx import { Iconify } from 'src/components/iconify'; ``` Props: `icon` (required), `width` (number or string, default 20), `sx` (any MUI sx), plus standard HTML attributes. --- ## 2. Approved icon sets Per the cursor rules, **prefer** these prefixes: | Prefix | Set | Style | Best for | |---|---|---|---| | `solar:` | Solar Icons | Bold / Line / Linear / Outline | Default everywhere — most consistent | | `eva:` | Eva Icons | Fill / Outline | Compact UI icons (close, more, plus) | | `mingcute:` | MingCute | Fill / Line | Detailed actions | | `mdi:` | Material Design Icons | Many variants | Use only when above sets lack the metaphor | | `simple-icons:` | Brand logos | Monochrome | Social platforms, third-party brands | | `flagpack:` | Country flags | Filled | Language switcher, address country | > [!tip] > Pick ONE style per set across the app for visual consistency. The default convention is `solar:*-bold` for filled and `solar:*-line-duotone` for accents. --- ## 3. Sizing | Size | Use | |---|---| | 16 px | Inline with text (caption, body2) | | 20 px | Inline with body1, navigation items, buttons (default) | | 24 px | Standalone action buttons, primary nav | | 32 px | Empty-state illustrations, large CTAs | | 48 px+ | Hero illustrations (consider Lottie or `react-icons` set built for hero use) | Set via `width` (icon is always square): ```tsx ``` --- ## 4. Color Color comes from the parent's `color` CSS property (Iconify renders with `fill: currentColor`). Use the `sx` prop: ```tsx ``` Never hard-code hex — go through palette tokens. --- ## 5. Common icon mappings A non-exhaustive convention table: | Action / Concept | Recommended icon | |---|---| | Search | `solar:magnifer-bold` | | Close | `eva:close-fill` | | Add / Create | `solar:add-circle-bold` or `mingcute:add-fill` | | Edit | `solar:pen-bold` | | Delete | `solar:trash-bin-trash-bold` | | Settings | `solar:settings-bold` | | Notifications | `solar:bell-bold` (badge for unread) | | User / Profile | `solar:user-bold` | | Avatar group | `solar:users-group-rounded-bold` | | Shopping cart | `solar:cart-bold` | | Filter | `solar:filter-bold` | | Sort | `solar:sort-bold` | | More menu | `eva:more-vertical-fill` | | Back | `solar:alt-arrow-left-bold` (auto-flips RTL) | | Forward | `solar:alt-arrow-right-bold` | | Up / Down | `solar:alt-arrow-up-bold` / `solar:alt-arrow-down-bold` | | Success | `solar:check-circle-bold` | | Warning | `solar:danger-bold` | | Error | `solar:close-circle-bold` | | Info | `solar:info-circle-bold` | | Upload | `solar:upload-bold` | | Download | `solar:download-bold` | | Copy | `solar:copy-bold` | | Eye (show/hide password) | `solar:eye-bold` / `solar:eye-closed-bold` | | Wallet | `solar:wallet-money-bold` | | Coin / Token | `solar:dollar-bold`, `mingcute:coin-fill` | | QR code | `solar:qr-code-bold` | | Chat | `solar:chat-round-bold` | | Send (chat) | `solar:plain-bold` | | Attachment | `eva:attach-2-fill` | | Calendar | `solar:calendar-bold` | | Clock | `solar:clock-circle-bold` | | Location | `solar:map-point-bold` | | Phone | `solar:phone-bold` | | Email | `solar:letter-bold` | | Lock | `solar:lock-password-bold` | | Unlock | `solar:lock-unlock-bold` | | Star (rating) | `solar:star-bold` (filled) / `solar:star-linear` (empty) | | Hamburger | `solar:hamburger-menu-bold` | | Refresh | `solar:refresh-bold` | | Logout | `solar:logout-3-bold` | --- ## 6. RTL & direction Direction-implying icons (chevrons, arrows, swipe) are flipped automatically by `stylis-plugin-rtl` for arrow-class icons. Semantic icons (play, share, send) should NOT flip — wrap them in: ```tsx ``` Or use `transform: 'scaleX(-1)'` on RTL if you specifically need to mirror. --- ## 7. Custom SVG (when Iconify is not enough) Place SVGs in `public/assets/icons/` or `frontend/src/assets/icons/` and use: ```tsx import { SvgColor } from 'src/components/svg-color'; ``` `svg-color` uses the mask-image technique so a single-color SVG inherits the parent color, matching Iconify behavior. For multi-color illustrations, ship them as separate files in `public/illustrations/` and reference with Next `Image`. --- ## 8. Accessibility - Icon-only buttons MUST have `aria-label`: ```tsx ``` - Icons next to a label are decorative — no aria-label needed. - Live status icons (loading, success) inside a `aria-live="polite"` region announce changes. --- ## 9. Performance - Iconify loads icons on demand from its CDN (or self-hosted if configured). - Bundle impact is minimal — only the icon component, not the icon data. - For the most-used set (e.g., `solar:*`), consider pre-loading via `@iconify-icons/solar` to remove the CDN dependency. --- ## 10. Related - [[Design System Overview]] · [[Components]] · [[Colors]] - [[Coding Standards]] — Iconify rule cited