Files
Htmx/docs/Components/Button.md
T
2026-05-04 19:57:48 +05:00

5.4 KiB

Button

A styled <button> element. Supports six visual variants and four sizes. HTMX attributes can be injected directly via the hxAttrs parameter.


HTML structure

button[type=$$Type$$, class=$$Classes$$, $$HxAttrs$$]
  $$Label$$

CSS mechanics

Base classes (always applied):

inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium
ring-offset-background transition-colors
focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2
disabled:pointer-events-none disabled:opacity-50

Variant appended:

Variant Added classes
default bg-primary text-primary-foreground hover:bg-primary/90
destructive bg-destructive text-destructive-foreground hover:bg-destructive/90
outline border border-input bg-transparent hover:bg-accent hover:text-accent-foreground
secondary bg-secondary text-secondary-foreground hover:bg-secondary/80
ghost hover:bg-accent hover:text-accent-foreground
link text-primary underline-offset-4 hover:underline

Size appended:

Size Added classes
default h-10 px-4 py-2 text-sm
sm h-9 rounded-md px-3 text-xs
lg h-11 rounded-md px-8 text-base
icon h-10 w-10

Constructor signature

public Button(
    string label,
    string variant = "default",
    string size    = "default",
    string type    = "button",
    string hxAttrs = "")
Parameter Description
label Button text (raw HTML — can include inline SVG)
variant Visual style; see table above
size Physical size; see table above
type HTML button type: "button" / "submit" / "reset"
hxAttrs Verbatim string appended as extra HTML attributes (HTMX, data-*, etc.)

Usage examples

Standard actions

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

Sizes

new Button("Small",   size: "sm")
new Button("Default", size: "default")
new Button("Large",   size: "lg")
new Button("⚙",       size: "icon")  // icon-only square button

HTMX trigger

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

Submit button inside a form

new Button("Sign in", variant: "default", type: "submit", size: "default")

Ghost button with inline SVG icon

new Button(
    label: """
        <svg class="h-4 w-4" .../>
        <span>Refresh</span>
    """,
    variant: "ghost")

Disabled appearance (via HTML)

The Button component does not have a disabled constructor parameter. Set it via hxAttrs if needed:

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

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

<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");
}