A pressable action. Primary for the one thing a view is for, secondary beside it, tertiary for the quiet way out and danger for a destructive confirmation.
Variants
Signal orange is deliberately not a variant: it is reserved for consent and legal actions.
Example
'use client';
import { Button } from '@snapshot-ui/react';
import type { ReactElement } from 'react';
export default function ButtonVariants(): ReactElement {
return (
<div className="row" style={{ justifyContent: 'center', gap: 12 }}>
<Button>Save changes</Button>
<Button variant="secondary">Preview</Button>
<Button variant="tertiary">Discard</Button>
<Button variant="danger">Delete site</Button>
</div>
);
}States
Pending keeps the width and the focus, and announces itself. Disabled is the only grey.
Example
'use client';
import { Button } from '@snapshot-ui/react';
import { useState, type ReactElement } from 'react';
export default function ButtonStates(): ReactElement {
const [isPending, setPending] = useState(false);
return (
<div className="row" style={{ justifyContent: 'center', gap: 12 }}>
<Button
isPending={isPending}
pendingLabel="Saving"
onPress={() => {
setPending(true);
setTimeout(() => {
setPending(false);
}, 2000);
}}
>
Save changes
</Button>
<Button isDisabled>Save changes</Button>
<Button variant="secondary" isDisabled>
Preview
</Button>
</div>
);
}Usage
Pass isPending while work runs. The button stays focusable, ignores presses and does not submit its form.
import { Button } from '@snapshot-ui/react';
export function SaveBar({ isSaving }: { isSaving: boolean }) {
return (
<Button type="submit" isPending={isSaving} pendingLabel="Saving">
Save changes
</Button>
);
}Props
Every React Aria Button prop is accepted. These are the ones Snapshot UI adds or shapes.
Whether the button is disabled.
Whether the button is in a pending state. This disables press and hover events while retaining focusability, and announces the pending state to screen readers.
Handler that is called when the press is released over the target.
Accessible name of the spinner shown while isPending.
Default: 'Loading'
Visual emphasis. Signal orange is deliberately not a variant: it is reserved for consent and legal actions.
Default: 'primary'
Accessibility
A native button element, with React Aria handling press across mouse, touch and keyboard.
Design rules
What keeps buttons in the system.
One primary per view. Pair it with a secondary or a tertiary.
Labels are verbs in sentence case, such as Save changes.
Never orange. Signal orange belongs to consent and legal actions.