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

178 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Alert
A contextual callout box for informational or error messages. Two variants: `default` (neutral) and `destructive` (red). An optional inline SVG icon is positioned automatically.
---
## HTML structure
```
div[role=alert].{variant classes}
{icon SVG} ← positioned absolute top-left via Tailwind arbitrary selectors
div
h5.font-medium ← title (always rendered)
div.text-sm ← description (omitted when empty)
```
---
## CSS mechanics
| Class / selector | Effect |
|---|---|
| `[&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4` | Positions any direct SVG child at top-left |
| `[&>svg~*]:pl-7` | Adds left padding to all siblings after the SVG so text is not covered by the icon |
| `[&>svg+div]:translate-y-[-3px]` | Vertically aligns the text div with the icon center |
| `border-destructive/50 text-destructive` | Red destructive variant |
The arbitrary selector approach (`[&>svg]:*`) means you can pass any SVG and it will be positioned correctly without extra wrapper divs.
---
## Constructor signature
```csharp
public Alert(
string title,
string description = "",
string variant = "default",
string icon = "")
```
| Parameter | Description |
|---|---|
| `title` | Required heading text |
| `description` | Optional body text below the title |
| `variant` | `"default"` or `"destructive"` |
| `icon` | Raw SVG string; omit for a text-only alert |
---
## Usage examples
### Informational (no icon)
```csharp
new Alert(
title: "Heads up",
description: "Your session expires in 5 minutes.")
```
### Destructive
```csharp
new Alert(
title: "Error",
description: "Invalid email or password.",
variant: "destructive")
```
### With an icon
```csharp
new Alert(
title: "New message",
description: "You have 3 unread messages.",
variant: "default",
icon: """
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07
A19.5 19.5 0 013.07 9.77a19.79 19.79 0 01-3.07-8.67
A2 2 0 012 .18L5 0a2 2 0 012 1.72 ..."/>
</svg>
""")
```
### Title-only
```csharp
new Alert(title: "Changes saved successfully.", variant: "default")
```
---
## Tips and tricks
- The icon SVG should be `h-4 w-4` — larger sizes will push text out of alignment.
- For the `destructive` variant the icon automatically inherits `text-destructive` color via the variant class.
- The `description` slot is a raw HTML string — you can include `<a>` links or `<code>` spans.
- Use `Alert` inside a page's optional error slot rather than always rendering it — pass an empty byte array (`[]`) when there is no error so the slot renders nothing.
---
## Complete page example
**`Templates/SystemStatusPage.htmx`**
```html
<div class="max-w-2xl mx-auto py-10 space-y-4">
<h1 class="text-2xl font-bold mb-6">System Status</h1>
$$MaintenanceAlert$$
$$DatabaseAlert$$
$$ApiAlert$$
</div>
```
**`Templates/SystemStatusPage.htmx.cs`**
```csharp
namespace Htmx.ApiDemo.Templates;
public sealed class SystemStatusPage : SystemStatusPageBase
{
private readonly IHtmxComponent _maintenance;
private readonly IHtmxComponent _database;
private readonly IHtmxComponent _api;
public SystemStatusPage(bool maintenanceScheduled, bool dbDegraded, bool apiOk)
{
_maintenance = maintenanceScheduled
? new Components.Alert(
title: "Scheduled maintenance",
description: "The service will be unavailable on Saturday 00:0002:00 UTC.",
variant: "default")
: HtmxEmpty.Instance;
_database = dbDegraded
? new Components.Alert(
title: "Database degraded",
description: "Query latency is elevated. Our team is investigating.",
variant: "destructive")
: HtmxEmpty.Instance;
_api = apiOk
? new Components.Alert(title: "All systems operational.")
: HtmxEmpty.Instance;
}
protected override void RenderMaintenanceAlert(HtmxRenderContext ctx)
=> _maintenance.Render(ctx.Next());
protected override void RenderDatabaseAlert(HtmxRenderContext ctx)
=> _database.Render(ctx.Next());
protected override void RenderApiAlert(HtmxRenderContext ctx)
=> _api.Render(ctx.Next());
}
```
**GET handler**
```csharp
[Handler]
[MapGet("/status")]
public static partial class GetSystemStatusHandler
{
public record Query();
private static Task<IResult> HandleAsync(
Query _,
HttpContext ctx,
CancellationToken ct)
{
var page = new SystemStatusPage(
maintenanceScheduled: true,
dbDegraded: false,
apiOk: true);
return ctx.WriteHtmxPage(page, title: "System Status");
}
}
```