BitColorPicker is the panel a color is chosen on: drag the saturation-brightness area for the shade, the hue slider for the color it is a shade of, and the alpha slider for how much of it shows through. The exact value can be typed into the text fields instead - in hexadecimal, RGB, HSL or HSV, with an optional button that moves between them - picked in one click from a palette of presets, or sampled from anywhere on the screen with the browser's own eyedropper. The value is read and written in whatever notation it arrives in - hexadecimal in three, four, six or eight digits, rgb(), hsl(), hwb(), the perceptual oklab() and oklch() modern design tokens are written in, a color keyword like 'tomato', plus hsv() for the model the picker itself is built on - or pinned to one with Format, with a matching alpha-carrying notation for when a single string has to survive a transparent color. Everything on it is reachable from the keyboard, including the two-dimensional area, every part of it announces the color by name rather than by channel numbers, and the whole panel mirrors in right-to-left.

Usage


Basic

<BitColorPicker />

<BitColorPicker Label="Brand color" />

<BitColorPicker>
    <LabelTemplate>
        <BitIcon IconName="@BitIconName.Color" /> <b>Accent color</b>
    </LabelTemplate>
</BitColorPicker>

<BitColorPicker IsEnabled="false" Color="#B34D4D" />

<BitColorPicker ReadOnly Color="#4D7FB3" />
On its own the BitColorPicker keeps its own state with no binding or event handler involved, starting on opaque white. Label names the panel - and names it to a screen reader too, through aria-labelledby rather than a label element, since a panel of many controls has no single input a for could point at - while LabelTemplate takes markup where a string will not do. Disabling it greys the whole panel out and takes it out of the interaction entirely. ReadOnly is the other half of that: the color is still shown at full contrast, but nothing about it can be changed - the mode to reach for when the picker is displaying a color someone else chose.

Basic:

Label:
Brand color

LabelTemplate:
Accent color

Disabled:

ReadOnly:

Alpha & Preview

<BitColorPicker ShowAlphaSlider ShowPreview @bind-Color="alphaColor" @bind-Alpha="alphaValue" />
<div>Color: @alphaColor &nbsp; Alpha: @alphaValue</div>

<BitColorPicker ShowPreview @bind-Color="previewColor" />
<div>Color: @previewColor</div>
@code {
    private string alphaColor = "#4D8CB3";
    private double alphaValue = 0.5;
    private string previewColor = "#5B8C5A";
}
                    
ShowAlphaSlider adds the transparency track under the hue slider, and ShowPreview adds the swatch beside them. Both are drawn over a checkerboard, so a half-transparent color reads as half-transparent rather than as a paler solid - which is the whole point of showing it. The alpha itself is tracked either way and is always readable through the Alpha parameter; the slider only decides whether the user gets to change it.

Alpha slider and preview:

Preview only:

Inputs

<BitColorPicker ShowInputs ShowPreview @bind-Color="inputsColor" />
<div>Color: @inputsColor</div>

<BitColorPicker ShowInputs ShowPreview ShowAlphaSlider
                Format="BitColorFormat.HexAlpha"
                @bind-Color="inputsAlphaColor" />
<div>Color: @inputsAlphaColor</div>
@code {
    private string inputsColor = "#B3804D";
    private string inputsAlphaColor = "#4DB39980";
}
                    
ShowInputs adds the hexadecimal and Red-Green-Blue text fields, which is how an exact color is entered - or read off - without hunting for it on the gradient. Each field commits when it is left or when Enter is pressed, so the picker does not jump around after every keystroke, and a value that is not a color is simply refused and replaced by the current one. The hexadecimal field grows to eight digits once the alpha slider is on, and gains its own percentage field beside the channels.

Hex and RGB:

With alpha (eight-digit hex and an A% field):

Input modes

<BitColorPicker ShowInputs ShowPreview ShowInputsModeSwitch
                @bind-InputsMode="inputsMode" @bind-Color="inputsModeColor" />
<div>Mode: @inputsMode &nbsp; Color: @inputsModeColor</div>

<BitColorPicker ShowInputs ShowPreview
                InputsMode="BitColorInputsMode.Hsl"
                @bind-Color="hslInputsColor" />
<div>Color: @hslInputsColor</div>

<BitColorPicker ShowInputs ShowPreview
                InputsMode="BitColorInputsMode.Hex"
                @bind-Color="hexInputsColor" />
<div>Color: @hexInputsColor</div>
@code {
    private BitColorInputsMode inputsMode = BitColorInputsMode.HexRgb;
    private string inputsModeColor = "#B34D6B";
    private string hslInputsColor = "hsl(150,45%,45%)";
    private string hexInputsColor = "#4D6BB3";
}
                    
InputsMode decides which channels the text fields are written in: the hexadecimal field with the Red-Green-Blue channels beside it, either of those on its own, or the hue-saturation-lightness and hue-saturation-brightness triplets - the model the picker itself is driven in. It is about how the color is typed, not how it is published: a picker edited in HSL still answers in whatever Format says. ShowInputsModeSwitch hands that choice to the user with a button that moves the fields on to the next set, so someone who thinks in hue and lightness is not made to translate it into RGB first, and @bind-InputsMode follows them there. Because the switch only changes which numbers the color is being read as, it keeps working on a read-only picker.

The user picks the model (try the button at the end of the row):

Fixed to HSL:

Hexadecimal alone:

Presets

<BitColorPicker ShowPreview Presets="brandPresets" @bind-Color="presetColor" />
<div>Color: @presetColor</div>

<BitColorPicker ShowPreview ShowAlphaSlider
                Presets="alphaPresets"
                Format="BitColorFormat.Rgba"
                @bind-Color="alphaPresetColor" />
<div>Color: @alphaPresetColor</div>

<BitColorPicker ShowPreview Presets="rampPresets" PresetsPerRow="5" @bind-Color="rampPresetColor" />
<div>Color: @rampPresetColor</div>
@code {
    private static readonly string[] brandPresets =
    [
        "#E24A4A", "#E2934A", "#E2D24A", "#7EE24A", "#4AE2C0",
        "#4A9BE2", "#7E4AE2", "#E24AC0", "#FFFFFF", "#8A8886", "#201F1E"
    ];
    private string presetColor = "#4A9BE2";
    
    private static readonly string[] alphaPresets =
    [
        "rgba(74,155,226,1)", "rgba(74,155,226,0.75)", "rgba(74,155,226,0.5)", "rgba(74,155,226,0.25)", "transparent"
    ];
    private string alphaPresetColor = "rgba(74,155,226,0.5)";
    
    private static readonly string[] rampPresets =
    [
        "#FDE7E7", "#F7B9B9", "#EE8080", "#E24A4A", "#B02F2F",
        "#E7F0FB", "#B9D3F2", "#80B0E8", "#4A9BE2", "#2F6BB0"
    ];
    private string rampPresetColor = "#4A9BE2";
}
                    
Presets puts a palette of one-click swatches under the picker, which is what turns "pick any color" into "pick one of ours" without giving up the gradient behind it. Each preset is written in any of the notations the Color parameter accepts, and the swatch matching the current color is marked with a ring. A preset that carries its own alpha applies it too, so the same hue can be offered at several transparencies; one that does not keeps whatever transparency is already dialled in - and transparent is a color like any other, which is how a palette offers "no color" at all. PresetsPerRow lays the swatches out on a grid instead of letting them wrap, which is what keeps a palette meant to be read in columns - a hue per column, a shade per row - in the arrangement it was written in. The palette is a single tab stop, walked with the arrow keys - Home and End jump to its ends, and the vertical arrows move a row at a time once PresetsPerRow says how long a row is - so a thirty-color palette does not put thirty tab stops between the picker and whatever comes after it. Tabbing in lands on the swatch the picker is already on.

Brand palette:

The same hue at four transparencies, plus "no color":

A shade ramp, five to a row:

Eye dropper

<BitColorPicker ShowEyeDropper ShowPreview ShowInputs @bind-Color="eyeDropperColor" />
<div>Color: @eyeDropperColor</div>
@code {
    private string eyeDropperColor = "#5B8C5A";
}
                    
ShowEyeDropper adds the button that opens the browser's own eyedropper and samples a color from anywhere on the screen - including outside the browser window. It is a Chromium-only browser feature, so the button is only rendered where the browser actually provides one and the picker never offers a control that cannot work. Dismissing the eyedropper with Escape leaves the color exactly where it was.

Click the eyedropper, then click anywhere on the screen:

Contrast

<BitColorPicker ShowContrast ShowInputs ShowPreview
                ContrastColor="@contrastBackground"
                @bind-Color="contrastColor" />
<div>@contrastColor on @contrastBackground</div>

<BitColorPicker ShowPreview ShowInputs @bind-Color="contrastBackground" />

<BitColorPicker ShowContrast ShowAlphaSlider ShowPreview
                ContrastColor="#1B1A19"
                Format="BitColorFormat.Rgba"
                @bind-Color="contrastOnDarkColor" />
<div>Color: @contrastOnDarkColor</div>
@code {
    private string contrastColor = "#767676";
    private string contrastBackground = "#FFFFFF";
    private string contrastOnDarkColor = "rgba(122,200,255,1)";
}
                    
ShowContrast adds the readout that answers the question a color is usually being picked to settle: can this be read? It measures the picked color against ContrastColor - the background it will be read on, white unless you say otherwise, in any of the notations Color accepts - and reports the WCAG 2 ratio along with whether it clears the bar for normal text (4.5:1) and for large text (3:1). A semi-transparent color is composited onto the background first, since a ratio taken against a color the eye never sees would answer the wrong question. Both bars are shown because a color that is fine for a heading is not necessarily fine for body copy, and each verdict carries a mark as well as a color - a pass marked only in green would be exactly the distinction this readout exists to help someone avoid making.

Text color against a page background:
4.54:1 AA AA Large

Pick the background it is read on:

Against a dark surface, with transparency in play:
9.54:1 AA AA Large

Format

<BitColorPicker ShowAlphaSlider ShowPreview Format="selectedFormat" @bind-Color="formatColor" />
<div>Color: @formatColor</div>

<BitChoiceGroup Horizontal
                Label="Format"
                @bind-Value="selectedFormat"
                TItem="BitChoiceGroupOption<BitColorFormat>" TValue="BitColorFormat">
    <BitChoiceGroupOption Text="Hex" Value="BitColorFormat.Hex" />
    <BitChoiceGroupOption Text="HexAlpha" Value="BitColorFormat.HexAlpha" />
    <BitChoiceGroupOption Text="Rgb" Value="BitColorFormat.Rgb" />
    <BitChoiceGroupOption Text="Rgba" Value="BitColorFormat.Rgba" />
    <BitChoiceGroupOption Text="Hsl" Value="BitColorFormat.Hsl" />
    <BitChoiceGroupOption Text="Hsla" Value="BitColorFormat.Hsla" />
    <BitChoiceGroupOption Text="Hsv" Value="BitColorFormat.Hsv" />
    <BitChoiceGroupOption Text="Hsva" Value="BitColorFormat.Hsva" />
    <BitChoiceGroupOption Text="Hwb" Value="BitColorFormat.Hwb" />
    <BitChoiceGroupOption Text="Hwba" Value="BitColorFormat.Hwba" />
    <BitChoiceGroupOption Text="Oklab" Value="BitColorFormat.Oklab" />
    <BitChoiceGroupOption Text="Oklaba" Value="BitColorFormat.Oklaba" />
    <BitChoiceGroupOption Text="Oklch" Value="BitColorFormat.Oklch" />
    <BitChoiceGroupOption Text="Oklcha" Value="BitColorFormat.Oklcha" />
</BitChoiceGroup>
@code {
    private BitColorFormat selectedFormat = BitColorFormat.Hex;
    private string formatColor = "#B34D8C";
}
                    
Left unset, the picker answers in the same notation it was given: a hexadecimal binding stays hexadecimal, an rgb() one stays rgb(). Format pins it to one instead, which matters when the value is going somewhere with its own expectations - a stylesheet variable, an API, a database column. Every notation has an alpha-carrying twin (HexAlpha, Rgba, Hsla, Hsva, Hwba, Oklaba, Oklcha): the plain ones drop the transparency from the string while the twins fold it in, which is what a single bound value needs to survive a semi-transparent color. Hwb is the "hue plus how much white and black" model, and Oklab and Oklch are the perceptually uniform pair modern design tokens are increasingly written in - a Tailwind palette is a list of oklch(). Both are read as well as written, so a token can be handed straight to the picker. Note that Hsv is the model the picker is actually built on, but unlike the others it is not a notation any browser understands.


Format

Binding

<BitColorPicker Color="oneWayColor" ShowPreview />
@foreach (var (label, color) in oneWayOptions)
{
    <BitButton OnClick="() => oneWayColor = color">@label</BitButton>
}

<BitColorPicker @bind-Color="twoWayColor" @bind-Alpha="twoWayAlpha" ShowAlphaSlider ShowPreview />
<BitTextField Label="Enter a color" @bind-Value="twoWayColor" Style="width: 220px;" />
<div>Alpha: @twoWayAlpha</div>
@code {
    private readonly (string Label, string Color)[] oneWayOptions =
    [
        ("Red", "#E24A4A"), ("Green", "#4AE27E"), ("Blue", "#4A7FE2")
    ];
    private string oneWayColor = "#E24A4A";
    private string twoWayColor = "#4A9BE2";
    private double twoWayAlpha = 1;
}
                    
A one-way Color leaves the page in charge of the color - the buttons below drive it, and dragging the gradient moves the picker without the page ever hearing about it, so the next color the page sets takes it straight back. Pair it with ReadOnly when the picker is only meant to display. @bind-Color completes the circuit in both directions, which is why the text field and the picker below stay in step whichever one is used. That text field is also the quickest way to see how forgiving the parser is: three-, four-, six- and eight-digit hexadecimal, rgb() and rgba(), hsl() and hsla(), hsv(), hwb(), oklab() and oklch(), color(srgb ...), the modern space-separated syntax with a slashed alpha, any CSS color keyword, and transparent are all understood, and anything it cannot read leaves the picker where it was rather than throwing - which is what lets a half-typed color be bound straight from a text field. @bind-Alpha is the separate binding for the transparency, and a color string that carries its own alpha overrides it.

One-way:

Two-way (try 'tomato', '#0f8', 'rgb(255 128 0 / 40%)', 'hwb(280 10% 20%)', 'oklch(0.7 0.18 200)'):

Events

<BitColorPicker ShowAlphaSlider ShowPreview
                OnChange="HandleOnChange"
                OnChangeEnd="HandleOnChangeEnd" />
<div>OnChange: @changeCount times, last @changedColor</div>
<div>OnChangeEnd: @changeEndCount times, last @changedHex / @changedRgba</div>
@code {
    private int changeCount;
    private int changeEndCount;
    private string? changedColor;
    private string? changedHex;
    private string? changedRgba;
    
    private void HandleOnChange(BitColorChangeEventArgs args)
    {
        changeCount++;
        changedColor = args.Color;
    }
    
    private void HandleOnChangeEnd(BitColorChangeEventArgs args)
    {
        changeEndCount++;
        changedHex = args.Hex;
        changedRgba = args.Rgba;
    }
}
                    
OnChange fires on every step of a drag, which is what keeps a live preview in step with the pointer. OnChangeEnd fires once, when the gesture is over: the drag ends, the slider is released, a text field is committed, a preset is picked. That is the one to hang expensive work off - saving, recoloring a document, a network call - since the counters below show just how much more often the first one runs. Both hand over a BitColorChangeEventArgs carrying the color in every notation at once - Hex, HexAlpha, Rgb, Rgba, the Hsl, Hsv, Hwb and Oklch tuples, and the ColorDescription that says it in words - so a handler that needs the hex does not have to convert the rgb back.

Public API

<BitColorPicker @ref="colorPickerRef" @bind-Color="boundColor" ShowAlphaSlider ShowPreview />
<div>Color: @boundColor</div>
<div>ColorDescription: @colorPickerRef?.ColorDescription</div>
<div>Hex: @colorPickerRef?.Hex</div>
<div>HexAlpha: @colorPickerRef?.HexAlpha</div>
<div>Rgb: @colorPickerRef?.Rgb</div>
<div>Rgba: @colorPickerRef?.Rgba</div>
<div>Hsl: @colorPickerRef?.Hsl</div>
<div>Hsv: @colorPickerRef?.Hsv</div>
<div>Hwb: @colorPickerRef?.Hwb</div>
<div>Oklch: @colorPickerRef?.Oklch</div>
@code {
    private string boundColor = "#B3B34D";
    private BitColorPicker? colorPickerRef;
}
                    
A @ref to the picker exposes the current color in every notation without going through the binding: Hex and HexAlpha, Rgb and Rgba, and the Hsl, Hsv, Hwb and Oklch tuples for when the channels are wanted as numbers rather than as a string. ColorDescription is the color said in words - "light vibrant blue" - which is what the picker announces to a screen reader and what a page usually wants when it has to name the color in text. They all describe the color the picker is on, whatever Format the bound value happens to be written in.

Accessibility

<BitColorPicker ShowAlphaSlider ShowInputs ShowPreview
                AriaLabel="Choose the brand color"
                @bind-Color="accessibilityColor" />
<div>Color: @accessibilityColor</div>
@code {
    private string accessibilityColor = "#4DB3B3";
}
                    
Every part of the picker is a tab stop of its own, and the saturation-brightness area is the interesting one: a two-dimensional control, which no ARIA role covers, exposed as a slider over the saturation and named a 2D slider so the arrangement is announced. Its value text names the color and then spells it out - "light vibrant green, Saturation 75%, Brightness 80%, #5CCC33" - because a channel triplet is three numbers nobody can picture, while the name says at once which color the area has landed on. The panel names itself the same way, and so does every preset swatch, so a palette is a list of colors rather than a list of hexadecimal strings read out digit by digit. ArrowLeft and ArrowRight move the saturation by one percent, ArrowUp and ArrowDown the brightness; holding Shift, or using PageUp and PageDown which need no modifier, moves ten at a time, and Home and End jump to the ends of the saturation axis. The horizontal arrows follow the reading direction, so they swap in right-to-left. The hue and alpha tracks are native range inputs and answer to the whole keyboard contract of a slider for free. AriaLabel names the panel as a whole, Label names it through the text it renders, and a picker given neither describes the color it is currently on. AutoFocus puts the focus on the gradient as soon as the picker renders, which is what a picker opened as the answer to a question - inside a popover, a dialog, a toolbar - usually wants.

Tab to the gradient, then use the arrow, Page, Home and End keys:

External Icons

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css" />

<BitColorPicker ShowEyeDropper EyeDropperIconName="@BitIconName.Color" />

<BitColorPicker ShowEyeDropper EyeDropperIcon="@BitIconInfo.Fa("solid eye-dropper")" />

<BitColorPicker ShowEyeDropper EyeDropperIcon="@BitIconInfo.Bi("eyedropper")" />
EyeDropperIconName replaces the built-in glyph of the eyedropper button with another one from the bit icon set, and EyeDropperIcon takes a BitIconInfo instead, which is how an icon from an external library is used. BitIconInfo.Fa and BitIconInfo.Bi build the class names for FontAwesome and Bootstrap Icons, BitIconInfo.Css takes whatever classes you hand it, and a plain string works too; the BitIconInfo wins when both are set. Remember to reference the stylesheet of the icon library itself. The buttons below only appear on browsers that provide an eyedropper.


bit icon set:

FontAwesome:

Bootstrap:

Size

<BitColorPicker Size="BitSize.Small" ShowAlphaSlider ShowPreview @bind-Color="smallColor" />

<BitColorPicker Size="BitSize.Medium" ShowAlphaSlider ShowPreview @bind-Color="mediumColor" />

<BitColorPicker Size="BitSize.Large" ShowAlphaSlider ShowPreview @bind-Color="largeColor" />
@code {
    private string smallColor = "#C25E5E";
    private string mediumColor = "#5EC27A";
    private string largeColor = "#5E7AC2";
}
                    
Size scales the whole panel at once - the gradient, the tracks, the thumbs and the preview - from the Small that fits inside a narrow popover to the Large that carries a color asked as the main question on a page. Medium is the default. A larger size also means a larger gradient, which is the difference between picking a shade and approximating one.

Small:

Medium:

Large:

Style & Class

<style>
    .custom-class {
        width: 100px;
        height: 250px;
    }

    .custom-field {
        color: blueviolet;
        border-color: blueviolet;
    }

    .custom-preset {
        border-radius: 50%;
    }

    .custom-preset-selected {
        --bit-clp-prt-sel-clr: blueviolet;
    }
</style>


<BitColorPicker ShowAlphaSlider Style="width: 230px; height: 150px;" />

<BitColorPicker ShowAlphaSlider Class="custom-class" />

<BitColorPicker ShowAlphaSlider ShowPreview ShowInputs
                Styles="@(new() { SaturationPicker = "border-radius: 1rem;",
                                  SaturationThumb = "width: 1.5rem; height: 1.5rem;",
                                  Preview = "border-radius: 50%;" })" />

<BitColorPicker ShowAlphaSlider ShowInputs Presets="brandPresets"
                Classes="@(new() { FieldInput = "custom-field",
                                   Preset = "custom-preset",
                                   SelectedPreset = "custom-preset-selected" })" />
Style and Class reach the root element of the picker, which is where its overall size and framing live - note that the panel's height is the sum of its rows, so a fixed height shrinks the gradient rather than the controls. Styles and Classes go a level deeper and address the parts by name - among them Root, SaturationPicker, SaturationThumb, Sliders, HueSlider, AlphaSlider, Preview, Inputs, FieldInput, InputsModeSwitch, Label, Contrast, Preset and SelectedPreset - so the gradient, the tracks and the text fields can each be restyled without leaving the component. A swatch reshaped through Preset takes its selection ring with it, and the colors of that ring are read from the --bit-clp-prt-sel-clr and --bit-clp-prt-sel-shd variables, so SelectedPreset can recolor the mark without redrawing it.

Component's Style & Class:



Styles & Classes:

RTL

<BitColorPicker Dir="BitDir.Rtl" ShowAlphaSlider ShowPreview ShowInputs
                Presets="brandPresets" @bind-Color="rtlColor" />
<div>@rtlColor</div>
Setting Dir to Rtl mirrors the whole panel: the saturation axis runs from the right edge outwards, the hue and alpha tracks reverse along with the native sliders that sit on them - so the fully transparent end stays under the position the thumb calls zero - the thumbs are corrected to stay centred on their color, and the horizontal arrow keys swap so that ArrowLeft still means "more saturated". The text fields and the presets flow right-to-left with everything else.

API

BitColorPicker parameters

Name Type Default value Description
Alpha double 1 Indicates the Alpha value, from 0 (fully transparent) to 1 (fully opaque). The alpha is tracked whether or not ShowAlphaSlider renders a control for it, and a color string that carries its own alpha overrides this parameter.
AutoFocus bool false Whether the saturation-brightness area takes the focus on the first render.
Classes BitColorPickerClassStyles? null Custom CSS classes for different parts of the BitColorPicker.
Color string rgb(255,255,255) String describing the color. Hexadecimal in three, four, six or eight digits, rgb() and rgba(), hsl() and hsla(), hwb(), lab() and lch(), oklab() and oklch(), color(srgb ...), a CSS color keyword such as "tomato", and transparent are all understood, in both the comma-separated and the modern space-separated syntax, as are hsv() and hsva(), which are not CSS notations but the model the picker itself is built on.
ContrastColor string? null The color the contrast readout measures the picked color against - the background it is going to be read on. It accepts any of the notations Color does, and defaults to white.
EyeDropperIcon BitIconInfo? null The icon of the eye dropper button, using custom CSS classes for external icon libraries. Takes precedence over EyeDropperIconName when both are set.
EyeDropperIconName string? null Custom icon name for the eye dropper button. If unset, default will be the Eyedropper icon.
Format BitColorFormat? null The notation the color value is written in, CSS or the non-CSS hsv() and hsva(). When left unset the picker answers in the same notation the Color arrived in.
InputsMode BitColorInputsMode BitColorInputsMode.HexRgb Which channels the text fields are written in. It decides how the color is typed, not how it is published - a picker edited in HSL still answers in whatever Format says.
InputsModeSwitchIcon BitIconInfo? null The icon of the inputs mode switch button, using custom CSS classes for external icon libraries. Takes precedence over InputsModeSwitchIconName when both are set.
InputsModeSwitchIconName string? null Custom icon name for the inputs mode switch button. If unset, default will be the Sort icon.
Label string? null The text that names the picker. It is not a label element: with no single input to point a "for" at, one would label nothing, so the panel is named through aria-labelledby instead.
LabelTemplate RenderFragment? null Custom markup in place of the plain Label text, for when the name needs more than a string.
OnChange EventCallback<BitColorChangeEventArgs> Callback for when the value changed. It fires on every step of a drag.
OnChangeEnd EventCallback<BitColorChangeEventArgs> Callback for when the user finishes changing the value: the drag ends, the slider is released, a text field is committed, or a preset is picked.
Presets IEnumerable<string>? null The colors offered as a row of one-click swatches under the picker, in any of the notations the Color parameter accepts. A swatch that carries its own alpha applies that alpha too.
PresetsPerRow int? null How many preset swatches are laid out per row. Left unset they simply wrap; setting it lays them out on a grid instead, which keeps a palette meant to be read in columns in the arrangement it was written in.
ReadOnly bool false Makes the color picker read-only: the value is still shown at full contrast, but nothing about it can be changed.
ShowAlphaSlider bool false Whether to show a slider for editing alpha value.
ShowContrast bool false Whether to show the contrast readout: how far the picked color stands from the ContrastColor it will be read on, and whether that clears the WCAG bar for text.
ShowEyeDropper bool false Whether to show the button that opens the browser's eyedropper to sample a color from anywhere on the screen. The button is only rendered where the browser actually provides one.
ShowInputs bool false Whether to show the hexadecimal and Red-Green-Blue text fields, which is how an exact color is entered or read off without hunting for it on the gradient.
ShowInputsModeSwitch bool false Whether to show the button that moves the text fields from one set of channels to the next, so the user can type the color in whichever model they are thinking in.
ShowPreview bool false Whether to show color preview box.
Size BitSize? null The size of the color picker.
Styles BitColorPickerClassStyles? null Custom CSS styles for different parts of the BitColorPicker.

BitComponentBase parameters

Name Type Default value Description
AriaLabel string? null Gets or sets the accessible label for the component, used by assistive technologies.
Class string? null Gets or sets the CSS class name(s) to apply to the rendered element.
Dir BitDir? null Gets or sets the text directionality for the component's content.
ForceAnimation bool false Gets or sets a value indicating whether the component's animations play at their full duration even when reduced motion is requested.
HtmlAttributes Dictionary<string, object> new Dictionary<string, object>() Captures additional HTML attributes to be applied to the rendered element, in addition to the component's parameters.
Id string? null Gets or sets the unique identifier for the component's root element.
IsEnabled bool true Gets or sets a value indicating whether the component is enabled and can respond to user interaction.
Style string? null Gets or sets the CSS style string to apply to the rendered element.
TabIndex string? null Gets or sets the tab order index for the component when navigating with the keyboard.
Visibility BitVisibility BitVisibility.Visible Gets or sets the visibility state (visible, hidden, or collapsed) of the component.

BitComponentBase public members

Name Type Default value Description
UniqueId Guid Guid.NewGuid() Gets the readonly unique identifier for the component's root element, assigned when the component instance is constructed.
RootElement ElementReference Gets the reference to the root HTML element associated with this component.

BitColorChangeEventArgs properties

Describes the color the picker has just moved to, in every notation at once.

Name Type Default value Description
Color string? null The main color value of the changed color in the same format as the Color parameter of the ColorPicker.
Alpha double 0 The alpha value of the changed color, from 0 (fully transparent) to 1 (fully opaque).
Hex string? null The changed color in six-digit hexadecimal notation, e.g. #FF0000.
HexAlpha string? null The changed color in eight-digit hexadecimal notation, whose last pair is the alpha channel, e.g. #FF000080.
Rgb string? null The changed color in functional RGB notation, e.g. rgb(255,0,0).
Rgba string? null The changed color in functional RGB notation with its alpha channel, e.g. rgba(255,0,0,0.5).
Hsl (double Hue, double Saturation, double Lightness) The changed color as hue (0-360), saturation and lightness (both 0-1).
Hsv (double Hue, double Saturation, double Value) The changed color as hue (0-360), saturation and value (both 0-1).
Hwb (double Hue, double Whiteness, double Blackness) The changed color as hue (0-360), whiteness and blackness (both 0-1).
Oklch (double Lightness, double Chroma, double Hue) The changed color as Oklab lightness (0-1), chroma (0 to about 0.4) and hue (0-360).
ColorDescription string? null The changed color said in words, e.g. "light vibrant blue".

BitColorPickerClassStyles properties

Custom CSS classes/styles for the parts of the BitColorPicker.

Name Type Default value Description
Root string? null Custom CSS classes/styles for the root element of the color picker.
LabelContainer string? null Custom CSS classes/styles for the element the label is rendered into.
Label string? null Custom CSS classes/styles for the label text of the color picker.
SaturationPicker string? null Custom CSS classes/styles for the saturation-value area of the color picker.
SaturationThumb string? null Custom CSS classes/styles for the thumb of the saturation-value area.
Content string? null Custom CSS classes/styles for the row that holds the sliders, the eye dropper and the preview.
Sliders string? null Custom CSS classes/styles for the column that holds the hue and alpha sliders.
HueSlider string? null Custom CSS classes/styles for the track of the hue slider.
AlphaSlider string? null Custom CSS classes/styles for the track of the alpha slider.
SliderInput string? null Custom CSS classes/styles for the range inputs of both sliders.
EyeDropper string? null Custom CSS classes/styles for the eye dropper button.
EyeDropperIcon string? null Custom CSS classes/styles for the icon of the eye dropper button.
InputsModeSwitch string? null Custom CSS classes/styles for the button that moves the text fields to the next set of channels.
InputsModeSwitchIcon string? null Custom CSS classes/styles for the icon of the inputs mode switch button.
Preview string? null Custom CSS classes/styles for the color preview box.
Inputs string? null Custom CSS classes/styles for the row of the hex and channel text fields.
Field string? null Custom CSS classes/styles for a single field of the inputs row, label included.
FieldInput string? null Custom CSS classes/styles for the text input of a single field.
FieldLabel string? null Custom CSS classes/styles for the caption of a single field.
Contrast string? null Custom CSS classes/styles for the row that holds the contrast readout.
ContrastRatio string? null Custom CSS classes/styles for the contrast ratio itself.
ContrastBadge string? null Custom CSS classes/styles for a pass/fail badge of the contrast readout.
Presets string? null Custom CSS classes/styles for the container of the preset swatches.
Preset string? null Custom CSS classes/styles for a single preset swatch.
SelectedPreset string? null Custom CSS classes/styles for the preset swatch of the current color, applied on top of Preset.

BitColorFormat enum

Name Value Description
Hex 0 Six-digit hexadecimal notation: #RRGGBB.
HexAlpha 1 Eight-digit hexadecimal notation, whose last pair is the alpha channel: #RRGGBBAA.
Rgb 2 Functional RGB notation: rgb(255,0,0).
Rgba 3 Functional RGB notation with an alpha channel: rgba(255,0,0,0.5).
Hsl 4 Functional HSL notation: hsl(0,100%,50%).
Hsla 5 Functional HSL notation with an alpha channel: hsla(0,100%,50%,0.5).
Hsv 6 Functional HSV notation: hsv(0,100%,100%). It is the model the picker itself is built on, but unlike the others it is not a notation any browser understands.
Hsva 7 Functional HSV notation with an alpha channel: hsva(0,100%,100%,0.5).
Hwb 8 Functional HWB notation: hwb(0 0% 0%). CSS only defines the space-separated syntax for it, so that is the one written.
Hwba 9 Functional HWB notation with an alpha channel: hwb(0 0% 0% / 0.5). CSS has no hwba() function - the alpha is written into hwb() itself, after a slash.
Oklab 10 Functional Oklab notation: oklab(0.6279 0.2249 0.1258). Oklab is a perceptually uniform color space, so the same numeric step covers the same visual difference wherever it is taken.
Oklaba 11 Functional Oklab notation with an alpha channel: oklab(0.6279 0.2249 0.1258 / 0.5).
Oklch 12 Functional Oklch notation: oklch(0.6279 0.2577 29.23). It is the polar form of Oklab, and the notation modern design tokens are increasingly written in.
Oklcha 13 Functional Oklch notation with an alpha channel: oklch(0.6279 0.2577 29.23 / 0.5).

BitColorInputsMode enum

Name Value Description
HexRgb 0 The hexadecimal field alongside the three Red-Green-Blue channels, which is the pair most color pickers show together.
Hex 1 The hexadecimal field on its own.
Rgb 2 The Red, Green and Blue channels, each from 0 to 255.
Hsl 3 Hue in degrees, saturation and lightness as percentages.
Hsv 4 Hue in degrees, saturation and brightness as percentages - the model the picker itself is driven in.

BitSize enum

Name Value Description
Small 0 Display the color picker using small size.
Medium 1 Display the color picker using medium size.
Large 2 Display the color picker using large size.

BitVisibility enum

Name Value Description
Visible 0 The content of the component is visible.
Hidden 1 The content of the component is hidden, but the space it takes on the page remains (visibility:hidden).
Collapsed 2 The component is hidden (display:none).

BitDir enum

Name Value Description
Ltr 0 Ltr (left to right) is to be used for languages that are written from the left to the right (like English).
Rtl 1 Rtl (right to left) is to be used for languages that are written from the right to the left (like Arabic).
Auto 2 Auto lets the user agent decide. It uses a basic algorithm as it parses the characters inside the element until it finds a character with a strong directionality, then applies that directionality to the whole element.

Feedback

You can give us your feedback through our GitHub repo by filing a new Issue or starting a new Discussion.


Or you can review / edit this page on GitHub.


Or you can review / edit this component on GitHub.