# VelvetKit

## Button (`UI::Button`)

Buttons in every variant and size, with icons and a loading state.

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

Also adds: `icon`, `spinner`

### Arguments

```ruby
UI::Button.new(variant: :default, size: :default, type: :button, full_width: false, loading: false, disabled: false, as_child: false, class: nil, **html_attrs)
```

Slots: `with_leading_icon`, `with_trailing_icon`

### Example: All Variants

```erb
<div class="flex flex-wrap items-center gap-3">
  <%= render(UI::Button.new(variant: :default))     { "Default" } %>
  <%= render(UI::Button.new(variant: :destructive)) { "Destructive" } %>
  <%= render(UI::Button.new(variant: :outline))     { "Outline" } %>
  <%= render(UI::Button.new(variant: :secondary))   { "Secondary" } %>
  <%= render(UI::Button.new(variant: :ghost))       { "Ghost" } %>
  <%= render(UI::Button.new(variant: :link))        { "Link" } %>
</div>
```

### Example: All Sizes

```erb
<div class="flex flex-wrap items-center gap-3">
  <%= render(UI::Button.new(size: :sm))      { "Small" } %>
  <%= render(UI::Button.new(size: :default)) { "Default" } %>
  <%= render(UI::Button.new(size: :lg))      { "Large" } %>
  <%= render(UI::Button.new(size: :icon))    { "I" } %>
</div>
```

### Example: With Leading Icon

```erb
<div class="flex flex-wrap items-center gap-3">
  <%= render(UI::Button.new(variant: :default)) do |btn|
        btn.with_leading_icon(name: "lock")
        "Sign in"
      end %>
  <%= render(UI::Button.new(variant: :outline)) do |btn|
        btn.with_leading_icon(name: "eye")
        "Preview"
      end %>
  <%= render(UI::Button.new(variant: :secondary)) do |btn|
        btn.with_leading_icon(name: "badge-check")
        "Verified"
      end %>
  <%= render(UI::Button.new(variant: :destructive)) do |btn|
        btn.with_leading_icon(name: "x")
        "Delete"
      end %>
  <%= render(UI::Button.new(variant: :ghost)) do |btn|
        btn.with_leading_icon(name: "user")
        "Profile"
      end %>
</div>
```

### Example: With Trailing Icon

```erb
<div class="flex flex-wrap items-center gap-3">
  <%= render(UI::Button.new(variant: :default)) do |btn|
        btn.with_trailing_icon(name: "arrow-right")
        "Continue"
      end %>
  <%= render(UI::Button.new(variant: :outline)) do |btn|
        btn.with_trailing_icon(name: "chevrons-up-down")
        "Sort"
      end %>
  <%= render(UI::Button.new(variant: :link)) do |btn|
        btn.with_trailing_icon(name: "arrow-right")
        "Read more"
      end %>
</div>
```

### Example: With Both Icons

```erb
<div class="flex flex-wrap items-center gap-3">
  <%= render(UI::Button.new(variant: :default)) do |btn|
        btn.with_leading_icon(name: "lock")
        btn.with_trailing_icon(name: "arrow-right")
        "Sign in"
      end %>
  <%= render(UI::Button.new(variant: :outline, size: :lg)) do |btn|
        btn.with_leading_icon(name: "eye")
        btn.with_trailing_icon(name: "chevrons-up-down")
        "Preview options"
      end %>
</div>
```

### Example: Icon Only

```erb
<div class="flex flex-wrap items-center gap-3">
  <%= render(UI::Button.new(variant: :default, size: :icon)) do |btn|
        btn.with_leading_icon(name: "menu")
      end %>
  <%= render(UI::Button.new(variant: :outline, size: :icon)) do |btn|
        btn.with_leading_icon(name: "user")
      end %>
  <%= render(UI::Button.new(variant: :secondary, size: :icon)) do |btn|
        btn.with_leading_icon(name: "panel-left")
      end %>
  <%= render(UI::Button.new(variant: :ghost, size: :icon)) do |btn|
        btn.with_leading_icon(name: "x")
      end %>
  <%= render(UI::Button.new(variant: :destructive, size: :icon)) do |btn|
        btn.with_leading_icon(name: "x")
      end %>
</div>
```

### Example: Loading

```erb
<div class="flex flex-wrap items-center gap-3">
  <%= render(UI::Button.new(loading: true)) { "Saving" } %>
  <%= render(UI::Button.new(variant: :outline, loading: true)) do |btn|
        btn.with_leading_icon(name: "lock")
        "Authenticating"
      end %>
  <%= render(UI::Button.new(variant: :destructive, loading: true)) do |btn|
        btn.with_trailing_icon(name: "arrow-right")
        "Deleting"
      end %>
  <%= render(UI::Button.new(variant: :default, size: :icon, loading: true)) %>
</div>
```

### Example: Disabled

```erb
<div class="flex flex-col gap-6">
  <div>
    <p class="text-xs text-muted-foreground mb-2">All variants — disabled</p>
    <div class="flex flex-wrap items-center gap-3">
      <%= render(UI::Button.new(variant: :default,     disabled: true)) { "Default" } %>
      <%= render(UI::Button.new(variant: :destructive, disabled: true)) { "Destructive" } %>
      <%= render(UI::Button.new(variant: :outline,     disabled: true)) { "Outline" } %>
      <%= render(UI::Button.new(variant: :secondary,   disabled: true)) { "Secondary" } %>
      <%= render(UI::Button.new(variant: :ghost,       disabled: true)) { "Ghost" } %>
      <%= render(UI::Button.new(variant: :link,        disabled: true)) { "Link" } %>
    </div>
  </div>

  <div>
    <p class="text-xs text-muted-foreground mb-2">Disabled with icons</p>
    <div class="flex flex-wrap items-center gap-3">
      <%= render(UI::Button.new(disabled: true)) do |btn|
            btn.with_leading_icon(name: "lock")
            "Locked"
          end %>
      <%= render(UI::Button.new(variant: :outline, disabled: true)) do |btn|
            btn.with_trailing_icon(name: "arrow-right")
            "Continue"
          end %>
      <%= render(UI::Button.new(variant: :destructive, size: :icon, disabled: true)) do |btn|
            btn.with_leading_icon(name: "x")
          end %>
    </div>
  </div>

  <div>
    <p class="text-xs text-muted-foreground mb-2">Loading auto-disables (cursor-not-allowed shows on hover)</p>
    <div class="flex flex-wrap items-center gap-3">
      <%= render(UI::Button.new(loading: true)) { "Saving" } %>
      <%= render(UI::Button.new(variant: :destructive, loading: true)) { "Deleting" } %>
      <%= render(UI::Button.new(variant: :outline, loading: true)) { "Loading" } %>
    </div>
  </div>
</div>
```
