Button

Filled / outlined CTA. Renders as <button (or <a when the action implies navigation). Supports an optional inline icon and a typed action prop covering navigation, modal toggling, cart, theme, and custom JS.

Filled / outlined CTA. Renders as <button> (or <a> when the action implies navigation). Supports an optional inline icon and a typed action prop covering navigation, modal toggling, cart, theme, and custom JS.

Button renders only its text and optional icon — child nodes in block JSON are ignored. For clickable wrappers around arbitrary children, use Container with an action prop instead.

Key files

Props

PropTypeNotes
textstringRequired. Interpolated against current item context ({{item.*}}).
icon{ value, only?, position?, size?, color? }value is ref-icon:<set>/<ExportName> or ref-image:<mediaId>. only: true hides text.
actionobjectSee actions-and-handlers. Types: link, open-modal, show-hide, toggle-theme, copy-to-clipboard, download-file, add-to-cart, toggle-cart, cart-checkout, manage-subscription, agent-send.
attrsrecordPass-through DOM attrs (data-*, role, aria-*). String values interpolate {{item.*}}.
handlersRecord<EventName, string>Custom JS event handlers (onClick, onMouseEnter, …) compiled as new Function("event", code). Runs after action. Editor-suppressed.
className, rootCanonical CTA: btn btn-primary cta-responsive rounded-box px-space-md py-space-xs min-h-12 font-semibold.

When to use (vs alternatives)

  • Button — anything with btn chrome (filled / outlined CTAs).
  • Link — plain text hyperlinks, nav items, "read more", footer links, mailto:/tel:. Link only supports the navigational link action.
  • Icon — standalone icons not inside a CTA. Don't add a separate Icon next to a Button — use Button.icon so the pair is atomic.

Gotchas

  • Button's text is a string, not HTML. Use Tiptap-style spans (<span data-variable="item.title" class="variable-node">{{item.title}}</span>) for interpolation in Text, but for Button just write {{item.title}} bare in text.
  • Children in JSON are ignored. Migrate to Container if you need them.
  • Long-text labels need max-w-full whitespace-normal text-xs sm:text-sm to wrap on mobile (btn defaults to nowrap).
  • On dark themes where Primary ≈ Base 100, btn btn-primary is invisible — use explicit bg-* text-* px-* py-* instead.

Related