Icon
Inline-block icon rendered via CSS mask-image. Color follows
currentColor, default size is 16×16, and the only required prop is
shape. The set of valid shapes is the union of Anta’s built-ins plus
any custom icons you generate yourself.
shape="loader" is the exception: it is Anta’s animated loading alias for
string-only icon props. Use Loader when you need a progress value, speed, or
accessible loading status.
In practice you’ll rarely reach for
<Icon>directly. Most Anta components that need an icon expose aniconprop that’s typed againstIconShape— autocomplete and type-checking work the same way without the wrapping element. Use<Icon>when you need a standalone icon outside of any other component.
Built-in shapes
Component props
| Prop | Type | Default | Description |
|---|---|---|---|
| shape | IconShape | — | Which icon to render. The set of valid shapes comes from Anta's
built-in icons plus any consumer-generated shapes (via the
IconShapes interface module augmentation). |
| size? | number | 16 | Width and height in pixels. |
| label? | string | — | Accessible name for the icon. When set, the wrapper exposes
role="img" and aria-label={label} so screen readers announce
the icon. When omitted (the default), the icon is treated as
decorative — aria-hidden="true" is applied so it doesn't add
noise alongside neighbouring text. |
Inherited props (children, className, id, slot, style, tabIndex, title)
| Prop | Type | Default | Description |
|---|---|---|---|
| children? | ReactNode | — | Child elements. When provided, replaces the component's default label/content. |
| className? | string | — | CSS class on the component's root element (merged with the component's own
classes). Use it directly for layout and positioning — grid/flex placement,
margins, alignment — rather than wrapping the component in a <div>/<span>. |
| id? | string | — | HTML id attribute. |
| slot? | string | — | Assigns the element to a named <slot> of a parent web component (e.g.
slot="header" inside a <Card>, slot="footer" inside a <Dialog>). |
| style? | CSSProperties | — | Inline styles on the component's root element. Set layout/positioning here
(or via className) directly on the component instead of adding a wrapper. |
| tabIndex? | number | — | Tab order. Set to -1 to skip the element when tabbing. |
| title? | string | — | HTML title attribute — native browser tooltip on hover. |
Plus every standard DOM event handler (onClick,
onFocus, onKeyDown, …) and any
data-* or aria-* attribute — forwarded as-is to
the underlying <a-*> element.
Web Component
Use the web component directly when you are not using React or Preact and a native control does not fit.
Set the accessible name on the raw element. Use --icon-size for a portable custom
size.
<a-icon shape="warning-triangle" role="img" aria-label="Warning" style="--icon-size: 24px"></a-icon>Sizing and color
Pass size (a number, in pixels) to control width and height
together. Default is 16. Color always follows currentColor.
<Icon shape="chevron-down" /> {/* 16×16, current color */}<Icon shape="check" size={24} /> {/* 24×24 */}<Text tone="critical"><Icon shape="warning-triangle" /></Text> {/* tinted */}Internally, size is applied as the --icon-size CSS custom property
on the rendered <a-icon>. The base CSS rule reads it as
width: var(--icon-size, 16px); height: var(--icon-size, 16px). That
means consumer CSS (or a parent’s variable cascade) can drive icon
size too — useful for sizing whole regions of UI at once:
.toolbar { --icon-size: 18px; }The
<Icon size>wrapper sets--icon-sizeinline, so it works everywhere. Hand-authoring the raw element’ssizeattribute (<a-icon size="18">) instead relies on typedattr()(Chrome 133+); on browsers without it (iOS Safari, Firefox) the attribute is ignored and the icon falls back to the 16px default. Prefer<Icon size>for exact custom sizes.
The blank spacer
shape="blank" renders nothing but still occupies a full icon box at the
current size. Use it to reserve a leading-icon column so labels line up when
only some rows carry an icon — a menu or list where a few items have a leading
glyph and the rest shouldn’t shift.
<Icon shape="blank" /> {/* invisible 16×16 spacer */}<MenuItem icon="blank" label="No icon, but aligned" />Note this differs from omitting the icon: leaving shape (or MenuItem’s
icon) unset renders no element, while blank renders an invisible sized
box. A bare <Icon> with no shape is not a spacer — with no mask it paints a
solid square.
Adding your own icons
Anta ships a generator script at dist/generate-icons.mjs. Drop your
SVGs in a folder, point the script at it, and it emits a CSS file plus
a TypeScript declaration that augments Anta’s IconShapes interface —
your shapes become valid <Icon shape="…" /> values automatically,
with autocomplete.
node ./node_modules/@antadesign/anta/dist/generate-icons.mjs \ --input ./svgs \ --output ./src/icons \ --name my-icons--input and --output are arbitrary paths in your project — pick
whatever fits your layout. The example above writes
./src/icons/my-icons.css and ./src/icons/my-icons.d.ts. Import
the CSS once at runtime; the .d.ts only needs to be in your
TypeScript include path (the same tsconfig.json include that
already covers your other source files), nothing else.
import './icons/my-icons.css' // runtime: registers shape rules on <a-icon>You can now use <Icon shape="my-shape" /> with full type safety.
SVG conventions
The generator strips width= and height= from the root <svg> so
size is fully under the host element’s CSS. For best results:
- Use
viewBox="0 0 16 16"(or any square viewBox). - Use
stroke="currentColor"(orfill="currentColor") — the icon is recolored via CSSbackground-color: currentColormasked through the SVG’s alpha. Black/colored fills work too, but only the alpha matters; the shape is always rendered in the current text color. - Single-color icons only. Multi-color SVGs collapse to one color
because the entire shape is masked through
currentColor.
Conflicting shape names
If a generated shape has the same name as one of Anta’s built-ins
(e.g. chevron-down), the generator prints a warning. At runtime, the
CSS file imported last wins — so importing your generated CSS
after @antadesign/anta/elements overrides the matching built-ins.
TypeScript silently merges the duplicate keys; both names remain valid
at the type level.
Programmatic use
import { generate } from '@antadesign/anta/generate-icons.mjs'
await generate({ input: './svgs', output: './src/icons', name: 'my-icons',})Useful for wiring icon generation into a build script.