Rask
Rask
v0.23.1-alpha.0.494

Components

Color picker

A colour picked from a palette, dragged out of a saturation and brightness area, or typed, for theme settings and brand colours. Its value is CSS text in the format it is set to.

Drawn and behaving as Flux UI's color picker does, measured against its live docs.

Color picker

The swatch button opens the popover; a typed colour is taken on Enter or on leaving the input.

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

public sealed partial class ColorPickerExample : Component
{
    private string _theme = "#bada55";

    protected override Component? Render() =>
        Div.Class("max-w-xs space-y-3")[
            Ui.ColorPicker.Value(_theme).OnChange(color => { _theme = color; }).Id("ui-color-picker-intro"),
            Ui.Text.Data("testid", "ui-color-picker-state")[$"Theme: {(_theme.Length == 0 ? "none" : _theme)}."]
        ];
}
Live result

Theme: #bada55.

Format

One colour written six ways. An alpha format adds an opacity slider to the popover.

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

public sealed partial class ColorPickerFormatExample : Component
{
    // One colour, written six ways: each picker writes it back in its own format.
    private const string Indigo = "rgb(99 102 241 / 0.5)";

    protected override Component? Render() =>
        Div.Class("grid max-w-xl gap-4 sm:grid-cols-2")[
            Ui.ColorPicker.Value(Indigo).Format(Ui.ColorPickerFormat.Hex),
            Ui.ColorPicker.Value(Indigo).Format(Ui.ColorPickerFormat.Hexa),
            Ui.ColorPicker.Value(Indigo).Format(Ui.ColorPickerFormat.Rgb),
            Ui.ColorPicker.Value(Indigo).Format(Ui.ColorPickerFormat.Rgba),
            Ui.ColorPicker.Value(Indigo).Format(Ui.ColorPickerFormat.Hsl),
            Ui.ColorPicker.Value(Indigo).Format(Ui.ColorPickerFormat.Hsla)
        ];
}
Live result

Sizes

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

public sealed partial class ColorPickerSizesExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs space-y-4")[
            Ui.ColorPicker.Value("#c0ffee"),
            Ui.ColorPicker.Value("#c0ffee").Sm,
            Ui.ColorPicker.Value("#c0ffee").Xs
        ];
}
Live result

Button trigger

One button that shows the colour, for a toolbar or a palette where nothing is typed.

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

public sealed partial class ColorPickerButtonExample : Component
{
    protected override Component? Render() =>
        Ui.ColorPicker.Value("#ca1ebb").Type(Ui.ColorPickerType.Button);
}
Live result

Custom swatches

Your palette in place of the 24 Tailwind colours: strings, or (value, label) pairs.

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

public sealed partial class ColorPickerSwatchesExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs space-y-4")[
            Ui.ColorPicker.Value("#ef4444").Swatches(["#ef4444", "#22c55e", "#3b82f6", "#f59e0b", "#a855f7"]),
            // With a label for each swatch, which assistive tech reads.
            Ui.ColorPicker.Value("#ef4444").Swatches([("#ef4444", "Red"), ("#22c55e", "Green"), ("#3b82f6", "Blue")])
        ];
}
Live result

No swatches

An empty list hides the palette, Flux's :swatches="false": the area, the hue slider and the input.

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

public sealed partial class ColorPickerNoSwatchesExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs")[
            Ui.ColorPicker.Value("#ef4444").Swatches([])
        ];
}
Live result

Custom layout

Children compose the popover from its parts, in any order.

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

public sealed partial class ColorPickerLayoutExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs")[
            Ui.ColorPicker.Value("#facade")[
                Div.Class("flex flex-col gap-3")[
                    Ui.ColorPickerInput.Placeholder("#000000"),
                    Ui.Separator,
                    Ui.ColorPickerArea,
                    Ui.ColorPickerSlider.Channel(Ui.ColorPickerChannel.Hue)
                ]
            ]
        ];
}
Live result

Dropper

A button that picks a colour from anywhere on the screen, there only in a browser with an EyeDropper.

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

public sealed partial class ColorPickerDropperExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs")[
            Ui.ColorPicker.Value("#dec0de").Dropper()
        ];
}
Live result

Clearable

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

public sealed partial class ColorPickerClearableExample : Component
{
    private string _color = "#deface";

    protected override Component? Render() =>
        Div.Class("max-w-xs space-y-3")[
            Ui.ColorPicker.Value(_color).OnChange(color => { _color = color; }).Clearable(),
            Ui.Text.Data("testid", "ui-color-picker-cleared")[$"Color: {(_color.Length == 0 ? "none" : _color)}."]
        ];
}
Live result

Color: #deface.

Copyable

One click copies the colour as it is written.

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

public sealed partial class ColorPickerCopyableExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs")[
            Ui.ColorPicker.Value("#0ff1ce").Copyable()
        ];
}
Live result

Disabled

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

public sealed partial class ColorPickerDisabledExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs")[
            Ui.ColorPicker.Value("#beefed").Disabled()
        ];
}
Live result

In a form

Bound in a form, the colour travels with the save, and text that is no colour holds the save back.

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

public sealed partial class ColorPickerFormExample : Component
{
    private readonly Brand _brand = new();
    private string _saved = "nothing yet";

    protected override Component? Render() =>
        Form.Model(_brand).OnSubmit(_ => { _saved = _brand.Accent; }).Class("flex max-w-xs flex-col items-start gap-3")[
            Ui.ColorPicker.Bind(() => _brand.Accent).Label("Accent").Description("Saved with the form.").Id("ui-color-picker-accent"),
            Ui.Button.Primary.Type(Ui.ButtonType.Submit)["Save"],
            Ui.Text.Data("testid", "ui-color-picker-saved")[$"Saved: {_saved}."]
        ];

    public sealed class Brand
    {
        public string Accent { get; set; } = "#6366f1";
    }
}
Live result
Saved with the form.

Saved: nothing yet.

Behaviour

Its value

The value is CSS text in Format, whatever CSS it was given in, and no colour is the empty string. A bound colour is written with the reader's next action, .Live() writes it as it is chosen, and under a pointer every change is the page's at once. Name adds a hidden input for a plain form post.

The keyboard

The swatch button, the button trigger or ArrowDown in the input opens the popover and focuses the area; Escape and a press outside close it and the focus returns.

Key
What happens
The arrows, on the areaMove the thumb by 2, and by 10 with Shift.
PageUp, PageDown, Home, End, on the areaFull and no brightness; no and full saturation.
The arrows, on a sliderStep by 1, by 10 with Shift, and by a tenth of the track with a page key.
The arrows, on the paletteWalk it eight to a row; Enter or Space picks. The palette is one tab stop.
Enter, or leaving the inputTakes a typed colour.

On a phone it is a sheet

Below sm the popover is centred over the page, which does not scroll behind it, and it keeps what is chosen until Select: Cancel, Escape and a press outside leave the colour as it was. A swatch does not wait: it is taken, and the sheet closes.

What a typed colour becomes

Hex, a CSS colour name, rgb(), hsl() and hwb() are read as CSS reads them. Flux hands every other form to the browser and reads the numbers of the colour the browser writes back as red, green and blue, so the wide-gamut functions come out as something else: oklch(0.7 0.1 200) is #0100c8. The kit reproduces it digit for digit, by the owner's decision.

Text that is no colour is refused, not put back, which is the one departure from Flux, and only in a form: a bound picker keeps #12 in the field, says "Enter a valid color." under it with the next action and holds the save. Outside a form it puts the last colour back, as Flux does.

No script of the kit's

The popover is a native modal <dialog> the button opens by command="show-modal", hung under the trigger by CSS anchor rules. The area and each track are data-rask-drag surfaces, so the thumb is under the pointer every frame; the sliders hold native range inputs for the keyboard; a press on the area leaves the focus where it was (data-rask-press-keeps-focus); the dropper shows where the browser has one (data-rask-requires); and the copy button writes the clipboard in the click (data-rask-copy). The colour maths and every key are C#.

Reference

Ui.ColorPicker

flux:color-picker

A colour from a palette, an area and sliders, or typed. Its children, when it has any, compose the popover.

Step
Takes
What it does
.Bind(…)() => a stringThe member it reads and writes: () => m.Theme. Or Value with OnChange.
.Value(…)stringThe colour as any CSS colour string, for a page that holds it itself.
.OnChange(…)a handler given the new valueRuns with the new colour, in Format.
.AfterBind(…)a handler given the new valueRuns after Bind has written the model.
.Validate(…)a validatorA rule the colour is checked by when it is written.
.Live()boolWrites the model as soon as a colour is chosen, not with the next action.
.Format(…)
Ui.ColorPickerFormat
Hex
Hexa
Rgb
Rgba
Hsl
Hsla

Each is a step of its own too, unless an HTML tag has its name.

What the colour is written as. An alpha format adds an alpha slider. Hex when unset.
.Type(…)
Ui.ColorPickerType
Input
Button

Each is a step of its own too, unless an HTML tag has its name.

An input with a swatch button, or one button showing the colour. The input when unset.
.Swatches(…)hex strings, or (value, label) pairsThe palette in place of the 24 Tailwind colours. An empty list shows none.
.Dropper()boolA button in the popover that picks a colour from the screen, where the browser has one.
.Clearable()boolA button on the input that clears the colour, while there is one.
.Copyable()boolA button on the input that copies the colour as it is written.
.Placeholder(…)stringShown while there is no colour. By format when unset: #000000 for hex.
.Size(…)
Ui.ColorPickerSize
Base
Sm
Xs

Each is a step of its own too, unless an HTML tag has its name.

How tall the trigger is. 40px when unset.
.Label(…)stringDraws a field around it, with this label and the error.
.Description(…)stringHelp text between the label and the picker.
.Name(…)stringAdds a hidden input of this name, so a plain form posts the colour.
.Disabled()boolA picker that cannot be opened or changed.
.Invalid()boolError styling the form did not ask for.

Ui.ColorPickerArea

flux:color-picker.area

The saturation and brightness area of a composed popover.

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

Ui.ColorPickerSlider

flux:color-picker.slider

The hue or the opacity slider of a composed popover.

Step
Takes
What it does
.Channel(…)
Ui.ColorPickerChannel
Hue
Alpha

Each is a step of its own too, unless an HTML tag has its name.

What the slider moves. The hue when unset.

Ui.ColorPickerInput

flux:color-picker.input

The text input of a composed popover.

Step
Takes
What it does
.Placeholder(…)stringShown while there is no colour. The picker's own when unset.

Ui.ColorPickerSwatches

flux:color-picker.swatches

The palette of a composed popover: the picker's own, or the Ui.ColorPickerSwatch children it is given.

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

Ui.ColorPickerSwatch

flux:color-picker.swatch

One colour of a palette.

Step
Takes
What it does
.Value(…)stringThe colour, as a CSS colour string: #ef4444.
.Label(…)stringWhat assistive tech calls it, and its tooltip. The value when unset.

Ui.ColorPickerDropper

flux:color-picker.dropper

The dropper button of a composed popover, there only where the browser has an EyeDropper.

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

Confirm