f6ae86617c
Co-authored-by: Copilot <copilot@github.com>
5.6 KiB
5.6 KiB
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")
Confirm and cancel in a dialog footer
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");
}