Usage
IconButton represents a frequent action with one unambiguous icon. Import it from @udixio/ui-react, @udixio/ui-angular or @udixio/ui-svelte. label and icon are required: the icon stays decorative while the stable label names the native control.
import { IconButton } from '@udixio/ui-react';
import { iAdd } from '@udixio/icons-rounded-400/add';
export default function IconButtonStatesReact() {
return (
<div className="flex flex-wrap items-center gap-3">
<IconButton label="Add item" icon={iAdd} />
<IconButton label="Disabled action" icon={iAdd} disabled />
</div>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IconButton } from '@udixio/ui-angular';
import { iAdd } from '@udixio/icons-rounded-400/add';
@Component({
selector: 'docs-icon-button-states-angular',
standalone: true,
imports: [IconButton],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="flex flex-wrap items-center gap-3">
<udx-icon-button label="Add item" [icon]="addIcon" />
<udx-icon-button label="Disabled action" [icon]="addIcon" disabled />
</div>
`,
})
export class IconButtonStatesAngular {
protected readonly addIcon = iAdd;
}<script lang="ts">
import { IconButton } from '@udixio/ui-svelte';
import { iAdd } from '@udixio/icons-rounded-400/add';
</script>
<div class="flex flex-wrap items-center gap-3">
<IconButton label="Add item" icon={iAdd} />
<IconButton label="Disabled action" icon={iAdd} disabled />
</div>Variants
Variants are standard, filled, tonal, and outlined.
import { IconButton } from '@udixio/ui-react';
import { iAdd } from '@udixio/icons-rounded-400/add';
export default function IconButtonVariantsReact() {
return (
<div className="flex flex-wrap items-center gap-3">
<IconButton label="Standard" icon={iAdd} variant="standard" />
<IconButton label="Filled" icon={iAdd} variant="filled" />
<IconButton label="Tonal" icon={iAdd} variant="tonal" />
<IconButton label="Outlined" icon={iAdd} variant="outlined" />
</div>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IconButton } from '@udixio/ui-angular';
import { iAdd } from '@udixio/icons-rounded-400/add';
@Component({
selector: 'docs-icon-button-variants-angular',
standalone: true,
imports: [IconButton],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="flex flex-wrap items-center gap-3">
<udx-icon-button label="Standard" [icon]="addIcon" variant="standard" />
<udx-icon-button label="Filled" [icon]="addIcon" variant="filled" />
<udx-icon-button label="Tonal" [icon]="addIcon" variant="tonal" />
<udx-icon-button label="Outlined" [icon]="addIcon" variant="outlined" />
</div>
`,
})
export class IconButtonVariantsAngular {
protected readonly addIcon = iAdd;
}<script lang="ts">
import { IconButton } from '@udixio/ui-svelte';
import { iAdd } from '@udixio/icons-rounded-400/add';
</script>
<div class="flex flex-wrap items-center gap-3">
<IconButton label="Standard" icon={iAdd} variant="standard" />
<IconButton label="Filled" icon={iAdd} variant="filled" />
<IconButton label="Tonal" icon={iAdd} variant="tonal" />
<IconButton label="Outlined" icon={iAdd} variant="outlined" />
</div>Sizes
Sizes range from xSmall to xLarge. Every size retains at least a 48 px touch target regardless of the visible icon size.
import { IconButton } from '@udixio/ui-react';
import { iAdd } from '@udixio/icons-rounded-400/add';
export default function IconButtonSizesReact() {
return (
<div className="flex flex-wrap items-center gap-3">
<IconButton variant="filled" label="Extra small" icon={iAdd} size="xSmall" />
<IconButton variant="filled" label="Small" icon={iAdd} size="small" />
<IconButton variant="filled" label="Medium" icon={iAdd} size="medium" />
<IconButton variant="filled" label="Large" icon={iAdd} size="large" />
<IconButton variant="filled" label="Extra large" icon={iAdd} size="xLarge" />
</div>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IconButton } from '@udixio/ui-angular';
import { iAdd } from '@udixio/icons-rounded-400/add';
@Component({
selector: 'docs-icon-button-sizes-angular',
standalone: true,
imports: [IconButton],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="flex flex-wrap items-center gap-3">
<udx-icon-button
variant="filled"
label="Extra small"
[icon]="addIcon"
size="xSmall"
/>
<udx-icon-button variant="filled" label="Small" [icon]="addIcon" size="small" />
<udx-icon-button
variant="filled"
label="Medium"
[icon]="addIcon"
size="medium"
/>
<udx-icon-button variant="filled" label="Large" [icon]="addIcon" size="large" />
<udx-icon-button
variant="filled"
label="Extra large"
[icon]="addIcon"
size="xLarge"
/>
</div>
`,
})
export class IconButtonSizesAngular {
protected readonly addIcon = iAdd;
}<script lang="ts">
import { IconButton } from '@udixio/ui-svelte';
import { iAdd } from '@udixio/icons-rounded-400/add';
</script>
<div class="flex flex-wrap items-center gap-3">
<IconButton variant="filled" label="Extra small" icon={iAdd} size="xSmall" />
<IconButton variant="filled" label="Small" icon={iAdd} size="small" />
<IconButton variant="filled" label="Medium" icon={iAdd} size="medium" />
<IconButton variant="filled" label="Large" icon={iAdd} size="large" />
<IconButton variant="filled" label="Extra large" icon={iAdd} size="xLarge" />
</div>Shape and width
shape selects the rounded or squared resting shape; width is narrow, default, or wide. The shared Motion controller morphs the shape on accepted presses by default. Set shapeFeedback="none" to keep it static.
import { IconButton } from '@udixio/ui-react';
import { iAdd } from '@udixio/icons-rounded-400/add';
export default function IconButtonShapesReact() {
return (
<div className="flex flex-col gap-4">
<div className="flex flex-wrap items-center gap-3">
<IconButton variant="filled" label="Narrow" icon={iAdd} shape="rounded" width="narrow" />
<IconButton variant="filled" label="Default" icon={iAdd} shape="rounded" width="default" />
<IconButton variant="filled" label="Wide" icon={iAdd} shape="rounded" width="wide" />
</div>
<div className="flex flex-wrap items-center gap-3">
<IconButton variant="filled" label="Narrow" icon={iAdd} shape="squared" width="narrow" />
<IconButton variant="filled" label="Default" icon={iAdd} shape="squared" width="default" />
<IconButton variant="filled" label="Wide" icon={iAdd} shape="squared" width="wide" />
</div>
</div>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IconButton } from '@udixio/ui-angular';
import { iAdd } from '@udixio/icons-rounded-400/add';
@Component({
selector: 'docs-icon-button-shapes-angular',
standalone: true,
imports: [IconButton],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="flex flex-col gap-4">
<div class="flex flex-wrap items-center gap-3">
<udx-icon-button
variant="filled"
label="Narrow"
[icon]="addIcon"
shape="rounded"
width="narrow"
/>
<udx-icon-button
variant="filled"
label="Default"
[icon]="addIcon"
shape="rounded"
width="default"
/>
<udx-icon-button
variant="filled"
label="Wide"
[icon]="addIcon"
shape="rounded"
width="wide"
/>
</div>
<div class="flex flex-wrap items-center gap-3">
<udx-icon-button
variant="filled"
label="Narrow"
[icon]="addIcon"
shape="squared"
width="narrow"
/>
<udx-icon-button
variant="filled"
label="Default"
[icon]="addIcon"
shape="squared"
width="default"
/>
<udx-icon-button
variant="filled"
label="Wide"
[icon]="addIcon"
shape="squared"
width="wide"
/>
</div>
</div>
`,
})
export class IconButtonShapesAngular {
protected readonly addIcon = iAdd;
}<script lang="ts">
import { IconButton } from '@udixio/ui-svelte';
import { iAdd } from '@udixio/icons-rounded-400/add';
</script>
<div class="flex flex-col gap-4">
<div class="flex flex-wrap items-center gap-3">
<IconButton variant="filled" label="Narrow" icon={iAdd} shape="rounded" width="narrow" />
<IconButton variant="filled" label="Default" icon={iAdd} shape="rounded" width="default" />
<IconButton variant="filled" label="Wide" icon={iAdd} shape="rounded" width="wide" />
</div>
<div class="flex flex-wrap items-center gap-3">
<IconButton variant="filled" label="Narrow" icon={iAdd} shape="squared" width="narrow" />
<IconButton variant="filled" label="Default" icon={iAdd} shape="squared" width="default" />
<IconButton variant="filled" label="Wide" icon={iAdd} shape="squared" width="wide" />
</div>
</div>Toggle buttons
Set toggleable for binary actions such as Favorite. pressed is controlled; defaultPressed initializes uncontrolled state. React emits onPressedChange; Angular emits pressedChange; Svelte keeps onPressedChange and also supports bind:pressed. pressedIcon optionally replaces the resting icon while pressed.
Navigation links ignore toggle state. Use aria-current for the current destination instead.
import { useState } from 'react';
import { IconButton } from '@udixio/ui-react';
import { iStar } from '@udixio/icons-rounded-400/star';
import { iStarFilled } from '@udixio/icons-rounded-400/filled/star';
export default function IconButtonToggleReact() {
const [pressed, setPressed] = useState(false);
return (
<div className="flex flex-wrap items-center gap-3">
<IconButton
label="Favorite (uncontrolled)"
icon={iStar}
pressedIcon={iStarFilled}
variant="tonal"
toggleable
defaultPressed
/>
<IconButton
label="Favorite (controlled)"
icon={iStar}
pressedIcon={iStarFilled}
variant="tonal"
toggleable
pressed={pressed}
onPressedChange={setPressed}
/>
</div>
);
}import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { IconButton } from '@udixio/ui-angular';
import { iStar } from '@udixio/icons-rounded-400/star';
import { iStarFilled } from '@udixio/icons-rounded-400/filled/star';
@Component({
selector: 'docs-icon-button-toggle-angular',
standalone: true,
imports: [IconButton],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="flex flex-wrap items-center gap-3">
<udx-icon-button
label="Favorite (uncontrolled)"
[icon]="starIcon"
[pressedIcon]="starFilledIcon"
variant="tonal"
toggleable
defaultPressed
/>
<udx-icon-button
label="Favorite (controlled)"
[icon]="starIcon"
[pressedIcon]="starFilledIcon"
variant="tonal"
toggleable
[pressed]="pressed()"
(pressedChange)="pressed.set($event)"
/>
</div>
`,
})
export class IconButtonToggleAngular {
protected readonly pressed = signal(false);
protected readonly starIcon = iStar;
protected readonly starFilledIcon = iStarFilled;
}<script lang="ts">
import { IconButton } from '@udixio/ui-svelte';
import { iStar } from '@udixio/icons-rounded-400/star';
import { iStarFilled } from '@udixio/icons-rounded-400/filled/star';
let pressed = $state(false);
</script>
<div class="flex flex-wrap items-center gap-3">
<IconButton
label="Favorite (uncontrolled)"
icon={iStar}
pressedIcon={iStarFilled}
variant="tonal"
toggleable
defaultPressed
/>
<IconButton
label="Favorite (bound)"
icon={iStar}
pressedIcon={iStarFilled}
variant="tonal"
toggleable
bind:pressed
/>
</div>In Svelte, use a normal bind:pressed for the common case. To reject a transition, use a function binding and only assign in its setter when the owner accepts the new value.
Accessibility
Action mode renders a native button with type="button" by default. href switches to a native link. Disabled links lose their destination, receive aria-disabled, and leave the tab order. Focus is visible and icons are decorative.
The accessible label is also shown in a tooltip on hover and keyboard focus. Set tooltip to a string to show different supporting text, or set it to false when the surrounding interface already makes the action explicit.
Migrating to 3.0
| Before | 3.0 |
|---|---|
iconSelected | pressedIcon |
activated | pressed or defaultPressed |
onToggle | toggleable plus onPressedChange / pressedChange |
allowShapeTransformation={false} | shapeFeedback="none" |
text children as the label | required label and icon |
implicit tooltip from title/label | automatic label; customize or hide with tooltip |