Capítulo 15 de 51

Chapter 15: Button

Core Idea

A single-part button that enforces real button semantics (role="button", keyboard interaction, disabled handling) even when rendered as a non-<button> tag via render — but it must never be used to render a link, since links have their own semantics that button behavior would incorrectly override.

Key Concepts

  • type="submit" is not automatic: unlike a native <button>, you must explicitly pass type="submit" for Button to act as a form submit button.
  • Non-button tags: render={<div />} nativeButton={false} lets Button render as any element while keeping it keyboard-accessible (useful for buttons needing complex non-inline children a native <button> restricts).
  • Never render a link as a Button: nativeButton={false} signals "not a <button> tag" but still applies button semantics — links must keep their own native semantics. If a link needs button styling, style the <a> directly with CSS instead of routing it through Button.
  • Loading states: set focusableWhenDisabled so a button that disables itself after being clicked (e.g. entering a loading spinner state) keeps focus and tab order instead of silently dropping focus.

Reference Tables

PartNotable propsNotable data attributes
ButtonnativeButton, focusableWhenDisableddata-disabled

Key Takeaways

  1. Add type="submit" explicitly on any Button meant to submit a form — the common bug is assuming Button mirrors native <button> defaults here.
  2. Never wrap an <a> with Button/render to make a "button-styled link" — style the anchor directly; Button's enforced semantics conflict with link semantics.
  3. Set focusableWhenDisabled on any button that disables itself post-click (loading/submitting state) to avoid a focus-loss accessibility bug.

Connects To

  • ch007 (Composition): render/nativeButton is the same pattern used across every trigger-like part in the library (Menu.Trigger, Checkbox.Root, etc.).
  • ch025 (Form): submit-button wiring in a Base UI Form.