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.
Icons are rendered by passing the icon name to the icon prop. The icon must be registered in the IconProvider.
<Icon icon="check" />
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>
);
}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} />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>
);
}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"} />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>
);
}| Name | Type | Default | Description |
|---|---|---|---|
icon | string | (required) | The name of the icon to render. Must match a key in the IconIndex provided to IconProvider. |
colors | stylex.Theme<...> | undefined | StyleX theme override for icon colors (iconPrimaryColor and iconSecondaryColor). |
style | StyleXStyles | undefined | Additional StyleX styles to apply to the icon container. |
ref | IconRef | ((ref: IconRef) => void) | undefined | Ref to access animation methods: playAnimation(name) and queueAnimation(name). |
| Name | Type | Default | Description |
|---|---|---|---|
children | JSXElement | - | Child components that will have access to the icon index. |
icons | IconIndex | - | An object mapping icon names to their SVG content and optional animations. |
The ref object provides methods to control icon animations:
type IconRef = {
playAnimation: (name: string) => Promise<void>;
queueAnimation: (name: string) => void;
};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]
}
>;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} />The Icon component respects the user's reduced motion preference via the ReducedMotionContext from ReefProvider. When reduced motion is preferred, animations will not play.