role presentation
Icon draft v0.1.0
A glyph of the system's icon set, decorative or named.
An icon draws one glyph of the icon set (Material Symbols, the Iconography foundation) at a size and in a color of the system. Next to text it is decoration and says nothing to assistive technology; alone, it must be named by what it means, and is then exposed as an image. Icons inside the other components (buttons, alerts, selects) are those components' parts, styled by their tokens; this component is for icons placed by a product in its own content.
Web implementation
Root .ds-icon on a <span>. Properties map to attributes: size → data-sizecolor → data-colorlabel → aria-label
packages/components/src/components/icon/icon.css
/*
* Icon — vanilla CSS reference implementation.
* Spec: packages/components/specs/components/icon.spec.json
* Tokens: packages/tokens/dist/css/components/icon.css (generated from packages/tokens/src/components/icon.tokens.json)
*
* Rules:
* - Only --icon-* custom properties may appear here. No raw values, no semantic tokens.
* - A glyph of the icon font. Size and color are data attributes; the default color, current,
* inherits the surrounding text color (currentColor: a token cannot say inherit).
*/
.ds-icon {
--_size: var(--icon-container-size-medium);
--_color: currentColor;
display: inline-block;
flex: none;
inline-size: var(--_size);
block-size: var(--_size);
overflow: hidden;
color: var(--_color);
font-family: var(--icon-container-font-family);
font-size: var(--_size);
font-weight: var(--icon-container-font-weight);
font-style: normal;
font-variation-settings:
"FILL" var(--icon-container-fill),
"GRAD" var(--icon-container-grade),
"opsz" var(--icon-container-optical-size);
font-feature-settings: "liga";
line-height: var(--_size);
letter-spacing: normal;
text-transform: none;
white-space: nowrap;
direction: ltr;
vertical-align: middle;
-webkit-font-smoothing: antialiased;
}
.ds-icon[data-size="small"] { --_size: var(--icon-container-size-small); }
.ds-icon[data-size="large"] { --_size: var(--icon-container-size-large); }
.ds-icon[data-color="neutral"] { --_color: var(--icon-container-color-neutral); }
.ds-icon[data-color="brand"] { --_color: var(--icon-container-color-brand); }
.ds-icon[data-color="success"] { --_color: var(--icon-container-color-success); }
.ds-icon[data-color="warning"] { --_color: var(--icon-container-color-warning); }
.ds-icon[data-color="error"] { --_color: var(--icon-container-color-error); }
.ds-icon[data-color="info"] { --_color: var(--icon-container-color-info); }
packages/components/src/components/icon/icon.template.mjs
/**
* Icon — HTML template for the web implementation.
* Pure function of the spec properties (packages/components/specs/components/icon.spec.json) -> HTML string.
* A glyph of the icon font written as its ligature name. Without a label it is decorative and
* hidden; with one it is an image named by the label.
*/
import { escapeAttr, renderIcon, ICONS } from '../../lib/template-utils.mjs';
export const meta = { id: 'icon', selector: '.ds-icon', icons: ICONS };
export function render(props = {}) {
const { name = 'add', label = null, size = 'medium', color = 'current', state = null } = props;
const attrs = ['class="ds-icon"', `data-size="${escapeAttr(size)}"`, `data-color="${escapeAttr(color)}"`];
if (label) attrs.push('role="img"', `aria-label="${escapeAttr(label)}"`);
else attrs.push('aria-hidden="true"');
if (state && state !== 'default') attrs.push(`data-state="${escapeAttr(state)}"`);
return `<span ${attrs.join(' ')}>${renderIcon(name || 'add')}</span>`;
}
No other platform implementation recorded yet. Platform token outputs live under Platforms.