Buttons

Buttons let people take an action with one tap. There are five styles, and the style shows how important the action is: filled for the main action of a screen, tonal and elevated one step below, outlined and text for secondary actions.

Types

Elevated button

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

<Button variant="elevated">Elevated</Button>
<Button variant="elevated" disabled>Disabled</Button>

Filled button

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

<Button variant="filled">Filled</Button>
<Button variant="filled" disabled>Disabled</Button>

Tonal button

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

<Button variant="tonal">Tonal</Button>
<Button variant="tonal" disabled>Disabled</Button>

Outlined button

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

<Button variant="outlined">Outlined</Button>
<Button variant="outlined" disabled>Disabled</Button>

Text button

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

<Button variant="text">Text</Button>
<Button variant="text" disabled>Disabled</Button>

Icon

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

<Button variant="tonal">
	{#snippet start()}
		<Icon>send</Icon>
	{/snippet}
	Send
</Button>
<Button variant="text">
	{#snippet end()}
		<Icon>open_in_new</Icon>
	{/snippet}
	Open
</Button>

Loading

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

<Button loading loadingAriaLabel="Loading elevated" variant="elevated">Elevated</Button>
<Button loading loadingAriaLabel="Loading outlined" variant="outlined">Outlined</Button>
<Button loading loadingAriaLabel="Loading text" variant="text">Text</Button>
For accessibility, set loadingAriaLabel when you use the loading state.

Size

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

<Button size="xs">{#snippet start()}<Icon>add</Icon>{/snippet}Extra small</Button>
<Button size="s">{#snippet start()}<Icon>add</Icon>{/snippet}Small</Button>
<Button size="m">{#snippet start()}<Icon>add</Icon>{/snippet}Medium</Button>
<Button size="l">{#snippet start()}<Icon>add</Icon>{/snippet}Large</Button>
<Button size="xl">{#snippet start()}<Icon>add</Icon>{/snippet}Extra large</Button>

Toggle

A toggle button changes its shape when selected: a round one turns square, and a square one turns round.

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

<div class="button-list">
	<Button toggle variant="elevated">
		{#snippet start()}
			<Icon>send</Icon>
		{/snippet}
		Elevated
	</Button>
	<Button toggle variant="filled">Filled</Button>
	<Button toggle variant="tonal">Tonal</Button>
	<Button toggle variant="outlined">Outlined</Button>
</div>
<div class="button-list">
	<Button toggle selected variant="elevated">Elevated</Button>
	<Button toggle selected variant="filled">Filled</Button>
	<Button toggle selected variant="tonal">Tonal</Button>
	<Button toggle selected variant="outlined">Outlined</Button>
</div>
<!-- A square toggle turns round when selected. -->
<div class="button-list">
	<Button toggle shape="square" variant="filled">Filled</Button>
	<Button toggle shape="square" variant="tonal">Tonal</Button>
	<Button toggle shape="square" variant="outlined">Outlined</Button>
</div>
<div class="button-list">
	<Button toggle selected shape="square" variant="filled">Filled</Button>
	<Button toggle selected shape="square" variant="tonal">Tonal</Button>
	<Button toggle selected shape="square" variant="outlined">Outlined</Button>
</div>

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

Theming

Elevated button tokens

TokenDefault value
--np-elevated-button-container-color--np-color-surface-container-low
--np-elevated-button-label-text-color--np-color-primary

Elevated button example

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

<Button variant="elevated" --np-elevated-button-label-text-color="var(--np-color-tertiary)">
	Custom button
</Button>

Filled button tokens

TokenDefault value
--np-filled-button-container-color--np-color-primary
--np-filled-button-label-text-color--np-color-on-primary

Filled button example

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

<Button
	variant="filled"
	--np-filled-button-label-text-color="var(--np-color-on-tertiary)"
	--np-filled-button-container-color="var(--np-color-tertiary)"
>
	Custom button
</Button>

Tonal button tokens

TokenDefault value
--np-tonal-button-container-color--np-color-secondary-container
--np-tonal-button-label-text-color--np-color-on-secondary-container

Tonal button example

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

<Button
	variant="tonal"
	--np-tonal-button-label-text-color="var(--np-color-on-tertiary-fixed)"
	--np-tonal-button-container-color="var(--np-color-tertiary-fixed)"
>
	Custom button
</Button>

Outlined button tokens

TokenDefault value
--np-outlined-button-outline-color--np-color-outline-variant
--np-outlined-button-label-text-color--np-color-on-surface-variant

Outlined button example

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

<Button variant="outlined" --np-outlined-button-label-text-color="var(--np-color-tertiary)">
	Custom button
</Button>

Text button tokens

TokenDefault value
--np-text-button-label-text-color--np-color-primary

Shared tokens

These apply to every variant. Their defaults depend on size, so setting one overrides the value at every size. --np-button-shape sets the radius of the square shape only, so use it with shape="square". Round buttons stay pills, with a radius that follows their height.

TokenDefault value
--np-button-shapeper size, 0.75rem at s
--np-button-paddingper size, 1rem at s
--np-button-gapper size, 0.5rem at s
--np-button-icon-sizeper size, 1.25rem at s
--np-button-icon-colorinherit, so the icon follows the label colour
--np-outlined-button-container-colortransparent

Text button example

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

<Button variant="text" --np-text-button-label-text-color="var(--np-color-tertiary)">
	Custom button
</Button>

Accessibility

A button renders a native <button>, or an <a> when you pass href, so the role, the keyboard and the focus ring come from the browser. Label it with its text content wherever you can.

A button with only an icon needs title. It becomes both the accessible name and the tooltip, and is read once. On a button with a visible label, the label stays the name and title only describes it. Extra small and small buttons keep a 48px tall touch target. toggle reports the state through aria-pressed. loading sets aria-busy and names the spinner with loadingAriaLabel. A disabled button is truly disabled, not only dimmed.

API

Attributes

AttributeTypeDefaultDescription
variant'text' | 'filled' | 'outlined' | 'elevated' | 'tonal''outlined'Visual appearance
startSnippet | undefinedundefinedIcon at the start of the button
endSnippet | undefinedundefinedIcon at the end of the button
disabledbooleanfalseDisables the button.
loadingbooleanfalseSets the button to a loading state.
loadingAriaLabelstring | undefinedundefinedProvides an accessibility label for the loading state.
titlestring | null | undefinedundefinedTooltip text. Without a visible label it is also the accessible name.
size'xs' | 's' | 'm' | 'l' | 'xl''s'Button size
shape'round' | 'square''round'Button shape
toggleboolean | undefinedfalseMakes the button an on/off toggle.
selectedboolean | undefinedfalseWhether the button is selected. Used with toggle.
...attributesHTMLButtonAttributes & HTMLAnchorAttributesOne 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.

Bindables

AttributeTypeDescription
elementHTMLElementThe component's root DOM element, bound with bind:this.