# VelvetKit

## Toggle group (`UI::ToggleGroup`)

A row of buttons where one or several are chosen, posting like radios or checkboxes.

Add it: `bin/rails generate velvetkit:add toggle_group`

Also adds: `icon`

### Arguments

```ruby
UI::ToggleGroup.new(name: nil, value: nil, multiple: false, variant: :default, size: :default, label: nil, form: nil, field: nil, required: false, disabled: false, class: nil, **html_attrs)
```

Slots: `with_item`

### Notes

A row of buttons where one is chosen (like radios) or several are
(`multiple: true`, like checkboxes). Each item is a real radio or checkbox
input inside its label, so it posts with the form under `name`, resets with
it, and needs no JavaScript: arrow keys move between radios and Space ticks a
checkbox. Bind it to a form builder with `form:` and `field:`.

A multiple group also posts an empty `name[]` value, so unticking every item
still sends the field, the way Rails' collection_check_boxes does.

`variant: :default` is a segmented control on a muted track; `:outline`
joins bordered buttons. Give the group a `label:` (its accessible name), and
give an icon-only item a `label:` too, which becomes its hidden text and
tooltip. Listen for `change` on the group to act as soon as the choice changes.

### Example: Outline

```erb
<%= render(UI::ToggleGroup.new(name: "billing", value: "monthly", variant: :outline, label: "Billing period")) do |group| %>
  <% group.with_item(value: "monthly", label: "Monthly") %>
  <% group.with_item(value: "yearly", label: "Yearly") %>
  <% group.with_item(value: "lifetime", label: "Lifetime", disabled: true) %>
<% end %>
```

### Example: With Icons

```erb
<%= render(UI::ToggleGroup.new(name: "layout", value: "grid", label: "Layout")) do |group| %>
  <% group.with_item(value: "list", label: "List", icon: "list") %>
  <% group.with_item(value: "grid", label: "Grid", icon: "layout-grid") %>
  <% group.with_item(value: "board", label: "Board", icon: "folder-kanban") %>
<% end %>
```

### Example: Icon Only

```erb
<%= render(UI::ToggleGroup.new(name: "align", value: "left", variant: :outline, label: "Text alignment")) do |group| %>
  <% group.with_item(value: "left", label: "Align left", icon: "align-left", icon_only: true) %>
  <% group.with_item(value: "center", label: "Align center", icon: "align-center", icon_only: true) %>
  <% group.with_item(value: "right", label: "Align right", icon: "align-right", icon_only: true) %>
<% end %>
```

### Example: Multiple

```erb
<%= render(UI::ToggleGroup.new(name: "styles", value: %w[bold], multiple: true, variant: :outline, label: "Text style")) do |group| %>
  <% group.with_item(value: "bold", label: "Bold", icon: "bold", icon_only: true) %>
  <% group.with_item(value: "italic", label: "Italic", icon: "italic", icon_only: true) %>
  <% group.with_item(value: "underline", label: "Underline", icon: "underline", icon_only: true) %>
<% end %>
```

### Example: Sizes

```erb
<div class="flex flex-col items-start gap-4">
  <% %i[sm default lg].each do |size| %>
    <%= render(UI::ToggleGroup.new(name: "size-#{size}", value: "b", size: size, label: "#{size} size")) do |group| %>
      <% group.with_item(value: "a", label: "Draft") %>
      <% group.with_item(value: "b", label: "Published") %>
      <% group.with_item(value: "c", label: "Archived") %>
    <% end %>
  <% end %>
</div>
```

### Example: In a Form

```erb
<form class="flex max-w-sm flex-col gap-4" action="#" onsubmit="event.preventDefault()">
  <div class="flex flex-col gap-2">
    <span id="visibility-label" class="text-sm font-medium">Visibility</span>
    <%= render(UI::ToggleGroup.new(name: "project[visibility]", value: "team", required: true, variant: :outline, class: "w-full", aria: { labelledby: "visibility-label" })) do |group| %>
      <% group.with_item(value: "private", label: "Private", class: "flex-1") %>
      <% group.with_item(value: "team", label: "Team", class: "flex-1") %>
      <% group.with_item(value: "public", label: "Public", class: "flex-1") %>
    <% end %>
  </div>
  <%= render(UI::Button.new(type: :submit, class: "self-start")) { "Save" } %>
</form>
```
