f6ae86617c
Co-authored-by: Copilot <copilot@github.com>
177 lines
4.6 KiB
Markdown
177 lines
4.6 KiB
Markdown
# Badge
|
|
|
|
A small coloured pill label — the kind you see next to a status field that says "Active", "Pending", or "Error".
|
|
|
|
---
|
|
|
|
## Quick example
|
|
|
|
```csharp
|
|
new Badge("Active")
|
|
new Badge("Pending", variant: "secondary")
|
|
new Badge("Error", variant: "destructive")
|
|
new Badge("Draft", variant: "outline")
|
|
```
|
|
|
|
---
|
|
|
|
## All the options
|
|
|
|
```csharp
|
|
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:
|
|
|
|
```csharp
|
|
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
|
|
|
|
```csharp
|
|
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
|
|
|
|
```html
|
|
<!-- MyPage.htmx -->
|
|
<div class="flex items-center gap-2">
|
|
<span>Status:</span>
|
|
$$StatusBadge$$
|
|
</div>
|
|
```
|
|
|
|
```csharp
|
|
// 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`**
|
|
```html
|
|
<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`**
|
|
```csharp
|
|
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**
|
|
```csharp
|
|
[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");
|
|
}
|
|
}
|
|
```
|