Rask
Rask
v0.23.1-alpha.0.478

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

CheckboxExample.cs
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."]
        ];
}
Live result

Terms not agreed yet.

Checkbox group

Related checkboxes down a column, the group bound to the list of what is ticked.

CheckboxGroupExample.cs
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)}."]
        ];
}
Live result

Notify by push, email.

With descriptions

A description sits under each checkbox's label.

CheckboxDescriptionsExample.cs
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.")
        ];
}
Live result
Receive our monthly newsletter with the latest updates and offers.
Stay informed about new features and product updates.
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.

CheckboxFieldsetExample.cs
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")
            ]
        ];
}
Live result
Languages
Choose the languages you want to support.

Check-all

One checkbox for the whole group: ticked when all are, a dash while some are.

CheckboxAllExample.cs
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)}."
            ]
        ];
}
Live result

Chosen: mara.

Checked

CheckboxCheckedExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class CheckboxCheckedExample : Component
{
    protected override Component? Render() =>
        Ui.Checkbox.Checked().Label("Enable notifications");
}
Live result

Disabled

CheckboxDisabledExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class CheckboxDisabledExample : Component
{
    protected override Component? Render() =>
        Ui.Checkbox.Disabled().Label("Read and write");
}
Live result

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.

CheckboxCardsExample.cs
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)}."]
        ];
}
Live result

Subscribed to newsletter.

Vertical cards

flex-col on the group stacks the cards everywhere.

CheckboxVerticalCardsExample.cs
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.")
        ];
}
Live result

Cards with icons

CheckboxCardIconsExample.cs
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.")
        ];
}
Live result

Custom card content

A card's children replace its label and description; Ui.CheckboxIndicator puts the box among them.

CheckboxCustomCardsExample.cs
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."]
                ]
            ]
        ];
}
Live result

Pills

Compact, rounded checkboxes that look like tags: for filters and categories.

CheckboxPillsExample.cs
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")
        ];
}
Live result

Buttons

Checkboxes drawn as a toolbar of buttons that stay pressed.

CheckboxButtonsExample.cs
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")
        ];
}
Live result

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

flux: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()boolWhether it is ticked, for a page that holds it itself.
.OnChange(…)a handler given the new valueRuns with the new state when it is pressed.
.AfterBind(…)a handler given the new valueRuns after Bind has written the model.
.Validate(…)a validatorA rule the value is checked by when it is written.
.Live()boolWrites the model as soon as it is pressed, not with the next action.
.Value(…)a value of the group's typeWhat the group's collection holds while it is ticked.
.Label(…)stringIts words, beside it.
.Description(…)stringHelp text under its label.
.Icon(…)Ui.IconName — one of 317 namesAn icon on a card or a button.
.Indeterminate()boolDraws a dash: some of what it stands for, not all.
.Disabled()boolDims it and takes it out of reach.
.Invalid()boolError styling the form did not ask for.
.Name(…)stringWhat it is posted under in a form.
.ShowValidation()boolFalse leaves the member's message to a Ui.Error placed elsewhere.
.Attributes(…)("aria-label", "Search") pairsAttributes for the <input> itself.

Ui.CheckboxGroup

flux:checkbox.group

Checkboxes over one collection of what is ticked.

Step
Takes
What it does
.Bind(…)() => a collection of TThe model's collection it reads and writes: () => m.Topics. Or Values with OnChange.
.Value(…)a collection of TWhat is ticked, for a page that holds it itself. The step is Values.
.OnChange(…)a handler given the new valueRuns with what is ticked after a press.
.AfterBind(…)a handler given the new valueRuns after Bind has written the model.
.Validate(…)a validatorA rule the value is checked by when it is written.
.Live()boolWrites the model as soon as a checkbox is pressed, not with the next action.
.Variant(…)
Ui.CheckboxGroupVariant
Default
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(…)stringDraws a field around it, with this label and the error.
.Description(…)stringHelp text between the label and the checkboxes.
.Disabled()boolTakes every checkbox in it out of reach.
.Invalid()boolError styling on every checkbox in it.
.ShowValidation()boolFalse leaves the member's message to a Ui.Error placed elsewhere.

Ui.CheckboxAll

flux:checkbox.all

Ticks or clears its whole group, and shows a dash while some are ticked.

Step
Takes
What it does
.Label(…)stringIts words, beside it.
.Description(…)stringHelp text under its label.
.Disabled()boolDims it and takes it out of reach.

Ui.CheckboxIndicator

flux:checkbox.indicator

The box, placed among a custom card's own content.

No steps of its own: what goes inside it is its content.

Confirm