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
| Token | Value |
|---|---|
--np-icon-button-icon-color | --np-color-on-surface-variant |
--np-icon-button-icon-size | 1.5rem |
--np-icon-button-shape | 0.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
| Token | Value |
|---|---|
--np-filled-icon-button-icon-color | --np-color-on-primary |
--np-filled-icon-button-container-color | --np-color-primary |
--np-icon-button-icon-size | 1.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.
| Token | Value |
|---|---|
--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
| Token | Default 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-size | 1.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
| Token | Default value |
|---|---|
--np-outlined-icon-button-outline-color | --np-color-outline-variant |
--np-icon-button-icon-size | 1.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
| Prop | Type | Default | Description |
|---|---|---|---|
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. |
toggle | boolean | false | Enables toggle behavior for the button. |
selected | bind:boolean | false | Indicates whether the button is selected. |
selectedIcon | Snippet | undefined | Icon to display when the button is selected. |
disabled | boolean | false | Disables the button. |
loading | boolean | false | Sets the button to a loading state. |
loadingAriaLabel | string | undefined | undefined | Provides an accessibility label for the loading state. |
title | string | null | undefined | undefined | Tooltip text |
element | bind:HTMLElement | A 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. | |
...attributes | HTMLButtonAttributes & HTMLAnchorAttributes | A 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. |