Button
Pill controls for the main action, a quieter alternative, and inline text.
Not saved yet
More examples
Link button
Pass href to navigate. Quiet never takes a link.
Source
<script lang="ts">
import 'portal-bits/styles.css';
import 'portal-bits/tokens.css';
import type { Snippet } from 'svelte';
let { children }: { children: Snippet } = $props();
</script>
{@render children()}
<script lang="ts">
import ButtonExample from './ButtonExample.svelte';
</script>
<ButtonExample variant={"primary"} size={40} disabled={false} icon={false} />
<script lang="ts">
import { Button } from 'portal-bits';
let {
variant = 'primary',
size = 40,
disabled = false,
icon = false,
}: {
variant?: 'primary' | 'secondary' | 'green' | 'quiet';
size?: 32 | 40 | 48;
disabled?: boolean;
icon?: boolean;
} = $props();
let saved = $state(false);
</script>
{#snippet label()}
{#if icon}
<svg
width="15"
height="15"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg
>
{/if}
{saved ? 'Changes saved' : 'Save changes'}
{/snippet}
<div class="stack">
{#if variant === 'quiet'}
<Button variant="quiet" {disabled} onclick={() => (saved = !saved)}>
{@render label()}
</Button>
{:else}
<Button {variant} {size} {disabled} onclick={() => (saved = !saved)}>
{@render label()}
</Button>
{/if}
<p role="status">{saved ? 'Saved' : 'Not saved yet'}</p>
</div>
<style>
.stack {
display: grid;
justify-items: center;
gap: 12px;
}
p {
margin: 0;
color: var(--portal-muted);
font-size: 13px;
line-height: 20px;
}
</style>
API reference
These tables list the props and snippets that Button declares. Attributes passed through to an element or primitive are listed under Forwarded attributes, not here.
Props
| Name | Type | Default | Required | Binding | Description |
|---|---|---|---|---|---|
variant | 'primary' | 'secondary' | 'green' | 'quiet' | secondary | No | One-way | Visual style. Quiet is inline text with an underline. |
size | 32 | 40 | 48 | 40 | No | One-way | Height in pixels. It does not apply to quiet. |
class | string | "" | No | One-way | Extra classes, added after the component classes. |
Snippets
| Name | Type | Default | Required | Binding | Description |
|---|---|---|---|---|---|
children | Snippet | None | No | One-way | The label or content. |
Forwarded attributes
- Primary, secondary, and green accept every Bits UI `Button.Root` prop. That includes `href`, which renders an anchor, plus `type`, `disabled`, `child`, `ref`, native attributes, and event handlers.
- Quiet accepts native button attributes and handlers. It renders a `button` with `type="button"` unless you set `type`.
The primitive underneath is a Bits UI peer dependency. Its own options are documented in the Bits UI Button documentation. Only the props listed on this page are part of the Button contract. No data attributes are documented as stable.
Limits
- Quiet does not accept `href` or `child`, and `size` does not apply. Use your own anchor for navigation. Quiet is an adaptation; its spacing and underline were not measured.
- `variant` is the only prop that changes the render path. A `variant` value outside the four listed fails type checking.
- Disabled quiet actions stay visible and do not fire.