Icon

A Spark icon inside a themed frame, for emphasis and status.

Usage

import { Icon } from '@epilot/spark-ui/icon'
import { SolarPower } from '@epilot/spark-icons'
<Icon>
  <SolarPower />
</Icon>

An <Icon> is a glyph in a styled box. It is neutral gray in every variant by default, so it stays quiet unless you ask for colour. Pick the fill weight with variant, set the shape with the radius knob, and add colour with color (see Colors).

Reach for a bare Spark icon (from @epilot/spark-icons) when you want the glyph with no frame, and for a Button (with an icon size) when the icon is clickable. Browse every Spark icon on Icons. Icon is for a non-interactive, framed icon: a feature bullet, a list leading icon, or a status tile.

Examples

Sizes

The small, medium (default), large, and xl sizes render a 24, 32, 40, or 48px frame. Both the frame and the glyph are spacing-derived, so they grow and shrink with the scaling and spacing knobs.

Styles

variant picks the fill weight: soft (default), surface, solid, ghost, or outline. All five paint with the palette color selects (neutral by default — see Colors). surface and outline add a 1px border.

High contrast

data-high-contrast (on the icon or any ancestor) darkens the glyph (step a11 to a12 on whichever palette color selected) and strengthens the surface / outline border for stronger legibility. It does not change the palette, only its depth. solid steps up the same way but to a dedicated fill/ink pair (step 12 fill, step 1 ink) rather than darkening in place — it's already at its base variant's highest depth, so high contrast swaps to the opposite end of the scale instead.

Colors

color picks the palette — accent, neutral (default), success, warning, or danger — the same axis as Button, Pill, and Avatar. It re-points every variant's fill, ink, and border together, so a solid danger icon and a soft danger icon both land on the same red scale without hand-picking tokens. A className fill/ink override still wins over either, through tailwind-merge.

Shape

The frame corners follow the radius knob. At radius="full" it becomes a circle; at smaller radii it is a rounded square. Radius must be set through <Theme> (or a .spark-theme scope), not a bare data-radius, so the corner calc()s re-resolve.

Custom glyph

Pass a Spark icon or an inline SVG as children. The glyph inherits the frame's ink via currentColor.

API Reference

PropTypeDefaultDescription
childrenReact.ReactNodeThe glyph (a Spark icon or inline SVG). Inherits the frame's ink via currentColor.
variant'soft' | 'surface' | 'solid' | 'ghost' | 'outline''soft'Fill weight. surface and outline add a 1px border.
colorSparkAccentColor'neutral'Palette axis, matching Button/Pill/Avatar: accent | neutral | success | warning | danger.
size'small' | 'medium' | 'large' | 'xl''medium'Frame 24 / 32 / 40 / 48px with a 16 / 20 / 24 / 28px glyph. Both track the spacing and scaling knobs.
classNamestringMerges with the base styles; a colour, size, or radius utility wins via tailwind-merge.

The component forwards all span HTML attributes via React.HTMLAttributes<HTMLSpanElement>. It tracks the neutral/accent, radius, spacing, scaling, and high-contrast knobs. color re-points the accent scale the same way Button's does (data-accent-color), so it costs nothing extra to theme.

Accessibility

Icon is decorative by default: the glyph is aria-hidden, and with no label the frame has no role, so assistive technology skips it. Use this when the icon merely repeats or decorates adjacent text.

When the icon is the only carrier of meaning, pass aria-label. The frame then becomes role="img" with that accessible name. A custom SVG glyph passed as children should carry its own aria-hidden so it does not announce twice.

Colour is not meaning: do not rely on color alone to signal state (success, error). Pair the icon with text or an aria-label.

On this page