Phosphor Icons 2020—
  1. [top]
  2. # An obsession
  3. # Providing great DX
  4. # Automate the fragile stuff, test everything
  5. # Giving Phosphor a home
  6. # Looking ahead

Phosphor Icons

An open source icon library for React, Vue, and vanilla JS

2020—

An obsession

A few years ago I made the switch from iPhone to Android. I wanted to escape Apple’s walled garden and start using technology that permitted me to modify and customize it to my liking, to make my own. I made a techy dashboard for my phone, with design help from my partner Helena Zhang. She designed around 40 custom, minimal icons to replace the common utility app icons and fit in with the hacker aesthetic.

Over time that seed grew, eventually becoming a complete set of icons for Android home screens, replacing icons for over 800 of the most common apps with clean, minimalistic, monochromatic glyphs. We released different colorways, took icon suggestions, got involved in the small but active community of phone customizers. Helena even wrote several articles on the subject of icon design and history. We were eating, breathing, and sleeping icons.

48

Eventually we realized that all this effort could serve a much larger audience of digital designers and engineers of all walks, not just the Android enthusiasts. We decided to create a library of general-purpose user interface icons for modern web, desktop, and mobile platforms — and Phosphor Icons was born.

Providing great DX

I knew that its success would not come down to the design of the icons alone. We wanted to make an icon library that was as easy to learn as it was to use, covered the vast majority of platforms, and just worked. We needed to provide a top-tier developer experience to those using the icons. This meant not only supporting the most common frameworks, with packages for React, Vue, and vanilla JS, but also exposing an intuitive API and writing great documentation.

We wanted to make an icon library that was as easy to learn as it was to use, covered the vast majority of platforms, and just worked.

Taking advantage of React’s Context API and Vue’s provide/inject feature, I brought stateful local and global styling to the icon components. You could set the appearance of all icons in a subtree from one place, but unlike CSS it could be dynamic and manipulated programmatically.

import React from "react";
import { createRoot } from 'react-dom/client';
import { IconContext, Horse, Heart, Cube } from "phosphor-react";

const App = () => {
  return (
    <IconContext.Provider
      value={{
        color: "limegreen",
        size: 32,
        weight: "bold",
        mirrored: false,
      }}
    >
      <div>
        <Horse /> {/* I'm lime-green, 32px, and bold! */}
        <Heart /> {/* Me too! */}
        <Cube />  {/* Me three :) */}
      </div>
    </IconContext.Provider>
  );
};

createRoot(document.getElementById('root')!).render(<App />);

Automate the fragile stuff, test everything

When working with large component libraries, it’s important to factor out sources of human error. Mistakes crop up inevitably at scale, and with 9072 icons and their corresponding implementations — packages in 5 javascript frameworks, a Figma plugin and library, and other things I’m forgetting — we had a lot of complexity to manage by hand. This led me to build custom internal tooling to support our efforts from the design process all the way through to production, including:

A small battery of unit and integration tests ensured that our automated approach wouldn’t propagate subtle bugs throughout the system. And at the end of it all, we generated example apps to allow thorough inspection of every icon with the good ol’ Mark I Eyeball™. This usually consisted of large contact-sheets with multiple instances of each icon in its many variants and sizes, arranged to visually highlight inconsistencies.

Aside from reducing carpal tunnel risks for my partner and myself, the automation and testing processes gave us a confidence we couldn’t get doing all of this manually.

Giving Phosphor a home

Naturally, we needed a fun and functional site to house the project. We wanted a searchable interface for the icon library that showcased each icon variant, along with code snippets for developers to quickly reference. And to show off a bit with sleek, snappy animations and strong visual demonstrations of the icons in use.

I took it as an opportunity to try out some new tools in the React ecosystem. TypeScript formed the foundation for less buggy code with more compile-time guarantees. I used the (now archived) Recoil, an experimental state management library from Facebook. It was an absolute joy to work with, and eliminates hundreds of lines of Redux boilerplate. I implemented a smart client-size fuzzy search with help from the awesome Fuse.js library, making searching for icons much more forgiving.

phosphoricons.com

phosphoricons.com
Above-the-fold content on the new Phosphor site

Ultimately, we managed to pack a ton of ergonomic features into a simple and straightforward one-page site, and even received some accolades from sites like:

Looking ahead

We continue to grow the library, using analytics and feedback from the community to add the most-needed icons first. We hope to expand to support more use-cases for developers and designers alike. A Flutter library, along with a number of other third-party ports, have since been added, and we have plans for more down the road.