Button
A button, a link that looks like one, or a button_to form, from one call; and button_classes, the class string alone, for link_to, button_to and form.submit. Pick a variant for its weight and a size to sit beside other controls.
Variants
Default, primary, ghost and danger. Danger keeps the default's shape; only the label and hover warn.
<div class="flex flex-wrap items-center gap-2">
<%= tag.button "Default", type: "button", class: button_classes %>
<%= tag.button "Primary", type: "button", class: button_classes(:primary) %>
<%= tag.button "Ghost", type: "button", class: button_classes(:ghost) %>
<%= tag.button "Danger", type: "button", class: button_classes(:danger) %>
</div>Sizes
Small, default and large, each matching an input of the same size.
<div class="flex flex-col items-center gap-3">
<div class="flex flex-wrap items-center gap-2">
<%= tag.button "Small", type: "button", class: button_classes(:default, size: :small) %>
<%= tag.button "Default", type: "button", class: button_classes %>
<%= tag.button "Large", type: "button", class: button_classes(:default, size: :large) %>
</div>
<div class="flex flex-wrap items-center gap-2">
<%= tag.button "Small", type: "button", class: button_classes(:primary, size: :small) %>
<%= tag.button "Default", type: "button", class: button_classes(:primary) %>
<%= tag.button "Large", type: "button", class: button_classes(:primary, size: :large) %>
</div>
</div>Icons, links and forms
icon: leads the label; the :icon variant shows only the icon and keeps the label for a screen reader. href: makes a link, and with method: a button_to form.
<div class="flex flex-wrap items-center gap-2">
<%= button "New label", :primary, icon: :plus %>
<%= button "Docs", href: "#", icon: :book_open %>
<%= button "Delete", :danger, href: "#", method: :delete, form: { data: { turbo_confirm: "Delete this label?" } }, icon: :x %>
<%= button "Close", :icon, icon: :x %>
<%= button "Edit", :icon, icon: :pencil, size: :small %>
</div>Loading, disabled and block
loading: true disables the button and turns a spinner in the icon's place. A disabled link is marked and taken out of the tab order. block: true fills the width.
<div class="flex flex-col items-center gap-3">
<div class="flex flex-wrap items-center gap-2">
<%= button "Saving", :primary, loading: true %>
<%= button "Checking", loading: true, icon: :rotate_cw %>
<%= button "Disabled", disabled: true %>
<%= button "Disabled link", href: "#", disabled: true %>
</div>
<div class="w-64">
<%= button "Continue", :primary, block: true, size: :large %>
</div>
</div>Button groups
button_group joins buttons edge to edge into one control; orientation: :vertical stacks them.
<div class="flex flex-col items-center gap-4">
<%= button_group label: "View" do |group| %>
<% group.button "List", icon: :list_checks, "aria-pressed": "true" %>
<% group.button "Board", icon: :folder %>
<% group.button "Timeline", icon: :clock %>
<% end %>
<%= button_group label: "Move", orientation: :vertical do |group| %>
<% group.button "Up", :icon, icon: :arrow_up, size: :small %>
<% group.button "Down", :icon, icon: :arrow_down, size: :small %>
<% end %>
</div>