# Card A styled container with optional header (title + description) and footer sections. The body content is always rendered; header and footer are conditionally included. --- ## HTML structure ``` div.rounded-lg.border.border-border.bg-card.text-card-foreground.shadow-sm.{extraClasses} div.flex.flex-col.space-y-1.5.p-6 ← header (omitted when no title/description) h3.text-2xl.font-semibold ← title p.text-sm.text-muted-foreground ← description div.p-6.pt-0 ← content (always present) {content} div.flex.items-center.p-6.pt-0 ← footer (omitted when empty) {footer} ``` --- ## CSS mechanics | Class | Effect | |---|---| | `bg-card text-card-foreground` | Pulls from CSS variables — dark mode works automatically | | `rounded-lg border border-border shadow-sm` | Subtle rounded box with border and drop shadow | | `p-6 pt-0` on content | Full padding except top (header provides the top spacing) | | `space-y-1.5` on header | Controlled gap between title and description | --- ## Constructor signature ```csharp public Card( string content, string title = "", string description = "", string footer = "", string extraClasses = "") ``` | Parameter | Description | |---|---| | `content` | Raw HTML for the card body (always rendered) | | `title` | Optional heading in the header area | | `description` | Optional subheading below the title | | `footer` | Optional raw HTML in the footer area | | `extraClasses` | Additional Tailwind classes on the outer `div` | --- ## Usage examples ### Simple content card ```csharp new Card(content: "
Your subscription renews on July 1.
") ``` ### Card with title and description ```csharp new Card( content: "Manage your billing details and invoices.
", title: "Billing", description: "Your current plan: Pro") ``` ### Card with footer actions ```csharp new Card( content: "Are you sure you want to cancel your account?
", title: "Delete account", description: "This action cannot be undone.", footer: """ """) ``` ### Constrained width ```csharp new Card( content: "Hello world
", title: "Welcome", extraClasses: "max-w-sm mx-auto") ``` ### Embedding a component as content ```csharp // Render a Badge to a string then embed in the card body var writer = new System.Buffers.ArrayBufferWriterStatus:
{badgeHtml}", title: "Account") ``` --- ## Tips and tricks - `content`, `footer`, title, and description are inserted as raw HTML — HTML-encode any user-supplied strings before passing them in. - Use `extraClasses` to set max-width, margin, or custom background without subclassing. - If you need a completely custom header layout, omit `title` and `description` and build the header HTML in `content`, adding `p-6` padding yourself. - Cards can be placed in a CSS grid: `{stats.UserCount:N0}
"); _revenue = new Components.Card( title: "Revenue", description: "This month", content: $"${stats.MonthlyRevenue:N2}
"); _orders = new Components.Card( title: "Open orders", description: "Awaiting fulfillment", content: $"{stats.OpenOrders}
", footer: """View all"""); } protected override void RenderUsersCard(HtmxRenderContext ctx) => _users.Render(ctx.Next()); protected override void RenderRevenueCard(HtmxRenderContext ctx) => _revenue.Render(ctx.Next()); protected override void RenderOrdersCard(HtmxRenderContext ctx) => _orders.Render(ctx.Next()); } ``` **GET handler** ```csharp [Handler] [MapGet("/dashboard")] public static partial class GetDashboardHandler { public record Query(); private static Task