Files
Htmx/docs/Components/Button.md
T
2026-05-05 23:55:26 +05:00

5.6 KiB
Raw Blame History

Button

A styled clickable button. Use it for form submissions, navigation actions, or triggering HTMX requests.


Quick example

new Button("Save changes", type: "submit")
new Button("Cancel",       variant: "outline")
new Button("Delete",       variant: "destructive")

All the options

public Button(
    string label,
    string variant = "default",
    string size    = "default",
    string type    = "button",
    string hxAttrs = "")
Parameter What it does
label The button text. Can include raw HTML — useful for icons.
variant Visual style. See table below.
size How big the button is. See table below.
type HTML button type. Use "submit" for form submit buttons. Defaults to "button".
hxAttrs Extra HTML attributes added verbatim — use this for HTMX, disabled, data-*, etc.

Variants:

Variant Looks like
default Filled with the primary colour — use for the main action on a page
destructive Red — use for irreversible actions like delete
outline Transparent with a border — use for secondary actions
secondary Muted fill — use for tertiary actions
ghost Invisible until hovered — use for toolbar buttons and icon actions
link Looks like a hyperlink with an underline on hover

Sizes:

Size Dimensions
sm Compact (36px tall) — good for dense UI
default Standard (40px tall)
lg Large (44px tall) — good for prominent CTAs
icon Square (40×40) — for icon-only buttons

Real-world examples

Form submit button

new Button("Sign in", type: "submit")
var footer = """
    {cancelButton}
    {deleteButton}
    """;

// Pre-render each to HTML string and embed:
string Render(IHtmxComponent c)
{
    var w = new System.Buffers.ArrayBufferWriter<byte>();
    c.Render(new HtmxRenderContext(w));
    return System.Text.Encoding.UTF8.GetString(w.WrittenSpan);
}

new Card(
    content: "<p>Are you sure you want to delete this item?</p>",
    footer:  Render(new Button("Cancel", variant: "outline"))
           + Render(new Button("Delete", variant: "destructive", type: "submit")))

HTMX load more button

new Button(
    "Load more",
    variant:  "outline",
    hxAttrs:  """hx-get="/items?page=2" hx-target="#item-list" hx-swap="beforeend"""")

Icon-only ghost button (e.g. a refresh icon in a toolbar)

new Button(
    label:   "<svg class='h-4 w-4' ...fill or stroke SVG here/>",
    variant: "ghost",
    size:    "icon")

Disabled state

Button does not have a disabled parameter. Pass it through hxAttrs:

new Button("Processing...", hxAttrs: "disabled aria-disabled='true'")

How it works

Button is a <button> element — straightforward HTML with Tailwind classes. The hxAttrs string is appended verbatim inside the opening <button> tag, so any valid HTML attribute works there. The label is inserted as raw HTML, which is how inline SVG icons are supported.


---

## Tips and tricks

- Use `type: "submit"` only inside `<form>` elements. Outside a form, always use `type: "button"` to prevent accidental page reloads in some browsers.
- `hxAttrs` is written verbatim between the class and the closing `>` of the button tag — you can add any attribute here: `hx-*`, `data-*`, `aria-*`, `onclick`, etc.
- The `ghost` variant has no visible background at rest — use it for toolbar actions or secondary icon buttons.
- The `link` variant looks like an anchor but behaves as a button — useful for inline text actions that trigger JS or HTMX requests rather than navigation.
- To use Button as a DropdownMenu trigger, pass a `Button` instance to `DropdownMenu`'s `trigger` parameter.

---

## Complete page example

**`Templates/SettingsPage.htmx`**
```html
<div class="max-w-lg mx-auto py-10 space-y-6">
  <h1 class="text-2xl font-bold">Settings</h1>
  <div class="flex gap-3">
    $$SaveBtn$$
    $$CancelBtn$$
    $$DangerBtn$$
  </div>
  <div class="border-t pt-4">
    $$LearnMoreLink$$
  </div>
</div>

Templates/SettingsPage.htmx.cs

namespace Htmx.ApiDemo.Templates;

public sealed class SettingsPage : SettingsPageBase
{
    private readonly IHtmxComponent _save;
    private readonly IHtmxComponent _cancel;
    private readonly IHtmxComponent _danger;
    private readonly IHtmxComponent _learn;

    public SettingsPage()
    {
        _save   = new Components.Button("Save changes", type: "submit");
        _cancel = new Components.Button("Cancel",       variant: "outline");
        _danger = new Components.Button("Delete account", variant: "destructive",
                      hxAttrs: "data-dialog-open=\"confirm-delete\"");
        _learn  = new Components.Button("Learn more about settings", variant: "link");
    }

    protected override void RenderSaveBtn(HtmxRenderContext ctx)       => _save.Render(ctx.Next());
    protected override void RenderCancelBtn(HtmxRenderContext ctx)     => _cancel.Render(ctx.Next());
    protected override void RenderDangerBtn(HtmxRenderContext ctx)     => _danger.Render(ctx.Next());
    protected override void RenderLearnMoreLink(HtmxRenderContext ctx) => _learn.Render(ctx.Next());
}

GET handler

[Handler]
[MapGet("/settings")]
public static partial class GetSettingsHandler
{
    public record Query();

    private static Task<IResult> HandleAsync(
        Query _,
        HttpContext ctx,
        CancellationToken ct)
        => ctx.WriteHtmxPage(new SettingsPage(), title: "Settings");
}