Icon buttons

An icon button is a single action drawn as an icon, for toolbars, app bars and anywhere a word would not fit. It comes in the same four styles as a button, and in a toggle variant for a state that stays.

Types

Icon button

<script lang="ts">
	import { IconButton } from 'noph-ui'
	import { Icon } from 'noph-ui/icons'
</script>

<IconButton aria-label="Icon button"><Icon>check</Icon></IconButton>
<IconButton aria-label="Disabled icon button" disabled><Icon>check</Icon></IconButton>

Filled icon button

<script lang="ts">
	import { IconButton } from 'noph-ui'
	import { Icon } from 'noph-ui/icons'
</script>

<IconButton aria-label="Filled icon button" variant="filled"><Icon>check</Icon></IconButton>
<IconButton aria-label="Disabled filled icon button" variant="filled" disabled
	><Icon>check</Icon></IconButton
>

Tonal icon button

<script lang="ts">
	import { IconButton } from 'noph-ui'
	import { Icon } from 'noph-ui/icons'
</script>

<IconButton aria-label="Tonal icon button" variant="tonal"><Icon>check</Icon></IconButton>
<IconButton aria-label="Disabled tonal icon button" variant="tonal" disabled>
	<Icon>check</Icon>
</IconButton>

Outlined icon button

<script lang="ts">
	import { IconButton } from 'noph-ui'
	import { Icon } from 'noph-ui/icons'
</script>

<IconButton aria-label="Outlined icon button" variant="outlined"><Icon>check</Icon></IconButton>
<IconButton aria-label="Disabled outlined icon button" variant="outlined" disabled
	><Icon>check</Icon></IconButton
>

Size

<script lang="ts">
	import { IconButton } from 'noph-ui'
	import { Icon } from 'noph-ui/icons'
</script>

<IconButton variant="outlined" aria-label="Extra small" size="xs"><Icon>add</Icon></IconButton>
<IconButton variant="outlined" aria-label="Small" size="s"><Icon>add</Icon></IconButton>
<IconButton variant="outlined" aria-label="Medium" size="m"><Icon>add</Icon></IconButton>
<IconButton variant="outlined" aria-label="Large" size="l"><Icon>add</Icon></IconButton>
<IconButton variant="outlined" aria-label="Extra large" size="xl"><Icon>add</Icon></IconButton>

Shape

Icon buttons come in two shapes. The shape morphs while the button is pressed and stays square while a toggle button is selected.

<script lang="ts">
	import { IconButton } from 'noph-ui'
	import { Icon } from 'noph-ui/icons'
</script>

<IconButton variant="outlined" aria-label="Round" shape="round"><Icon>bookmark</Icon></IconButton>
<IconButton variant="outlined" aria-label="Square" shape="square"><Icon>bookmark</Icon></IconButton>

Width

The width can be adjusted independently of the size. The height stays the same.

<script lang="ts">
	import { IconButton } from 'noph-ui'
	import { Icon } from 'noph-ui/icons'
</script>

<IconButton variant="filled" aria-label="Narrow" width="narrow"><Icon>more_vert</Icon></IconButton>
<IconButton variant="filled" aria-label="Default" width="default"><Icon>more_vert</Icon></IconButton
>
<IconButton variant="filled" aria-label="Wide" width="wide"><Icon>more_vert</Icon></IconButton>

Toggle

<script lang="ts">
	import { IconButton } from 'noph-ui'
	import { Icon } from 'noph-ui/icons'
</script>

<div class="icon-list">
	<IconButton aria-label="Unselected icon button" toggle><Icon>settings</Icon></IconButton>
	<IconButton aria-label="Unselected filled icon button" variant="filled" toggle
		><Icon>settings</Icon></IconButton
	>
	<IconButton aria-label="Unselected tonal icon button" variant="tonal" toggle
		><Icon>settings</Icon></IconButton
	>
	<IconButton aria-label="Unselected outlined icon button" variant="outlined" toggle
		><Icon>settings</Icon></IconButton
	>
</div>
<div class="icon-list">
	<IconButton aria-label="Selected icon button" toggle selected><Icon>settings</Icon></IconButton>
	<IconButton aria-label="Selected filled icon button" variant="filled" toggle selected
		><Icon>settings</Icon></IconButton
	>
	<IconButton aria-label="Selected tonal icon button" variant="tonal" toggle selected
		><Icon>settings</Icon></IconButton
	>
	<IconButton aria-label="Selected outlined icon button" variant="outlined" toggle selected
		><Icon>settings</Icon></IconButton
	>
</div>

<style>
	.icon-list {
		display: flex;
		flex-wrap: wrap;
		gap: 1rem;
	}
</style>

Loading

<script lang="ts">
	import { IconButton } from 'noph-ui'
	import { Icon } from 'noph-ui/icons'
</script>

<IconButton loading loadingAriaLabel="Loading text"><Icon>check</Icon></IconButton>
<IconButton loading loadingAriaLabel="Loading filled" variant="filled">
	<Icon>check</Icon>
</IconButton>
<IconButton loading loadingAriaLabel="Loading tonal" variant="tonal">
	<Icon>check</Icon>
</IconButton>
<IconButton loading loadingAriaLabel="Loading outlined" variant="outlined">
	<Icon>check</Icon>
</IconButton>
For accessibility, the loadingAriaLabel attribute is recommended when using the loading state.

Tooltip

<script lang="ts">
	import { IconButton } from 'noph-ui'
	import { Icon } from 'noph-ui/icons'
</script>

<IconButton title="Icon button with tooltip" variant="filled"><Icon>check</Icon></IconButton>

Theming

Icon button tokens

TokenValue
--np-icon-button-icon-color--np-color-on-surface-variant
--np-icon-button-icon-size1.5rem
--np-icon-button-shape0.75rem to 1.75rem, per size

--np-icon-button-shape is the corner radius of shape="square". A round icon button stays fully rounded.

Icon button example

<script lang="ts">
	import { IconButton } from 'noph-ui'
	import { Icon } from 'noph-ui/icons'
</script>

<IconButton
	aria-label="Custom icon button"
	--np-icon-button-icon-color="var(--np-color-tertiary)"
	--np-icon-button-icon-size="32px"
>
	<Icon>close</Icon>
</IconButton>

Filled icon button tokens

TokenValue
--np-filled-icon-button-icon-color--np-color-on-primary
--np-filled-icon-button-container-color--np-color-primary
--np-icon-button-icon-size1.5rem

Filled icon button example

<script lang="ts">
	import { IconButton } from 'noph-ui'
	import { Icon } from 'noph-ui/icons'
</script>

<IconButton
	aria-label="Custom filled icon button"
	--np-filled-icon-button-container-color="var(--np-color-tertiary)"
	--np-filled-icon-button-icon-color="var(--np-color-on-tertiary)"
	--np-icon-button-icon-size="32px"
	variant="filled"
>
	<Icon>close</Icon>
</IconButton>

Filled toggle icon button tokens

A toggle filled icon button switches between an unselected and a selected container, each with its own tokens instead of sharing the plain filled ones above.

TokenValue
--np-filled-icon-button-unselected-icon-color--np-color-on-surface-variant
--np-filled-icon-button-unselected-container-color--np-color-surface-container
--np-filled-icon-button-selected-icon-color--np-color-on-primary
--np-filled-icon-button-selected-container-color--np-color-primary

Filled toggle icon button example

<script lang="ts">
	import { IconButton } from 'noph-ui'
	import { Icon } from 'noph-ui/icons'
</script>

<IconButton
	aria-label="Custom toggle icon button"
	toggle
	selected
	--np-filled-icon-button-selected-container-color="var(--np-color-tertiary-container)"
	--np-filled-icon-button-selected-icon-color="var(--np-color-on-tertiary-container)"
	variant="filled"
>
	<Icon>favorite</Icon>
</IconButton>

Tonal icon buttons tokens

TokenDefault value
--np-tonal-icon-button-icon-color--np-color-on-secondary-container
--np-tonal-icon-button-container-color--np-color-secondary-container
--np-icon-button-icon-size1.5rem

Tonal icon button example

<script lang="ts">
	import { IconButton } from 'noph-ui'
	import { Icon } from 'noph-ui/icons'
</script>

<IconButton
	aria-label="Custom tonal icon button"
	--np-tonal-icon-button-container-color="var(--np-color-tertiary-container)"
	--np-tonal-icon-button-icon-color="var(--np-color-on-tertiary)"
	--np-icon-button-icon-size="32px"
	variant="tonal"
>
	<Icon>close</Icon>
</IconButton>

Outlined icon button tokens

TokenDefault value
--np-outlined-icon-button-outline-color--np-color-outline-variant
--np-icon-button-icon-size1.5rem

Outlined icon button example

<script lang="ts">
	import { IconButton } from 'noph-ui'
	import { Icon } from 'noph-ui/icons'
</script>

<IconButton
	aria-label="Custom outlined icon button"
	--np-outlined-icon-button-outline-color="var(--np-color-tertiary)"
	--np-icon-button-icon-size="32px"
	variant="outlined"
>
	<Icon>close</Icon>
</IconButton>

Accessibility

An icon button renders a native <button>, or an <a> with href. Nothing in an icon carries a name, so title is not optional here: it becomes both the accessible name and the tooltip.

toggle reports the state with aria-pressed, so use it for a control that stays on, a bookmark or a mute button, and write a title that holds for both states. loading sets aria-busy and names the spinner with loadingAriaLabel.

API

Props

PropTypeDefaultDescription
variant'text' | 'filled' | 'outlined' | 'tonal''text'Defines the visual style of the button.
size'xs' | 's' | 'm' | 'l' | 'xl''s'Defines the size of the button.
shape'round' | 'square''round'Defines the shape of the button.
width'narrow' | 'wide' | 'default''default'Defines the width of the button.
togglebooleanfalseEnables toggle behavior for the button.
selectedbind:booleanfalseIndicates whether the button is selected.
selectedIconSnippetundefinedIcon to display when the button is selected.
disabledbooleanfalseDisables the button.
loadingbooleanfalseSets the button to a loading state.
loadingAriaLabelstring | undefinedundefinedProvides an accessibility label for the loading state.
titlestring | null | undefinedundefinedTooltip text
elementbind:HTMLElementA reference to the root DOM element of the component. This variable is bound using bind:this, allowing direct access to the underlying HTML element for manipulation or querying within the component's logic.
...attributesHTMLButtonAttributes & HTMLAnchorAttributesA single, unified set of <button> and <a> attributes. Setting href renders an <a>, otherwise a <button>. Event handlers such as onclick receive event.currentTarget typed as HTMLButtonElement | HTMLAnchorElement, so you no longer need to set href to get correctly typed events.