Iconography
Roadie uses Phosphor Icons at the Bold weight. The thicker strokes pair with the system's rounded, approachable visual language and stay legible at small sizes.
Principles
Use icons intentionally. Pair with text labels wherever possible. Avoid decorative-only icons that add clutter without aiding comprehension.
Prefer existing icons. Browse Phosphor's library before considering custom SVGs. Reusing established metaphors keeps the system consistent.
Keep it consistent. Always Bold weight. Only use Fill for active or selected states. Never mix Regular, Thin, or Light weights.
Visual style
Bold weight provides thicker strokes that are more legible at small sizes and create a confident, approachable feel. Here are some commonly used icons in the system.
Heart
Star
Plus
Trash
MagnifyingGlass
Gear
CaretDown
CheckCircle
Weight
Three weights are used in the system. Bold is the default for everything. Fill is reserved for active or selected states. Duotone is for large, decorative icons — feature surfaces and icons inside an IconTile above 48px, where a bold outline alone looks hollow.
| Weight | When to use | Preview |
|---|---|---|
| bold | Default for all icons | |
| fill | Active or selected states only | |
| duotone | Large decorative icons only (48px+, e.g. in an IconTile) |
Example: navigation items using Bold (inactive) and Fill (active).
Reserve duotone for large, decorative icons
Duotone adds depth at large sizes but muddies legibility when small.
Do
weight="duotone" for icons 48px and up — feature surfaces and icons inside an IconTile — where the two-tone fill reads as intentional depth.Don’t
weight="bold" instead.Sizing
Four fixed tiers mapped to component contexts. Use Tailwind size-* utilities via className to set icon size.
| Tier | Size | Class | Use for | Preview |
|---|---|---|---|---|
| XS | 12px | size-3 | Badges, tags, compact elements, chevrons in small buttons | |
| SM | 16px | size-4 | Buttons, inline with body text (default) | |
| MD | 20px | size-5 | Navigation, standalone actions | |
| LG | 24px | size-6 | Page headers, feature cards, hero sections |
Auto-sizing in components: Badge, Button, and IconTile auto-size child SVGs via CSS ([&_svg]:size-[1em] and [&_svg]:size-4). You typically don't need an explicit size class when placing icons inside these components.
Icon tiles
When an icon needs to stand on its own — leading a dialog, a list row, or an empty state — frame it in an IconTile. The tile sizes and centres the icon for you, so you pass a bare icon as children with no size class.
Weight inside tiles: tiles are the one place weight="duotone" is welcome. Use weight="bold" up to 48px, then switch to duotone above 48px, where a bold outline can look hollow on the larger surface. Keep Fill reserved for active states as elsewhere.
Import conventions
Use the Icon suffix export
Phosphor exports each icon with an Icon suffix. Always use the suffixed export — the bare name is deprecated.
import {HeartIcon,StarIcon} from '@phosphor-icons/react/ssr'
Do
Icon-suffixed export directly.import {Heart,Star} from '@phosphor-icons/react/ssr'
Don’t
Use the SSR import for server components
Phosphor provides a /ssr entry point that avoids hydration mismatches in server components.
// Server component (no 'use client')import {HeartIcon} from '@phosphor-icons/react/ssr'
Do
@phosphor-icons/react/ssr in server components.// Server component (no 'use client')import {HeartIcon} from '@phosphor-icons/react'
Don’t
Color
Icons inherit currentColor by default. Use text-* utilities to set icon color, or let them inherit from a parent intent context.
text-normal
text-subtle
text-strong
intent-danger
intent-success
Guidelines
Pair icons with text labels
Icons are most effective when paired with text. Use icon-only buttons only when the action is universally understood, and always provide an aria-label.
Do
IconButton which requires aria-label.Don’t
Use Bold weight consistently
All icons should use weight="bold". Don't mix weights — it breaks visual harmony.
Do
Don’t
Reserve Fill for active states
Fill weight signals that something is selected or active. Don't use it as the default.
Do
Don’t
Match icon size to context
Use the sizing scale to keep icons proportional to their surroundings.
Do
Don’t
Best practices
Always set
weight="bold"explicitly. Phosphor's default is Regular, not Bold.Use
aria-labelon icon-only buttons. TheIconButtoncomponent enforces this as a required prop.Browse icons at phosphoricons.com — filter by Bold weight to see what's available.
Icons inherit
currentColor. Usetext-*utilities for color. Don't use inline styles or the Phosphorcolorprop.Inside Badge, Button, and IconTile, icons auto-size. No explicit
classNamesize needed — the component CSS handles it.Use
@phosphor-icons/react/ssrfor server components. Only use@phosphor-icons/reactin files with'use client'.