Buttons

Buttons let people take an action with one tap. Material 3 gives five styles, and the one you pick says how much weight the action carries on the screen: filled for the one action a screen is about, tonal and elevated below it, outlined and text for everything secondary.

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, the loadingAriaLabel attribute is recommended when using 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

<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>

<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-primary

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 come from size, so setting one overrides the sizing for whatever size the button is. --np-button-shape is the exception worth knowing: it sets the radius of the square shape only, so pair 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> as soon as you pass href, so the role, the keyboard and the focus ring come from the platform. Label it with its text content wherever you can.

A button showing only an icon needs title. It becomes the accessible name and the tooltip in one go. toggle reports the state through aria-pressed, loading sets aria-busy and names the spinner with loadingAriaLabel, and a disabled button is really disabled rather than 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 | undefinedundefinedSpecifies the tooltip text.
size'xs' | 's' | 'm' | 'l' | 'xl''s'Button size
shape'round' | 'square''round'Button shape
toggleboolean | undefinedfalseEnables toggle behavior, allowing the button to act as a toggleable (on/off) button.
selectedboolean | undefinedfalseIndicates whether the button is currently selected (used with toggle buttons).
...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.

Bindables

AttributeTypeDescription
elementHTMLElementA 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.