Button group

One labelled action group containing typed Button children.

Source
app/components/nitro_kit/button_group.rb
API
NitroKit::ButtonGroup.new(label:) { |group| group.button }

Member counts

One, two, and larger groups share the same labelled native group contract.

Count scale

One action
Two actions
Four actions
Viewport640 px · sm
Rubytest/dummy/app/components/gallery/components/button_group_page.rb
sample("One action", slug: "one") do
  render NitroKit::ButtonGroup.new(
    id: "gallery-button-group-one",
    label: "Single record action",
    buttons: [
      NitroKit::Button.new(
        "Edit",
        id: "gallery-button-group-one-edit",
        icon: :pencil
      )
    ]
  )
end
sample("Two actions", slug: "two") do
  render NitroKit::ButtonGroup.new(
    id: "gallery-button-group-two",
    label: "Form actions"
  ) do |group|
    group.button("Save", id: "gallery-button-group-two-save", variant: :primary)
    group.button("Cancel", id: "gallery-button-group-two-cancel")
  end
end
sample("Four actions", slug: "four") do
  render NitroKit::ButtonGroup.new(
    id: "gallery-button-group-four",
    label: "Document actions"
  ) do |group|
    group.button("Open", id: "gallery-button-group-four-open")
    group.button("Duplicate", id: "gallery-button-group-four-duplicate")
    group.button("Archive", id: "gallery-button-group-four-archive")
    group.button("Delete", id: "gallery-button-group-four-delete", variant: :destructive)
  end
end

Mixed actions

Buttons, links, leading and trailing icons, long labels, blocks, and disabled state can coexist.

Mixed member contract

ViewportFull width
Rubytest/dummy/app/components/gallery/components/button_group_page.rb
render NitroKit::ButtonGroup.new(
  id: "gallery-button-group-mixed",
  label: "Audit record actions"
) do |group|
  group.button(
    "Return to audit log",
    id: "gallery-button-group-mixed-back",
    href: "#audit-log",
    icon: :arrow_left
  )
  group.button(
    "Export every selected record as a comma-separated value file",
    id: "gallery-button-group-mixed-export",
    href: "#audit-export",
    icon: :download
  )
  group.button(
    "Archive",
    id: "gallery-button-group-mixed-archive",
    icon_right: :archive,
    disabled: true
  )
  group.button(
    id: "gallery-button-group-mixed-delete",
    icon: :trash_2,
    variant: :destructive,
    aria: { label: "Delete selected audit records" }
  )
  group.button(id: "gallery-button-group-mixed-block") { "Block-provided action" }
end

Record toolbar

Card, Badge, ButtonGroup, and Button compose into a focused record toolbar.

API credential

Viewport640 px · sm
Rubytest/dummy/app/components/gallery/components/button_group_page.rb
render NitroKit::Card.new(id: "gallery-button-group-record-card") do |card|
  card.title("Production API key", level: 3)
  card.body do
    render NitroKit::Badge.new(
      "Read and write",
      id: "gallery-button-group-record-access",
      color: :info,
      size: :sm
    )
    p { "nk_live_7P3F · Last used July 13, 2026 at 08:31 UTC" }
  end
  card.footer do
    render NitroKit::ButtonGroup.new(
      id: "gallery-button-group-record-actions",
      label: "Production API key actions"
    ) do |group|
      group.button(
        "Copy prefix",
        id: "gallery-button-group-record-copy",
        icon: :copy
      )
      group.button(
        "Rotate key",
        id: "gallery-button-group-record-rotate",
        icon: :refresh_cw
      )
      group.button(
        "Revoke",
        id: "gallery-button-group-record-revoke",
        variant: :destructive,
        icon: :trash_2
      )
    end
  end
end

Table toolbar

A labelled bulk-action group remains separate from the semantic records table it controls.

Selected members

ViewportFull width
Rubytest/dummy/app/components/gallery/components/button_group_page.rb
render NitroKit::ButtonGroup.new(
  id: "gallery-button-group-table-actions",
  label: "Two selected member actions"
) do |group|
  group.button("Change role", id: "gallery-button-group-table-role", icon: :user_cog)
  group.button("Deactivate", id: "gallery-button-group-table-deactivate", disabled: true)
  group.button(
    "Remove",
    id: "gallery-button-group-table-remove",
    variant: :destructive,
    icon: :user_minus
  )
end

render NitroKit::Table.new(
  id: "gallery-button-group-members-table",
  table_html: { id: "gallery-button-group-members-table-element" }
) do |table|
  table.caption("Selected workspace members")
  table.thead do
    table.tr do
      table.th("Name")
      table.th("Role")
      table.th("Status", align: :right)
    end
  end
  table.tbody do
    Gallery::Data.members.first(2).each do |member|
      table.tr do
        table.th(member.name, scope: :row)
        table.td(member.role.to_s.humanize)
        table.td(member.status.to_s.humanize, align: :right)
      end
    end
  end
end