Skip to content

Iconography

Icons communicate meaning quickly and reinforce text labels. Tessera UI provides design guidelines that work with any icon library, plus a built-in ts-icon component with Lucide icons available out of the box.

For setup and configuration details, see the Icons setup guide.

Icons should align with the type scale for visual consistency:

ContextIcon SizeMatching Font Token
Badge, caption12px--ts-font-size-xs
Button (sm), label14px--ts-font-size-sm
Button (md), body text16px--ts-font-size-md
Button (lg), subheading18px--ts-font-size-lg
Section header20px--ts-font-size-xl
Hero, display24px+--ts-font-size-2xl+

Rule of thumb: Icon size should match the font-size of adjacent text. If an icon sits next to 14px text, the icon should be 14px.

For outlined icon libraries, maintain consistent stroke width across all icons:

  • Recommended: 1.5px2px stroke width
  • Avoid mixing stroke widths within the same interface — this creates visual noise
  • Choose a weight and apply it consistently (most libraries support this via props or CSS)

Icons should vertically center with their adjacent text. Tessera UI components handle this automatically via inline-flex and align-items: center:

<ts-button>
<ts-icon slot="prefix" name="save" size="sm"></ts-icon>
Save
</ts-button>

For standalone icons next to text, use flexbox:

.icon-text {
display: inline-flex;
align-items: center;
gap: var(--ts-spacing-2);
}

Tessera UI components provide prefix and suffix slots for icon placement:

<ts-button>
<ts-icon slot="prefix" name="download" size="sm"></ts-icon>
Download
<ts-icon slot="suffix" name="external-link" size="sm"></ts-icon>
</ts-button>
<ts-input label="Search">
<ts-icon slot="prefix" name="search" size="md"></ts-icon>
</ts-input>
<ts-alert variant="info">
<ts-icon slot="icon" name="info" size="md"></ts-icon>
Your changes have been saved.
</ts-alert>
  • Decorative icons (next to text that conveys meaning): omit the label prop — ts-icon sets aria-hidden="true" automatically
  • Meaningful icons (no adjacent text): set the label prop — ts-icon sets role="img" and aria-label automatically
  • Icon-only buttons: always provide an aria-label on the button
<!-- Decorative — text conveys meaning, icon is supplementary -->
<ts-button>
<ts-icon slot="prefix" name="trash-2"></ts-icon>
Delete
</ts-button>
<!-- Meaningful — icon IS the label -->
<ts-button aria-label="Close">
<ts-icon slot="prefix" name="x" label="Close"></ts-icon>
</ts-button>
LibraryStyleLicenseBest For
Lucide (built-in)Outlined, geometricISCGeneral-purpose UI
PhosphorSix weight variantsMITFlexible, multi-weight designs
HeroiconsOutlined + solidMITTailwind-adjacent projects
Material SymbolsOutlined + filled + roundedApache 2.0Material Design ecosystems
Tabler IconsOutlined, consistent strokeMITClean, minimal UI

Lucide is available out of the box. To use a different library, see Swapping icon libraries.

  1. One icon library per project. Mixing libraries creates visual inconsistency in stroke width, style, and proportions.
  2. Use semantic icons. A trash can means “delete,” a pencil means “edit.” Don’t repurpose icons for unrelated actions.
  3. Don’t use icons as the sole indicator of state. Always pair icons with text or ARIA labels for accessibility.
  4. Size icons to match text. An oversized icon next to small text looks unbalanced. Use the sizing table above.
  5. Prefer ts-icon over raw SVG. The component handles sizing, color inheritance, and accessibility attributes consistently.