why phosphor?

An overview of why Caddy uses Phosphor Icons and how to get the most from the library.

Caddy uses Phosphor Icons — a flexible, open-source family of over 9,000 icons available in six weights: Thin, Light, Regular, Bold, Fill, and Duotone.

We chose Phosphor for three reasons:

1.

Breadth and reliability.

The library is extensive and actively maintained, covering nearly every interface need without requiring custom icons.

2.

Weight flexibility.

Six weights let you match visual density to context — lighter weights for editorial moments, heavier for small-scale UI — while keeping shapes instantly recognizable.

3.

Shape integrity.

Despite weight variation, every Phosphor icon reads clearly at a glance. The geometry is designed for universality, not cleverness. This is why we use Phosphor rather than custom icons.

A 2013 benchmark study on icon comprehension across non-literate users found that the most effective icons use concrete, real-world shapes that transcend language and cultural context — Phosphor's core design principle. Accessible design benefits everyone.

Read the IAENG study →

product icon guidance

Usage principles for designers building the Chipin product UI.

When to use icons

Icons belong in buttons, icon buttons, navigation elements, avatar-icons, status indicators, and task progress indicators. Their job is to help users understand the purpose of an interactive element or the state of the system — instantly, without reading.

DO

  • ·Use icons in buttons to reinforce the action
  • ·Use icons in nav to signal destination or mode
  • ·Use icons to show system status (e.g. checkmark for complete)
  • ·Use icons in avatar-icon components to represent user types

DON'T

  • ·Use icons purely for decoration
  • ·Use icons on success screens — use an illustration
  • ·Use icons on product showcase screens — use an illustration
  • ·Combine icons with labels that contradict the icon's meaning

Choosing icons

Choose icons that are instantly interpretable. If there's any question about what an icon means in context, choose a different one. For nav and buttons, the icon should be able to stand in for the label — not just accompany it. Use concrete, real-world imagery.

DO

ph-clock for event time
ph-calendar for date selection
ph-arrow-right for next / continue

DON'T

ph-alarm for event time
ph-calendar-check for unconfirmed events
ph-caret-right where more visual weight is needed

Weights

Default to Regular for all product UI. Adjust weight based on size and context. Within any group of related actions, use the same weight and size for all icons in that group.

Example Weight When to use
Regular Default for all product UI
Bold When icons appear at very small sizes (under 16px)
Fill Selected or active states (e.g. active nav icon)
Light Larger icons where less visual mass is appropriate
Thin Large illustrative icons only
Duotone Card buttons, data points, feature highlights only

Hard rule

Never use Duotone in navigation elements. Reserve it for cards, data indicators, and feature highlights.

DO

  • ·Use Regular across all items in a navigation bar
  • ·Use Duotone in a feature card component
  • ·Use Fill to show active / selected state

DON'T

  • ·Mix Bold and Regular in the same nav bar
  • ·Use Duotone in a sidebar nav item
  • ·Use Fill for all icons regardless of state

Colour

Use icon semantic tokens as a starting point. Apply colour with intention — sentiment tokens communicate system state, not decoration.

Example Token Use
--icon-neutral Default colour for most UI contexts
--icon-positive Success states, confirmations
--icon-negative Error states, destructive actions
--icon-warning Caution, pending states

Icons nested within interactive elements should use a content colour token to match adjacent text — e.g. --content-primary or --content-on-primary.

Applying secondary palette colours to icon and avatar-icon elements is one of the best ways to add personality without visual clutter — ideal for card buttons, feature lists, or anywhere a colour accent adds context.

Avoid using sentiment icon tokens (--icon-positive, --icon-negative) for decoration or branding. Use secondary colours instead.

editorial icon guidance

Usage principles for editorial, marketing, and branded content.

When to use icons

DO

  • ·Pair an icon with a feature description to reinforce the message
  • ·Use icons to anchor a proof point (e.g. beside Donation Management copy)
  • ·Use icons to add visual rhythm to a list of features or benefits

DON'T

  • ·Use icons as a substitute for illustration or UI screenshots
  • ·Use icons in place of a headline image or hero graphic
  • ·Use icons decoratively with no semantic relationship to the content

Weights

In editorial you have more creative freedom — use any weight that serves the design. The same consistency rule applies within sections: all icons in a proof-point row should share the same weight. Different sections can differ.

Colour

Use best judgement. Pull from the content palette for a grounded, typographic tone; the secondary palette to add personality; or icon semantic tokens for structured, system-like moments. Avoid using sentiment tokens (--icon-positive, --icon-negative) for promotion or decoration.

getting started with phosphor

Phosphor Icons is available for React, Vue, web components, and vanilla HTML. The primary path for Chipin's stack is @phosphor-icons/react.

React (Chipin Stack)

Install:

npm install @phosphor-icons/react

Basic usage:

import { CalendarCheck, Bell, ArrowRight } from "@phosphor-icons/react";

<CalendarCheck />
<Bell size={24} weight="bold" color="var(--icon-neutral)" />

Set global defaults via context:

import { IconContext } from "@phosphor-icons/react";

<IconContext.Provider value={{ size: 20, weight: "regular" }}>
  <App />
</IconContext.Provider>

Props reference:

Prop Type Default Description
size number | string 1em Width and height
weight "thin" | "light" | "regular" | "bold" | "fill" | "duotone" "regular" Icon weight / style
color string currentColor Stroke / fill — accepts CSS vars
mirrored boolean false Flip horizontally for RTL
alt string Accessible alt text

Next.js bundle optimisation:

// next.config.js
module.exports = {
  experimental: {
    optimizePackageImports: ["@phosphor-icons/react"],
  },
};

SSR / Server Components — import from the /ssr sub-path:

import { BellIcon } from "@phosphor-icons/react/ssr";

Vanilla HTML

Load only the weights you need (recommended):

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@phosphor-icons/web@2.1.2/src/regular/style.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@phosphor-icons/web@2.1.2/src/fill/style.css" />

<i class="ph ph-calendar-check"></i>
<i class="ph-fill ph-heart" style="color: var(--icon-positive)"></i>

Load all weights via a single script (~3 MB — avoid in production):

<script src="https://cdn.jsdelivr.net/npm/@phosphor-icons/web@2.1.2"></script>

Weight class prefix reference:

Example Weight Class prefix
Regular ph
Bold ph-bold
Fill ph-fill
Light ph-light
Thin ph-thin
Duotone ph-duotone

Applying Caddy Tokens

Always apply colour using CSS custom properties — never hardcoded hex values.

// ✅ Token-driven
<Bell color="var(--icon-neutral)" />
<CheckCircle color="var(--icon-positive)" />

// ✅ Inherits currentColor from parent
<span style={{ color: "var(--content-primary)" }}>
  <ArrowRight />
</span>

// ❌ Avoid — hardcoded colour
<Bell color="#065c3e" />

Recommended sizes by context:

Context Size
Inline with body text 1em
Button icons 20px
Navigation icons 24px
Avatar-icon 20–24px
Card / feature icon 32–40px
Duotone / editorial 40–56px