Rask
Rask
v0.23.1-alpha.0.440

Getting started

Dark mode

Dark mode is Flux UI's: a dark class on <html>, and dark: utilities that follow it. Every Rask.Ui component is drawn for both, and the reader chooses light, dark or their system's.

Light, dark or system

Each button sets the reader's appearance in the browser. There is no C# handler, so it works on a prerendered page before the app has booted.

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

public sealed partial class DarkModeExample : Component
{
    protected override Component? Render() =>
        Div.Class("flex flex-wrap items-center gap-4")[
            Ui.ButtonGroup[
                Ui.Button.Icon(Ui.IconName.Sun).Attributes(("onclick", "Rask.appearance = 'light'"))["Light"],
                Ui.Button.Icon(Ui.IconName.Moon).Attributes(("onclick", "Rask.appearance = 'dark'"))["Dark"],
                Ui.Button.Icon(Ui.IconName.ComputerDesktop).Attributes(("onclick", "Rask.appearance = 'system'"))["System"]
            ],
            Ui.Button.Subtle.Icon(Ui.IconName.Moon).Tooltip("Toggle dark mode").Attributes(("onclick", "Rask.dark = !Rask.dark"))
        ];
}
Live result

Before the first paint

Put Ui.AppearanceScript in the root component's head assets, before the stylesheets, so a dark page starts dark:

protected override Component? HeadAssets => [Title["…"], Ui.AppearanceScript, /* stylesheets */];

The reader's appearance is light, dark or system. System is the default: it follows prefers-color-scheme while the page is open, and is stored as nothing at all. The other two are kept in localStorage under rask.appearance — .StorageKey("…") names another key. The class is put back after every redraw, and a change in another tab is followed.

Switching it

Two properties, the ones Flux calls Flux.appearance and Flux.dark:

Rask.appearance = 'light' | 'dark' | 'system'   // get or set the reader's preference
Rask.dark = true | false                        // get or set whether the page is dark right now

So a toggle is one attribute and no C# handler. That is the moon in this site's own bar:

Ui.Button.Subtle.Icon(Ui.IconName.Moon).Attributes(("onclick", "Rask.dark = !Rask.dark"))

Your own dark: utilities

The kit's import already points dark: at the class. A stylesheet of your own that does not import the kit says the same thing:

@custom-variant dark (&:where(.dark, .dark *));