AntaButton
Switch to dark theme
Search documentation
On this page

Button Documentation has not yet been reviewed by a human.

A button starts an action. Use its priority, tone, and size to match the action’s importance and context.

Playground

Priority

Use one primary button for the main action in a group. Lower priorities reduce visual emphasis.

PublishMoveCancelRemind
<Button tone="brand" priority="primary" label="Publish" />
<Button tone="brand" priority="secondary" label="Move" />
<Button tone="brand" priority="tertiary" label="Cancel" />
<Button tone="brand" priority="quaternary" label="Remind" />
  • primary: main call to action
  • secondary: supporting action and the default
  • tertiary: low-emphasis action with a hover background
  • quaternary: text-only action

Tone

Six named tones: neutral (default), brand, critical, info, success, and warning. Omitting tone, or passing an empty string, resolves to neutral.

SavePublishDeletePreviewApproveArchive
<Button label="Save" />
<Button tone="brand" label="Publish" />
<Button tone="critical" label="Delete" />
<Button tone="info" label="Preview" />
<Button tone="success" label="Approve" />
<Button tone="warning" label="Archive" />

Custom tone

Pass any CSS color to tone. Custom tones work with every priority and adapt to the current color mode.

PinkifyPinkifyPinkifyMintifyMintifyMintify
<Button priority="primary" tone="#ff1493" label="Pinkify" />
<Button priority="secondary" tone="oklch(0.655 0.261 356.9)" label="Pinkify" />
<Button priority="tertiary" tone="hsl(328 100% 54%)" label="Pinkify" />
<Button priority="primary" tone="mediumaquamarine" label="Mintify" />
<Button priority="secondary" tone="rgb(102 205 170)" label="Mintify" />
<Button priority="tertiary" tone="lch(75.7% 39.2 167.8)" label="Mintify" />

Size

Buttons come in small, medium, and large. medium is the default.

SmallMediumLarge
<Button tone="brand" size="small" label="Small" />
<Button tone="brand" size="medium" label="Medium" />
<Button tone="brand" size="large" label="Large" />

Paddingless

Use paddingless with a quaternary button when an action should sit flush with surrounding text.

If you’re familiar with the basics, click here to skip the live demo.

If you're familiar with the basics, click
<Button tone="critical" priority="quaternary" paddingless label="here" />
to skip the live demo.

Round

Set round for a pill or circular icon button. Pass a number or CSS length for a custom corner radius.

PillCustom 10px
<Button round tone="brand" label="Pill" />
<Button round tone="brand" icon="heart" aria-label="Like" />
<Button round={10} tone="brand" label="Custom 10px" />

Icons

Use icon for a leading icon and iconTrailing for a trailing icon. See Icon for available shapes.

ConfirmRead the docsFilter
<Button tone="brand" priority="primary" icon="check" label="Confirm" />
<Button tone="brand" iconTrailing="external-link" label="Read the docs" />
<Button tone="brand" priority="tertiary" icon="filter" iconTrailing="chevron-down" label="Filter" />

Icon-only

Omit the label for an icon-only button. Pass a clear aria-label when the icon name does not describe the action well.

<Button icon="dots-vertical" size="small" aria-label="More options" />
<Button tone="critical" icon="trash" aria-label="Delete" />
<Button round tone="brand" icon="check" size="large" aria-label="Confirm" />

Children

Use children for inline content such as keyboard hints, badges, or counters. Text and number children receive the same label styling as the label prop.

Save
<Button tone="brand" label="Save" icon="check" aria-keyshortcuts="Meta+s">
<kbd aria-hidden="true">⌘S</kbd>
</Button>

Underline

Tertiary and quaternary buttons support solid, dashed, and dotted underlines. Use underlineOnHover to show the underline only on hover.

SolidDashedDottedHover only

States

loading and disabled prevent activation. selected communicates a toggled or pressed state.

SubmittingLockedToggled on
<Button tone="brand" loading label="Submitting" />
<Button tone="brand" disabled label="Locked" />
<Button tone="brand" selected label="Toggled on" />

ButtonCopy

ButtonCopy is a Button preset for copy-to-clipboard. Its copy glyph changes to a check on success or an x on failure, then returns to its resting state. onCopied(ok) reports the result. Omit the label for an icon-only copy button.

The preset composes a regular Button with <a-copy>. Use <a-copy> directly when you need the same behavior in another control.

Copy install commandCopy install command
<ButtonCopy copy="npm i @antadesign/anta" label="Copy install command" />
<ButtonCopy copy="https://anta.design" priority="tertiary" />

Icon placement

Set iconPlacement to leading, trailing, or none. With none, the button does not change. Successful pointer activation shows a confirmation beside the pointer; keyboard activation shows it at the button’s inline start. Use copiedLabel to change the message.

LeadingTrailingNo icon
<ButtonCopy copy={value} label="Leading" />
<ButtonCopy copy={value} label="Trailing" iconPlacement="trailing" />
<ButtonCopy copy={value} label="No icon" iconPlacement="none" />

Copy a DOM node

Use copyNode to copy a rendered region as text/html and plain text. Bare copyNode finds the nearest data-copy-source; a string selects an ancestor. The copy control itself is omitted from the copied content.

The quick brown fox jumps over the lazy dog.Copy card
<div data-copy-source>
<Text>The quick brown fox jumps over the lazy dog.</Text>
<ButtonCopy copyNode label="Copy card" />
</div>

Copy the page URL

Use copyUrl to copy location.href. copyWithUrl prefixes copied text with // URL: <current page URL>.

Copy linkCopy snippet
<ButtonCopy copyUrl label="Copy link" />
<ButtonCopy copy={snippet} copyWithUrl label="Copy snippet" />

Copy dynamic text

copy is controlled. For text generated on demand, initialize it to '' and update it in onCopyRequest. The callback fires on pointerdown or Enter/Space keydown, before activation writes the current copy value. Its return value is ignored.

Copy report
const [report, setReport] = useState('')
<ButtonCopy
copy={report}
label="Copy report"
onCopyRequest={() => setReport(generateReport())}
/>

Why copy is controlled

Anta supports applications whose JSX renderer runs in a worker. The DOM copy control and Clipboard API remain on the browser’s UI thread, and a callback cannot cross that boundary as a callable reference.

onCopyRequest asks the application to calculate the text. The resulting state update sends a serializable copy string to the DOM control, which writes it during the user activation required by the Clipboard API. A lazyCopy callback would only hide this state update in a main-thread wrapper and would not work across renderers. Separate copy, copyNode, and copyUrl inputs also keep the clipboard format explicit.

Props

Prop Type Default Description
tone? neutralbrandcriticalinfosuccesswarningstring neutral Semantic tone, or any literal CSS color ('#ff1493', 'rebeccapurple') for a one-off custom tone. Primary uses the color as-is; secondary, tertiary, and quaternary take its hue and pin lightness/chroma to the brand curve so any input stays legible.
size? smallmediumlarge medium Size variant. small=24px, medium=28px, large=32px. Omit the attribute or pass 'medium' for the default — both render identically and emit no DOM attribute.
loading? boolean — Show a rotating loading indicator. Blocks clicks and keyboard activation, and removes the button from the tab order while active.
disabled? boolean — Disable the button.
round? booleannumberstring — Fully-round corners — a pill for text buttons, a circle for icon-only ones (border-radius: 999px, clamped to the element's height). Pass a number (px) or a CSS length string ('1rem') for a custom radius instead.
onClick? (e) => void — Click handler.
tabIndex? number 0 Tab order. The button is keyboard-focusable by default (0) and becomes -1 automatically while disabled or loading — <a-button> and <a role="button"> aren't focusable without an explicit tabindex, and a loading button must stay out of the tab order so Enter/Space can't fire it mid-flight.
role? string button ARIA role override (e.g. 'gridcell' when a button is a cell in a grid). Forwarded to the underlying element.
priority? primarysecondarytertiaryquaternary secondary Visual emphasis.
underline? soliddasheddotted — Underline style.
underlineOnHover? boolean — Hide the underline at rest and reveal it on hover.
paddingless? boolean — Drops outer padding to zero.
label? string — Label text. Renders between the leading icon and children.
icon? IconShape — Leading icon shape. When set alone (no label, no iconTrailing, no children), the button renders as a square icon-only control and the wrapper auto-supplies aria-label={icon} (override by passing your own aria-label).
copy? string — Text copied to the clipboard on activation.
copyWithUrl? boolean — Prefix the copied text with // URL: <current page URL>.
onCopyRequest? () => void — Refresh a dynamic copy value before activation. Set the new string in application state so the next render updates copy. Return values are ignored. Fires on pointerdown and Enter/Space keydown.
onCopied? (ok) => void — Fires after the copy attempt with whether it succeeded.
copyNode? booleanstring — Copy a DOM node as rich text (text/html) + plain text. true copies the nearest ancestor marked data-copy-source; a string is a CSS selector for an ancestor region (closest). The copy control is stripped from the copied output.
copyUrl? true — Copy the current page URL (location.href).
iconPlacement? leadingtrailingnone 'leading' Where the copy glyph sits relative to the label — or 'none' to omit it. Without a glyph, a successful copy shows a small confirmation label near the pointer and leaves the button unchanged.
copiedLabel? string Copied Text in the successful no-icon confirmation.
Inherited props (children, className, id, slot, style, title)
Prop Type Default Description
children? ReactNode — Child elements. When provided, replaces the component's default label/content.
className? string — CSS class on the component's root element (merged with the component's own classes). Use it directly for layout and positioning — grid/flex placement, margins, alignment — rather than wrapping the component in a <div>/<span>.
id? string — HTML id attribute.
slot? string — Assigns the element to a named <slot> of a parent web component (e.g. slot="header" inside a <Dialog>, slot="footer" inside a <Dialog>).
style? CSSProperties — Inline styles on the component's root element. Set layout/positioning here (or via className) directly on the component instead of adding a wrapper.
title? string — HTML title attribute — native browser tooltip on hover.

Plus every standard DOM event handler (onClick, onFocus, onKeyDown, …) and any data-* or aria-* attribute — forwarded as-is to the underlying <a-*> element.

Set href to render a link with button styling. An absent or undefined URL keeps the regular button, which makes conditional links straightforward.

<Button href="/docs" target="_blank" label="Read the docs" />
<Button
href={reportUrl}
disabled={!reportUrl}
iconTrailing="external-link"
label="View report"
/>

Routing libraries

For client-side routing, wrap your router’s link and add role="button" and data-anta to its anchor output.

import { Link } from 'react-router-dom'
export const LinkButton = ({ label, ...props }) => (
<Link role="button" data-anta {...props}>
<a-button-label>{label}</a-button-label>
</Link>
)

Special events

Beyond a plain click, a button can submit or reset a native form and dispatch a named custom event.

Form submission

For non-link buttons, type="submit" and type="reset" integrate with native forms. The form prop associates a button with a form elsewhere on the page. Submitting calls form.requestSubmit(), so the form’s validation and submit event still run. It also dispatches submitdetailed on the form with { formData, submitter: { tag, attrs } } in detail, which can identify the trigger in analytics or multi-button forms.

Sign upClear
Submit from outside
<form id="signup">
<Button tone="brand" type="submit" label="Sign up" />
<Button priority="tertiary" type="reset" label="Clear" />
</form>
<Button type="submit" form="signup" label="Submit from outside" />

Custom click events

Set data-custom-event="<name>" to dispatch a bubbling CustomEvent("<name>") on click. This is useful for declarative actions or analytics that should not take ownership of onClick.

<Button label="Save" data-custom-event="save-clicked" />

Component props

Prop Type Default Description
tone? neutralbrandcriticalinfosuccesswarningstring neutral Semantic tone, or any literal CSS color ('#ff1493', 'rebeccapurple') for a one-off custom tone. Primary uses the color as-is; secondary, tertiary, and quaternary take its hue and pin lightness/chroma to the brand curve so any input stays legible.
size? smallmediumlarge medium Size variant. small=24px, medium=28px, large=32px. Omit the attribute or pass 'medium' for the default — both render identically and emit no DOM attribute.
loading? boolean — Show a rotating loading indicator. Blocks clicks and keyboard activation, and removes the button from the tab order while active.
disabled? boolean — Disable the button.
selected? boolean — Toggled-on / pressed state, e.g. for filter chips.
round? booleannumberstring — Fully-round corners — a pill for text buttons, a circle for icon-only ones (border-radius: 999px, clamped to the element's height). Pass a number (px) or a CSS length string ('1rem') for a custom radius instead.
onClick? (e) => void — Click handler.
tabIndex? number 0 Tab order. The button is keyboard-focusable by default (0) and becomes -1 automatically while disabled or loading — <a-button> and <a role="button"> aren't focusable without an explicit tabindex, and a loading button must stay out of the tab order so Enter/Space can't fire it mid-flight.
role? string button ARIA role override (e.g. 'gridcell' when a button is a cell in a grid). Forwarded to the underlying element.
priority? primarysecondarytertiaryquaternary secondary Visual emphasis.
underline? soliddasheddotted — Underline style.
underlineOnHover? boolean — Hide the underline at rest and reveal it on hover.
paddingless? boolean — Drops outer padding to zero.
label? string — Label text. Renders between the leading icon and children.
icon? IconShape — Leading icon shape. When set alone (no label, no iconTrailing, no children), the button renders as a square icon-only control and the wrapper auto-supplies aria-label={icon} (override by passing your own aria-label).
iconTrailing? IconShape — Trailing icon shape. Renders after children, last in the slot order.
href? string — URL to link to. A definite string renders <a role="button">; omit it (or pass undefined) to render <a-button>, so href={maybeUrl} degrades to a plain button when the URL is absent.
target? string — Anchor target.
rel? string — Anchor rel.
download? stringboolean — Anchor download attribute. Empty string / true triggers a download with the resource's default name; a string overrides the filename.
ping? string — Space-separated URLs the browser pings on navigation.
type? buttonsubmitreset — Form submission type.
form? string — Form id when the button isn't a descendant of its form.
Inherited props (children, className, id, slot, style, title)
Prop Type Default Description
children? ReactNode — Child elements. When provided, replaces the component's default label/content.
className? string — CSS class on the component's root element (merged with the component's own classes). Use it directly for layout and positioning — grid/flex placement, margins, alignment — rather than wrapping the component in a <div>/<span>.
id? string — HTML id attribute.
slot? string — Assigns the element to a named <slot> of a parent web component (e.g. slot="header" inside a <Dialog>, slot="footer" inside a <Dialog>).
style? CSSProperties — Inline styles on the component's root element. Set layout/positioning here (or via className) directly on the component instead of adding a wrapper.
title? string — HTML title attribute — native browser tooltip on hover.

Plus every standard DOM event handler (onClick, onFocus, onKeyDown, …) and any data-* or aria-* attribute — forwarded as-is to the underlying <a-*> element.

Web Component

When using <a-button> directly, add its button role and keyboard tab stop.

Create project
<a-button role="button" tabindex="0" priority="primary">
<a-icon shape="plus" aria-hidden="true"></a-icon>
<a-button-label>Create project</a-button-label>
</a-button>

Native HTML button

Add data-anta to a native <button> to use Anta’s button styles with native keyboard and form behavior. Set type="button" for actions that should not submit a surrounding form. Use type="submit" or type="reset" for form actions.

<button type="button" data-anta tone="brand" priority="primary">Save changes</button>
<button type="button" data-anta disabled>Unavailable</button>

Copy feedback

Put <a-copy> directly inside an activatable control. Add toast for the floating success confirmation and copied-label to change its text. The confirmation uses a manual shadow popover, escapes clipping ancestors, and lets pointer events pass through. Style it with a-copy::part(feedback).

<button type="button" data-anta>
Copy command
<a-copy copy="npm i @antadesign/anta" toast copied-label="Copied"></a-copy>
</button>

copyrequest asks for a controlled copy refresh before activation. copydone reports { ok: boolean } after the clipboard attempt. Both events are non-bubbling. Full-bundle imports and the granular elements/a-copy entry include feedback styling. Under CSP, load their emitted CSS from an allowed URL.

Styling

Use tone, priority, size, and round before adding custom CSS. For a distinct treatment, target a class on the button and cover its interaction states.

Checkout
a-button.checkout {
color: #fff;
background: #673de6;
border-radius: 999px;
padding-inline: 20px;
}
a-button.checkout:hover { background: #5931c4; }
a-button.checkout:active { background: #48269f; }

Style the copy confirmation with a-copy::part(feedback). If you customize display, use a-copy::part(feedback):popover-open so closed popovers stay hidden.