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

4.6 KiB

Badge

A small coloured pill label — the kind you see next to a status field that says "Active", "Pending", or "Error".


Quick example

new Badge("Active")
new Badge("Pending", variant: "secondary")
new Badge("Error",   variant: "destructive")
new Badge("Draft",   variant: "outline")

All the options

public Badge(string text, string variant = "default")
Parameter What it does
text The label inside the pill
variant The colour scheme: "default" (primary colour), "secondary" (muted), "destructive" (red), "outline" (border only)

Real-world examples

Status column in a user table

When you need a Badge inside a table cell (which takes a raw HTML string), render it to a string first:

static string RenderBadge(string text, string variant)
{
    var writer = new System.Buffers.ArrayBufferWriter<byte>();
    new Badge(text, variant).Render(new HtmxRenderContext(writer));
    return System.Text.Encoding.UTF8.GetString(writer.WrittenSpan);
}

new Table(
    headers: new[] { "Name", "Role", "Status" },
    rows: users.Select(u => new[]
    {
        u.DisplayName ?? "",
        u.Role,
        RenderBadge(u.IsActive ? "Active" : "Suspended",
                    u.IsActive ? "default"  : "destructive"),
    }))

Dynamic variant based on data

var badge = order.Status switch
{
    "complete"  => new Badge("Complete"),
    "pending"   => new Badge("Pending",  variant: "secondary"),
    "cancelled" => new Badge("Cancelled", variant: "destructive"),
    _           => new Badge(order.Status, variant: "outline"),
};

Inside a page slot

<!-- MyPage.htmx -->
<div class="flex items-center gap-2">
  <span>Status:</span>
  $$StatusBadge$$
</div>
// MyPage.htmx.cs
public sealed class MyPage : MyPageBase
{
    private readonly IHtmxComponent _statusBadge;

    public MyPage(string status)
    {
        _statusBadge = new Badge(status == "active" ? "Active" : "Inactive",
                                 status == "active" ? "default" : "secondary");
    }

    protected override void RenderStatusBadge(HtmxRenderContext ctx)
        => _statusBadge.Render(ctx.Next());
}

How it works

Badge is a <span> with rounded-full giving it the pill shape. The four variants are just different combinations of background and text colour classes. Badge is a purely server-rendered display element — it has no JavaScript and no click behaviour. If you need a clickable badge, wrap it in an <a> tag or use a Button component with a link variant.


Complete page example

Templates/OrdersPage.htmx

<div class="max-w-4xl mx-auto py-10">
  <h1 class="text-2xl font-bold mb-6">Orders</h1>
  $$OrdersTable$$
</div>

Templates/OrdersPage.htmx.cs

namespace Htmx.ApiDemo.Templates;

public sealed class OrdersPage : OrdersPageBase
{
    private readonly IHtmxComponent _table;

    public OrdersPage(IEnumerable<Order> orders)
    {
        _table = new Components.Table(
            headers: new[] { "Order", "Customer", "Amount", "Status" },
            rows: orders.Select(o => new[]
            {
                System.Net.WebUtility.HtmlEncode(o.Id),
                System.Net.WebUtility.HtmlEncode(o.CustomerName),
                $"${o.Total:F2}",
                BadgeHtml(o.Status),
            }));
    }

    private static string BadgeHtml(string status)
    {
        var variant = status switch
        {
            "paid"      => "default",
            "pending"   => "secondary",
            "cancelled" => "destructive",
            _           => "outline",
        };
        var buf = new System.Buffers.ArrayBufferWriter<byte>();
        new Components.Badge(status, variant).Render(new HtmxRenderContext(buf));
        return System.Text.Encoding.UTF8.GetString(buf.WrittenSpan);
    }

    protected override void RenderOrdersTable(HtmxRenderContext ctx)
        => _table.Render(ctx.Next());
}

GET handler

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

    private static Task<IResult> HandleAsync(
        Query _,
        HttpContext ctx,
        CancellationToken ct)
    {
        // Replace with real data source
        var orders = new[]
        {
            new Order("ORD-001", "Alice Smith",  42.00m, "paid"),
            new Order("ORD-002", "Bob Jones",    18.50m, "pending"),
            new Order("ORD-003", "Carol White",  99.99m, "cancelled"),
        };
        return ctx.WriteHtmxPage(new OrdersPage(orders), title: "Orders");
    }
}