Malevich

Elements / Form/

Form-button

Submit button with data-state for submitting/success/error.

Form-button

Submit / reset / cancel button with form-aware states. Per ADR-0013 — distinct from generic Button because submit buttons carry states (submitting, success, error) that generic Button does not.

When to use

For any button that does not submit or reset a form, use generic Button (elements/button/). The decision test: is the button submitting or resetting a form? Yes → Form-button. No → Button.

States

State is driven by data-state on the button. Transitioning states is the consumer's responsibility (form submit handler sets it). Per the answered design question recorded with this component:

State Visual Set when
Default Variant color Initial render
submitting Cursor: progress, indicator slot shows Async submit in flight; pair with aria-busy="true"
success Background: success color, check icon Server returned OK; auto-revert after ~1.5s
error Background: danger color, alert icon Server returned error; revert on retry

The visual states override the variant color so the form button clearly broadcasts outcome regardless of original styling.

Variants

Variant Class
Primary .form-button.-primary
Secondary .form-button.-secondary
Ghost .form-button.-ghost
Danger .form-button.-danger
Success .form-button.-success

Sizes: .-s and .-l (default = medium).

Anatomy

<!-- Default -->
<button type="submit" class="form-button -primary">Save</button>

<!-- Submitting -->
<button type="submit" class="form-button -primary"
        data-state="submitting" aria-busy="true">
  Saving
  <span class="form-button__indicator" aria-hidden="true">
    <span class="spinner -s -inverse" role="presentation"></span>
  </span>
</button>

<!-- Success -->
<button type="submit" class="form-button -primary" data-state="success">
  Saved
  <span class="form-button__indicator" aria-hidden="true">✓</span>
</button>

<!-- Error -->
<button type="submit" class="form-button -primary" data-state="error">
  Try again
  <span class="form-button__indicator" aria-hidden="true">⚠</span>
</button>

Authors render all four state contents conditionally (or swap inner content on transition). A common pattern is a single inner indicator slot that the application updates on each state change.

Tokens used

Accessibility

Edge cases

Do

Don't