Components

DhIconButton

Icon-only button rendered as a tight circle (1:1 hit area) by default; shape="square" gives a rounded square. A DhButton with a single icon and no label — reuses its role/surface model (variant primary / secondary / error / ghost, conditional outlined default, state layer, disabled, loading) and scales down slightly on press. ariaLabel is required. DhIconLinkButton is the anchor-rendered counterpart.

An icon-only button that renders as a tight perfect circle — the shape DhButton's pill shape="round" can't give. Reuses DhButton's role/surface model, so variant, outlined, the state layer, disabled, and loading all behave the same.

Variants

`variant` picks the role colour. Surface defaults to filled — except `secondary`, which outlines by default, mirroring DhButton.

<DhIconButton icon="pencil" ariaLabel="Edit" />                       <!-- secondary, outlined by default -->
<DhIconButton icon="plus" ariaLabel="Add" variant="primary" />
<DhIconButton icon="trash-2" ariaLabel="Delete" variant="error" />
<DhIconButton icon="ellipsis" ariaLabel="More" variant="ghost" />

Filled, outlined, ghost

`outlined` toggles the ringed surface. Ghost is transparent and ignores it.

<DhIconButton icon="plus" ariaLabel="Add" variant="primary" />              <!-- filled -->
<DhIconButton icon="plus" ariaLabel="Add" variant="primary" outlined />    <!-- ringed -->

<!-- Secondary's outlined default is true; pass outlined={false} to fill it. -->
<DhIconButton icon="pencil" ariaLabel="Edit" />
<DhIconButton icon="pencil" ariaLabel="Edit" outlined={false} />

Sizes

The hit area scales while the circle stays 1:1: 2.5 / 3 / 3.5 rem.

<DhIconButton icon="search" ariaLabel="Search" variant="primary" size="sm" />
<DhIconButton icon="search" ariaLabel="Search" variant="primary" size="md" />
<DhIconButton icon="search" ariaLabel="Search" variant="primary" size="lg" />

Disabled and loading

Disabled inherits DhButton's neutral fade. Loading swaps the glyph for a centred spinner and sets aria-busy. Click the third button.

<DhIconButton icon="check" ariaLabel="Confirm" variant="primary" />
<DhIconButton icon="check" ariaLabel="Confirm" variant="primary" disabled />
<DhIconButton icon="check" ariaLabel="Saving" variant="primary" loading={isLoading} onclick={simulateLoad} />

Press feedback

On :active the button scales down slightly (to 0.97) — a subtle press response; the circle's radius stays constant. Honours prefers-reduced-motion. Press and hold to feel it.

<!-- On press the button scales down slightly (to 0.97); the circle's
     radius stays constant. Honours prefers-reduced-motion.
     Press and hold to feel it. -->
<DhIconButton icon="heart" ariaLabel="Like" variant="primary" size="lg" />

DhIconLinkButton

The anchor-rendered counterpart. Same visuals; navigates instead of firing a handler, so it joins browser history and right-click works.

<DhIconLinkButton href="/settings" icon="settings" ariaLabel="Settings" variant="primary" />
<DhIconLinkButton href="https://figma.com" external icon="external-link" ariaLabel="Open in Figma" />