Files
nick-doc/05 - Design System/Iconography.md
2026-05-23 20:35:34 +03:30

5.8 KiB

title, tags, created
title tags created
Iconography
design-system
icons
iconify
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/:

import { Iconify } from 'src/components/iconify';

<Iconify icon="solar:user-bold" />
<Iconify icon="eva:close-fill" width={20} />
<Iconify icon="mingcute:check-fill" sx={{ color: 'success.main' }} />

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):

<Iconify icon="solar:bell-bold" width={24} />

4. Color

Color comes from the parent's color CSS property (Iconify renders with fill: currentColor). Use the sx prop:

<Iconify icon="solar:check-circle-bold" sx={{ color: 'success.main' }} />
<Iconify icon="solar:warning-bold" sx={{ color: 'warning.dark' }} />

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:

<Box sx={{ direction: 'ltr' }}>
  <Iconify icon="solar:play-bold" />
</Box>

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:

import { SvgColor } from 'src/components/svg-color';

<SvgColor src="/assets/icons/custom-shape.svg" sx={{ color: 'primary.main' }} />

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:
    <IconButton aria-label="close"><Iconify icon="eva:close-fill" /></IconButton>
    
  • 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.