Components
Checkbox
One or several options from a set. On its own a checkbox binds a bool; in a group, the group binds the collection your model declares and each checkbox says what it holds while it is ticked.
Drawn and behaving as Flux UI's checkbox does, measured against its live docs.
Checkbox
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CheckboxExample : Component
{
private bool _terms;
protected override Component? Render() =>
Div.Class("space-y-3")[
Ui.Field.Variant(Ui.FieldVariant.Inline)[
Ui.Checkbox.Checked(_terms).OnChange(value => { _terms = value; }).Id("cb-terms"),
Ui.Label["I agree to the terms and conditions"],
Ui.Error
],
Ui.Text.Data("testid", "ui-checkbox-state")[_terms ? "Terms agreed." : "Terms not agreed yet."]
];
}Terms not agreed yet.
Checkbox group
Related checkboxes down a column, the group bound to the list of what is ticked.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CheckboxGroupExample : Component
{
private ICollection<string> Notifications { get; set; } = ["push", "email"];
protected override Component? Render() =>
Div.Class("space-y-3")[
Ui.CheckboxGroup.Bind(() => Notifications).Live().Label("Notifications")[
Ui.Checkbox.Value("push").Label("Push notifications"),
Ui.Checkbox.Value("email").Label("Email"),
Ui.Checkbox.Value("app").Label("In-app alerts"),
Ui.Checkbox.Value("sms").Label("SMS")
],
Ui.Text.Data("testid", "ui-checkbox-group-state")[$"Notify by {string.Join(", ", Notifications)}."]
];
}Notify by push, email.
With descriptions
A description sits under each checkbox's label.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CheckboxDescriptionsExample : Component
{
private ICollection<string> Subscription { get; set; } = ["newsletter"];
protected override Component? Render() =>
Ui.CheckboxGroup.Bind(() => Subscription).Label("Subscription preferences")[
Ui.Checkbox.Value("newsletter").Label("Newsletter")
.Description("Receive our monthly newsletter with the latest updates and offers."),
Ui.Checkbox.Value("updates").Label("Product updates")
.Description("Stay informed about new features and product updates."),
Ui.Checkbox.Value("invitations").Label("Event invitations")
.Description("Get invitations to our exclusive events and webinars.")
];
}Horizontal fieldset
Checkboxes across a row, under a legend, each bound to a bool of its own.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CheckboxFieldsetExample : Component
{
private bool _english = true;
private bool _spanish = true;
private bool _french;
private bool _german;
protected override Component? Render() =>
Ui.Fieldset[
Ui.Legend["Languages"],
Ui.Description["Choose the languages you want to support."],
Div.Class("flex flex-wrap gap-4 *:gap-x-2")[
Ui.Checkbox.Checked(_english).OnChange(on => { _english = on; }).Label("English"),
Ui.Checkbox.Checked(_spanish).OnChange(on => { _spanish = on; }).Label("Spanish"),
Ui.Checkbox.Checked(_french).OnChange(on => { _french = on; }).Label("French"),
Ui.Checkbox.Checked(_german).OnChange(on => { _german = on; }).Label("German")
]
];
}Check-all
One checkbox for the whole group: ticked when all are, a dash while some are.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CheckboxAllExample : Component
{
private ICollection<string> People { get; set; } = ["mara"];
protected override Component? Render() =>
Div.Class("space-y-3")[
Ui.CheckboxGroup.Bind(() => People).Live().Id("cb-people")[
Ui.CheckboxAll.Label("Everyone"),
Ui.Checkbox.Value("mara").Label("Mara Lind"),
Ui.Checkbox.Value("theo").Label("Theo Brandt"),
Ui.Checkbox.Value("rosa").Label("Rosa Vidal")
],
Ui.Text.Data("testid", "ui-checkbox-all-state")[
People.Count == 0 ? "Nobody chosen." : $"Chosen: {string.Join(", ", People)}."
]
];
}Chosen: mara.
Checked
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CheckboxCheckedExample : Component
{
protected override Component? Render() =>
Ui.Checkbox.Checked().Label("Enable notifications");
}Disabled
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CheckboxDisabledExample : Component
{
protected override Component? Render() =>
Ui.Checkbox.Disabled().Label("Read and write");
}Checkbox cards
A bordered card is the checkbox: a press anywhere on it ticks it. max-sm:flex-col stacks the cards on a phone.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CheckboxCardsExample : Component
{
private ICollection<string> Subscription { get; set; } = ["newsletter"];
protected override Component? Render() =>
Div.Class("space-y-3")[
Ui.CheckboxGroup.Bind(() => Subscription).Live().Id("cb-cards").Label("Subscription preferences").Cards
.Class("max-sm:flex-col")[
Ui.Checkbox.Value("newsletter").Label("Newsletter").Description("Get the latest updates and offers."),
Ui.Checkbox.Value("updates").Label("Product updates").Description("Learn about new features and products."),
Ui.Checkbox.Value("invitations").Label("Event invitations").Description("Invitations to exclusive events.")
],
Ui.Text.Data("testid", "ui-checkbox-cards-state")[$"Subscribed to {string.Join(", ", Subscription)}."]
];
}Subscribed to newsletter.
Vertical cards
flex-col on the group stacks the cards everywhere.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CheckboxVerticalCardsExample : Component
{
private ICollection<string> Subscription { get; set; } = ["newsletter"];
protected override Component? Render() =>
Ui.CheckboxGroup.Bind(() => Subscription).Label("Subscription preferences").Cards.Class("max-w-md flex-col")[
Ui.Checkbox.Value("newsletter").Label("Newsletter").Description("Get the latest updates and offers."),
Ui.Checkbox.Value("updates").Label("Product updates").Description("Learn about new features and products."),
Ui.Checkbox.Value("invitations").Label("Event invitations").Description("Invitations to exclusive events.")
];
}Cards with icons
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CheckboxCardIconsExample : Component
{
private ICollection<string> Subscription { get; set; } = ["newsletter"];
protected override Component? Render() =>
Ui.CheckboxGroup.Bind(() => Subscription).Label("Subscription preferences").Cards.Class("max-w-md flex-col")[
Ui.Checkbox.Value("newsletter").Icon(Ui.IconName.Newspaper).Label("Newsletter")
.Description("Get the latest updates and offers."),
Ui.Checkbox.Value("updates").Icon(Ui.IconName.Cube).Label("Product updates")
.Description("Learn about new features and products."),
Ui.Checkbox.Value("invitations").Icon(Ui.IconName.Calendar).Label("Event invitations")
.Description("Invitations to exclusive events.")
];
}Custom card content
A card's children replace its label and description; Ui.CheckboxIndicator puts the box among them.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CheckboxCustomCardsExample : Component
{
private ICollection<string> Subscription { get; set; } = ["newsletter"];
protected override Component? Render() =>
Ui.CheckboxGroup.Bind(() => Subscription).Label("Subscription preferences").Cards.Class("max-w-md flex-col")[
Ui.Checkbox.Value("newsletter")[
Ui.CheckboxIndicator,
Div.Class("flex-1")[
Ui.Heading.Class("leading-4")["Newsletter"],
Ui.Text.Sm.Class("mt-2")["Get the latest updates and offers."]
]
],
Ui.Checkbox.Value("updates")[
Ui.CheckboxIndicator,
Div.Class("flex-1")[
Ui.Heading.Class("leading-4")["Product updates"],
Ui.Text.Sm.Class("mt-2")["Learn about new features and products."]
]
],
Ui.Checkbox.Value("invitations")[
Ui.CheckboxIndicator,
Div.Class("flex-1")[
Ui.Heading.Class("leading-4")["Event invitations"],
Ui.Text.Sm.Class("mt-2")["Invitations to exclusive events."]
]
]
];
}Pills
Compact, rounded checkboxes that look like tags: for filters and categories.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CheckboxPillsExample : Component
{
private ICollection<string> Categories { get; set; } = ["fantasy", "science-fiction", "thriller"];
protected override Component? Render() =>
Ui.CheckboxGroup.Bind(() => Categories).Label("Categories").Pills[
Ui.Checkbox.Value("fantasy").Label("Fantasy"),
Ui.Checkbox.Value("science-fiction").Label("Science fiction"),
Ui.Checkbox.Value("horror").Label("Horror"),
Ui.Checkbox.Value("mystery").Label("Mystery"),
Ui.Checkbox.Value("romance").Label("Romance"),
Ui.Checkbox.Value("autobiography").Label("Autobiography"),
Ui.Checkbox.Value("thriller").Label("Thriller"),
Ui.Checkbox.Value("poetry").Label("Poetry"),
Ui.Checkbox.Value("children").Label("Children")
];
}Buttons
Checkboxes drawn as a toolbar of buttons that stay pressed.
namespace Rask.Site.Features.UiDocs.Examples;
public sealed partial class CheckboxButtonsExample : Component
{
private ICollection<string> Features { get; set; } = ["notifications", "analytics"];
protected override Component? Render() =>
Ui.CheckboxGroup.Bind(() => Features).Label("Features").Buttons.Class("flex-wrap")[
Ui.Checkbox.Value("notifications").Icon(Ui.IconName.Bell).Label("Notifications"),
Ui.Checkbox.Value("analytics").Icon(Ui.IconName.ChartBar).Label("Analytics"),
Ui.Checkbox.Value("backups").Icon(Ui.IconName.CloudArrowUp).Label("Backups")
];
}Behaviour
The group holds the value
On its own a checkbox binds a bool, or a bool? whose null draws the dash: Ui.Checkbox.Bind(() => m.Agreed), or Checked(on).OnChange(v => on = v) for one the page owns. A checkbox inside a Ui.CheckboxGroup binds nothing itself: the group binds the collection (a List<T>, a HashSet<T>, an array) and each checkbox's Value is what the collection holds while it is ticked, written in the order the checkboxes are written. The group's controlled opening is Values.
Cards, Pills and Buttons draw the same checkboxes differently. A choice's Label, Description and Icon are drawn on the card, the pill or the button, and a card's children replace them.
The check-all
Ui.CheckboxAll sits among a group's checkboxes, anywhere in its markup. It is ticked when all of them are, shows a dash (data-indeterminate, as Flux marks it) while some are, and a press ticks them all unless they all are already. A disabled checkbox keeps what it has. Ui.Checkbox.Indeterminate() draws the same dash on a checkbox of your own.
Real inputs, no script
Every root (data-ui-checkbox, and data-ui-checkbox-cards, -pills or -buttons) is a <label> around an <input type="checkbox"> that is out of sight, never hidden. The tick reads the input's own :checked, so the space bar, a click on the label and the form post are the browser's, however the checkbox is drawn. Name is what it is posted under, and Attributes(("aria-label", "Select row")) forwards anything else to the input.
Validation
A bound checkbox or group is invalid on its own while its form holds a message for the member: aria-invalid, data-invalid, and aria-describedby naming the field's Ui.Error, which Label draws with it. Invalid() says so by hand. Flux's pages show no invalid checkbox to measure, so the unticked box takes the red border Flux's input has.
Reference
Ui.Checkbox
A checkbox in a label: a bool on its own, a value in a group. Its children make a custom card.
Step | Takes | What it does |
|---|---|---|
.Bind(…) | () => a bool or a bool? | The model's flag it reads and writes: () => m.Agreed. Or Checked with OnChange. |
.Checked() | bool | Whether it is ticked, for a page that holds it itself. |
.OnChange(…) | a handler given the new value | Runs with the new state when it is pressed. |
.AfterBind(…) | a handler given the new value | Runs after Bind has written the model. |
.Validate(…) | a validator | A rule the value is checked by when it is written. |
.Live() | bool | Writes the model as soon as it is pressed, not with the next action. |
.Value(…) | a value of the group's type | What the group's collection holds while it is ticked. |
.Label(…) | string | Its words, beside it. |
.Description(…) | string | Help text under its label. |
.Icon(…) | Ui.IconName — one of 317 names | An icon on a card or a button. |
.Indeterminate() | bool | Draws a dash: some of what it stands for, not all. |
.Disabled() | bool | Dims it and takes it out of reach. |
.Invalid() | bool | Error styling the form did not ask for. |
.Name(…) | string | What it is posted under in a form. |
.ShowValidation() | bool | False leaves the member's message to a Ui.Error placed elsewhere. |
.Attributes(…) | ("aria-label", "Search") pairs | Attributes for the <input> itself. |
Ui.CheckboxGroup
Checkboxes over one collection of what is ticked.
Step | Takes | What it does |
|---|---|---|
.Bind(…) | () => a collection of T | The model's collection it reads and writes: () => m.Topics. Or Values with OnChange. |
.Value(…) | a collection of T | What is ticked, for a page that holds it itself. The step is Values. |
.OnChange(…) | a handler given the new value | Runs with what is ticked after a press. |
.AfterBind(…) | a handler given the new value | Runs after Bind has written the model. |
.Validate(…) | a validator | A rule the value is checked by when it is written. |
.Live() | bool | Writes the model as soon as a checkbox is pressed, not with the next action. |
.Variant(…) | Ui.CheckboxGroupVariantDefault Cards Pills Buttons Each is a step of its own too, unless an HTML tag has its name. | How the checkboxes are drawn. A column when unset. |
.Label(…) | string | Draws a field around it, with this label and the error. |
.Description(…) | string | Help text between the label and the checkboxes. |
.Disabled() | bool | Takes every checkbox in it out of reach. |
.Invalid() | bool | Error styling on every checkbox in it. |
.ShowValidation() | bool | False leaves the member's message to a Ui.Error placed elsewhere. |
Ui.CheckboxAll
Ticks or clears its whole group, and shows a dash while some are ticked.
Step | Takes | What it does |
|---|---|---|
.Label(…) | string | Its words, beside it. |
.Description(…) | string | Help text under its label. |
.Disabled() | bool | Dims it and takes it out of reach. |
Ui.CheckboxIndicator
The box, placed among a custom card's own content.
No steps of its own: what goes inside it is its content.