Components
Card
A container for related content. Give it a header, a body and a footer and it handles the spacing, dividers and corners between them: Body sets how they are apart, Variant the surface, Size the room.
Drawn and behaving as Flux UI's card does, measured against its live docs.
Card
Anything put straight inside is padded evenly.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CardExample : Component
{
protected override Component? Render() =>
Ui.Card.Class("max-w-sm")[
Ui.CardHeading.Lg["Are you sure?"],
Ui.Text.Class("mt-2 mb-4")["Your post will be deleted permanently. This action cannot be undone."],
Ui.Button["Delete"]
];
}Your post will be deleted permanently. This action cannot be undone.
Header, body and footer
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CardProfileExample : Component
{
protected override Component? Render() =>
Ui.Card.Inset.Soft.Lg.Class("max-w-md")[
Ui.CardHeader[
Ui.CardHeading["Profile"],
Ui.CardSubheading["This is how others will see you"],
Ui.CardActions[Ui.Button["Edit"]]
],
Ui.CardBody[
Ui.Text.Variant(Ui.TextVariant.Strong)["Rosa Vidal"],
Ui.Text.Class("mt-4")["A few words about yourself"]
],
Ui.CardFooter[
Ui.Text["Last saved 2 minutes ago"],
Ui.CardActions[Ui.Button["Cancel"], Ui.Button["Save"]]
]
];
}This is how others will see you
Rosa Vidal
A few words about yourself
Last saved 2 minutes ago
As a link
The link goes around a small card, and the hover is the call site's.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CardLinkExample : Component
{
protected override Component? Render() =>
A.Href("#").Aria("label", "Latest on our blog").Class("block max-w-sm")[
Ui.Card.Xs.Class("hover:bg-zinc-50 dark:hover:bg-zinc-700")[
Ui.CardHeading["Latest on our blog"],
Ui.Text.Class("mt-2")["Stay up to date with our latest insights, tutorials, and product updates."]
]
];
}Variants
The surface, from raised to a bare edge.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CardVariantsExample : Component
{
protected override Component? Render() =>
Div.Class("grid gap-4 sm:grid-cols-3")[
Ui.Card.Sm[Ui.CardHeading["Default"], Ui.Text.Class("mt-1")["Raised, for primary content."]],
Ui.Card.Sm.Muted[Ui.CardHeading["Muted"], Ui.Text.Class("mt-1")["A quieter tint for secondary panels."]],
Ui.Card.Sm.Soft[Ui.CardHeading["Soft"], Ui.Text.Class("mt-1")["The faintest tint, for light grouping."]],
Ui.Card.Sm.Outline[Ui.CardHeading["Outline"], Ui.Text.Class("mt-1")["Just an edge, over whatever's behind it."]],
Ui.Card.Sm.Filled[Ui.CardHeading["Filled"], Ui.Text.Class("mt-1")["A tint with no edge, for inline surfaces."]]
];
}Raised, for primary content.
A quieter tint for secondary panels.
The faintest tint, for light grouping.
Just an edge, over whatever's behind it.
A tint with no edge, for inline surfaces.
Sizes
The room: padding, corners and the space between the parts.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CardSizesExample : Component
{
protected override Component? Render() =>
Div.Class("grid items-start gap-6 sm:grid-cols-2")[
Ui.Card.Xs.Separated[
Ui.CardHeader[Ui.CardHeading["xs"], Ui.CardActions[Ui.Button["Edit"]]],
Ui.CardBody[Ui.Text["Compact, for dense lists and sidebars."]]
],
Ui.Card.Sm.Separated[
Ui.CardHeader[Ui.CardHeading["sm"], Ui.CardActions[Ui.Button["Edit"]]],
Ui.CardBody[Ui.Text["Tight, for small widgets and stats."]]
],
Ui.Card.Md.Separated[
Ui.CardHeader[Ui.CardHeading["md"], Ui.CardActions[Ui.Button["Edit"]]],
Ui.CardBody[Ui.Text["The default, for most content."]]
],
Ui.Card.Lg.Separated[
Ui.CardHeader[Ui.CardHeading["lg"], Ui.CardActions[Ui.Button["Edit"]]],
Ui.CardBody[Ui.Text["Roomy, for forms and settings."]]
]
];
}Compact, for dense lists and sidebars.
Tight, for small widgets and stats.
The default, for most content.
Roomy, for forms and settings.
Body
How the header, the body and the footer are set apart.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CardBodyExample : Component
{
protected override Component? Render() =>
Div.Class("grid items-start gap-6 sm:grid-cols-2 lg:grid-cols-3")[
Preferences(Ui.Card.Seamless, "Seamless"),
Preferences(Ui.Card.Inset.Soft, "Inset"),
Preferences(Ui.Card.Flush.Soft, "Flush"),
Preferences(Ui.Card.Divided, "Divided"),
Preferences(Ui.Card.Divided.Divider(Ui.CardDivider.Inset), "Divided, inset"),
Preferences(Ui.Card.Separated, "Separated")
];
private static Component Preferences(UiCard card, string body) =>
card.Key(body)[
Ui.CardHeader[Ui.CardHeading[body], Ui.CardSubheading["Choose what you hear about"]],
Ui.CardBody[Ui.Text["Product updates"], Ui.Text.Class("mt-4")["Weekly digest"], Ui.Text.Class("mt-4")["Security alerts"]],
Ui.CardFooter[Ui.Text["Changes apply at once"]]
];
}Choose what you hear about
Product updates
Weekly digest
Security alerts
Changes apply at once
Choose what you hear about
Product updates
Weekly digest
Security alerts
Changes apply at once
Choose what you hear about
Product updates
Weekly digest
Security alerts
Changes apply at once
Choose what you hear about
Product updates
Weekly digest
Security alerts
Changes apply at once
Choose what you hear about
Product updates
Weekly digest
Security alerts
Changes apply at once
Choose what you hear about
Product updates
Weekly digest
Security alerts
Changes apply at once
Bleed
Media that runs to the card's edges.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CardBleedExample : Component
{
protected override Component? Render() =>
Ui.Card.Inset.Class("max-w-sm")[
Ui.CardBody[
Ui.CardBleed[Div.Class("aspect-video w-full bg-linear-to-br from-emerald-700 to-emerald-200").Aria("hidden", "true")]
],
Ui.CardFooter[Ui.CardHeading["Morning hike"], Ui.CardSubheading["Sept 12"]]
];
}Sept 12
Header outside
A header beside the card rather than in it.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CardOutsideHeaderExample : Component
{
protected override Component? Render() =>
Div.Class("max-w-md")[
Ui.CardHeader[Ui.CardHeading.Lg["Security"], Ui.CardActions[Ui.Button["Activity log"]]],
Ui.Card[
Ui.CardHeading["Password"],
Ui.Text.Class("mt-1")["Last changed 3 months ago"]
]
];
}Last changed 3 months ago
Header inside the body
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CardNestedHeaderExample : Component
{
protected override Component? Render() =>
Ui.Card.Inset.Soft.Class("max-w-md")[
Ui.CardHeader[Ui.CardHeading["Billing"], Ui.CardSubheading["Manage your plan and payments"]],
Ui.CardBody[
Ui.CardHeader[
Ui.CardHeading["Pro plan"],
Ui.CardSubheading["$24 per month, renews Oct 12"],
Ui.CardActions[Ui.Button["Change plan"]]
],
Ui.Text["8 of 10 seats used"]
],
Ui.CardFooter[Ui.Text["Invoices are emailed to billing@acme.com"]]
];
}Manage your plan and payments
$24 per month, renews Oct 12
8 of 10 seats used
Invoices are emailed to billing@acme.com
Behaviour
What each step decides
Each value is a chain step, Ui.Card.Divided.Sm; Inset is the body treatment, so the divider is .Divider(Ui.CardDivider.Inset). A card needs none of its parts: Ui.Card[Ui.CardHeading.Lg["Are you sure?"], P["This cannot be undone."]] is padded evenly.
Step | What happens |
|---|---|
Body | How the header, body and footer are set apart: by space (Seamless, the default), a panel in from the edges (Inset), a panel out to them (Flush), lines (Divided), or tinted bands (Separated). |
Variant | The surface: raised (Default), two tints (Muted, Soft), an edge only (Outline), or a tint with no edge (Filled). |
Size | Xs, Sm, Md (the default) or Lg: the padding, the corners and the space between the parts. |
Divider | With Divided, Ui.CardDivider.Inset stops the lines at the content's edges. |
Highlight | false turns off the faint highlight inside the top edge, in light mode. |
Headers and footers
Ui.CardActions in a header centres on the heading and tucks into the corner. Ui.CardHeading takes Size (Base, Lg, Xl) and Level; without a level it is a <div>, outside the document outline.
A header or footer outside a card is a section heading above one: give it the Size of the card it sits beside. Inside a Ui.CardBody it titles a sub-section and takes none of the card's treatment.
Out to the edges
Ui.CardBleed runs media out to the card's edges: always to the sides, and to the top or bottom when it is the first or last thing, rounding only the corners it reaches. The distances are the --ui-bleed-x, --ui-bleed-top, --ui-bleed-bottom, --ui-bleed-top-radius and --ui-bleed-bottom-radius variables the card and its body set, so your own content can bleed the same way. A card also states --ui-bleed, which a table's or a carousel's Bleed() reads.
A card that is a link
There is no Href on a card. A link card is a link around a small card, as in Flux: A.Href(url)[Ui.Card.Xs.Class("hover:bg-zinc-50 dark:hover:bg-zinc-700")[…]], and nothing inside it may be a button.
Reference
Ui.Card
A container for related content, with the spacing between its parts.
Step | Takes | What it does |
|---|---|---|
.Variant(…) | Ui.CardVariantDefault Muted Soft Outline Filled Each is a step of its own too, unless an HTML tag has its name. | The card's surface. |
.Size(…) | Ui.CardSizeMd Xs Sm Lg Each is a step of its own too, unless an HTML tag has its name. | Scales the padding, the corners and the spacing. |
.Body(…) | Ui.CardBodyVariantSeamless Inset Flush Divided Separated Each is a step of its own too, unless an HTML tag has its name. | How the header, body and footer are set apart. Seamless when unset. |
.Divider(…) | Ui.CardDividerFull Inset Each is a step of its own too, unless an HTML tag has its name. | With Divided, where the lines stop. |
.Highlight() | bool | A faint highlight inside the top edge in light mode. On unless false. |
Ui.CardHeader
The heading, subheading and actions across the top.
Step | Takes | What it does |
|---|---|---|
.Size(…) | Ui.CardSizeMd Xs Sm Lg Each is a step of its own too, unless an HTML tag has its name. | Outside a card, the size of the card it sits beside. |
Ui.CardHeading
The card's title.
Step | Takes | What it does |
|---|---|---|
.Size(…) | Ui.CardHeadingSizeBase Lg Xl Each is a step of its own too, unless an HTML tag has its name. | How big it looks. |
.Level(…) | int | The heading level to render: 2 for an <h2>. |
Ui.CardSubheading
The line under the heading.
No steps of its own: what goes inside it is its content.
Ui.CardActions
Buttons at the end of a header or footer.
No steps of its own: what goes inside it is its content.
Ui.CardBody
The card's content.
No steps of its own: what goes inside it is its content.
Ui.CardFooter
The line along the bottom.
Step | Takes | What it does |
|---|---|---|
.Size(…) | Ui.CardSizeMd Xs Sm Lg Each is a step of its own too, unless an HTML tag has its name. | Outside a card, the size of the card it sits beside. |
Ui.CardBleed
Content that runs to the card's edges: an image.
No steps of its own: what goes inside it is its content.