Icon Component

The Icon component renders SVG icons with support for animations and theming. Icons are provided via the IconProvider context and can include transition animations between states.

Usage

Basic Icon

Icons are rendered by passing the icon name to the icon prop. The icon must be registered in the IconProvider.

<Icon icon="check" />

IconProvider Setup

Before using icons, you must wrap your app with IconProvider and provide an IconIndex containing your SVG icons.

import { IconProvider, Icon } from "@228-co/reef/components";

const icons = {
  check: {
    default: '<svg>...</svg>',
    animations: {
      "pulse": ['<svg>...</svg>', 300],
    },
  },
  loading: {
    default: '<svg>...</svg>',
  },
};

function App() {
  return (
    <IconProvider icons={icons}>
      <Icon icon="check" />
    </IconProvider>
  );
}

Custom Styling

Apply custom StyleX styles to the icon container using the style prop.

const customStyles = stylex.create({
  largeIcon: {
    width: "48px",
    height: "48px",
  },
});

<Icon icon="check" style={customStyles.largeIcon} />

Icon Animations

Icons can have animations defined in the IconIndex. Use the ref to trigger animations programmatically.

function AnimatedIcon() {
  let iconRef;

  const handleClick = () => {
    iconRef?.playAnimation("pulse");
  };

  return (
    <button onClick={handleClick}>
      <Icon icon="check" ref={(r) => (iconRef = r)} />
    </button>
  );
}

Auto Transition Animations

When switching between icons, the component automatically plays transition animations if defined with the "to:iconName" naming convention.

const icons = {
  play: {
    default: '<svg>...</svg>',
    animations: {
      "to:pause": ['<svg>...</svg>', 200],
    },
  },
  pause: {
    default: '<svg>...</svg>',
    animations: {
      "to:play": ['<svg>...</svg>', 200],
    },
  },
};

// Transition animation plays automatically when icon changes
<Icon icon={isPlaying() ? "pause" : "play"} />

Queuing Animations

Use queueAnimation to add animations to a queue that plays sequentially.

function QueuedAnimations() {
  let iconRef;

  const handleMultipleAnimations = () => {
    iconRef?.queueAnimation("bounce");
    iconRef?.queueAnimation("spin");
    iconRef?.queueAnimation("pulse");
  };

  return (
    <button onClick={handleMultipleAnimations}>
      <Icon icon="star" ref={(r) => (iconRef = r)} />
    </button>
  );
}

Icon Props

NameTypeDefaultDescription
iconstring(required)

The name of the icon to render. Must match a key in the IconIndex provided to IconProvider.

colorsstylex.Theme<...>undefined

StyleX theme override for icon colors (iconPrimaryColor and iconSecondaryColor).

styleStyleXStylesundefined

Additional StyleX styles to apply to the icon container.

refIconRef | ((ref: IconRef) => void)undefined

Ref to access animation methods: playAnimation(name) and queueAnimation(name).

IconProvider Props

NameTypeDefaultDescription
childrenJSXElement-

Child components that will have access to the icon index.

iconsIconIndex-

An object mapping icon names to their SVG content and optional animations.

Types

IconRef

The ref object provides methods to control icon animations:

type IconRef = {
  playAnimation: (name: string) => Promise<void>;
  queueAnimation: (name: string) => void;
};

IconIndex

The icon index maps icon names to their SVG content and optional animations:

type IconIndex = Record<
  string,
  {
    default: string;  // SVG string for the default state
    animations?: Record<string, [string, number]>;  // [SVG string, duration in ms]
  }
>;

Color Theming

Icons support two color variables that can be used in your SVG markup:

--primary - Maps to themeDetails.iconPrimaryColor

--secondary - Maps to themeDetails.iconSecondaryColor

Use these CSS variables in your SVG to enable theming:

<svg viewBox="0 0 24 24">
  <circle fill="var(--primary)" cx="12" cy="12" r="10" />
  <path fill="var(--secondary)" d="M12 2L12 22" />
</svg>

Override colors using the colors prop with a StyleX theme:

import { themeDetails } from "@228-co/reef/themes";

const customColors = stylex.createTheme(themeDetails, {
  iconPrimaryColor: "#ff0000",
  iconSecondaryColor: "#00ff00",
});

<Icon icon="check" colors={customColors} />

Reduced Motion

The Icon component respects the user's reduced motion preference via the ReducedMotionContext from ReefProvider. When reduced motion is preferred, animations will not play.