ee8797c142
Co-authored-by: Copilot <copilot@github.com>
194 lines
5.4 KiB
Markdown
194 lines
5.4 KiB
Markdown
# 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
|
|
|
|
```csharp
|
|
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
|
|
|
|
```csharp
|
|
new Button("Save changes", type: "submit")
|
|
new Button("Cancel", variant: "outline")
|
|
new Button("Delete", variant: "destructive")
|
|
new Button("Learn more", variant: "link")
|
|
```
|
|
|
|
### Sizes
|
|
|
|
```csharp
|
|
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
|
|
|
|
```csharp
|
|
new Button(
|
|
"Load more",
|
|
hxAttrs: """hx-get="/items?page=2" hx-target="#item-list" hx-swap="beforeend"""")
|
|
```
|
|
|
|
### Submit button inside a form
|
|
|
|
```csharp
|
|
new Button("Sign in", variant: "default", type: "submit", size: "default")
|
|
```
|
|
|
|
### Ghost button with inline SVG icon
|
|
|
|
```csharp
|
|
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:
|
|
|
|
```csharp
|
|
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`**
|
|
```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`**
|
|
```csharp
|
|
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**
|
|
```csharp
|
|
[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");
|
|
}
|
|
```
|