ThemePicker
ThemePicker renders a labelled list of palettes. Choosing one applies it at once
and keeps it in the osirion-preferred-palette cookie, so the next page, and the next visit, use it too. Light and dark
stay with ThemeToggle; the two sit well side by side. The demo below changes this
site's own palette, which is the point of the component, and your choice stays in your browser.
Package Osirion.Blazor.Theming, namespace Osirion.Blazor.Theming.Components. Source on GitHub.
@using Osirion.Blazor.Theming.Components
@* Changes the palette of the page you are reading; the choice is kept in your browser's cookie. *@
<div style="display: flex; flex-wrap: wrap; align-items: center; gap: 1rem;">
<ThemePicker />
<ThemeToggle />
</div>Usage
Allow palette selection, so every page links the palette stylesheet and a chosen palette is painted with the first frame:
{
"Osirion": {
"Theming": {
"AllowPaletteSelection": true
}
}
}
Then place the picker, for example next to the toggle in a menu:
@using Osirion.Blazor.Theming.Components
<ThemePicker />
<ThemeToggle />
Offer fewer palettes, in your order, and rename the option that applies none:
@using Osirion.Blazor.Components
@using Osirion.Blazor.Theming.Components
<ThemePicker Label="Colors"
FrameworkLabel="Site colors"
Palettes="@([ThemePalette.Framework, ThemePalette.Editor, ThemePalette.Contrast])" />
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
Label |
string |
"Palette" |
The visible text of the list's label. |
Palettes |
IReadOnlyList<ThemePalette>? |
null |
The palettes offered, in this order. When null, every palette is offered. Duplicates and values outside ThemePalette are dropped. The palette the visitor already uses is offered even when it is not listed (first, when it is missing), so the list always shows the palette in effect. |
FrameworkLabel |
string |
"Default" |
The text of the ThemePalette.Framework option, which applies no palette and shows the site's own colors. |
Theme |
ThemeMode |
ThemeMode.System |
The component's color mode. Light or Dark writes it to data-theme (data-bs-theme under Bootstrap) on the root element; System writes nothing. |
Class |
string? |
null |
Extra CSS classes for the component's root element. |
Style |
string? |
null |
An inline style for the component's root element. |
Class, Style and any extra attributes go on the outer <label>. Theme, inherited from the component base class,
is not written to the markup.
Behavior
- The server renders the list with the visitor's palette selected (
IThemeService.CurrentPalette). On a page exported to static files, or one cached before the visitor chose, the script selects the palette from the cookie when the page loads and after every enhanced navigation. - Choosing an option sets
data-osirion-paletteon<html>(or removes it forFramework), writes the cookie for one year (SameSite=Lax,Secureon HTTPS) and keeps every picker on the page in step. When the page has no palette stylesheet (AllowPaletteSelectionoff), the script adds it. - No interactive render mode is needed. The script,
theme-picker.js, is loaded once through the BlazorJSComponents script loader (registered byAddOsirion, or bybuilder.Services.AddJSComponents()next toAddOsirionTheming), and listens on the document, so pickers that enhanced navigation adds work without further setup. It writes no inline script and no event handler attributes. - Without JavaScript the list renders but choosing does nothing, as with
ThemeToggle.
Accessibility
The list is a native <select> inside its <label>, so it has an accessible name, works with the keyboard (arrow keys
change the palette) and needs no id, which keeps several pickers on one page valid. Its focus outline uses
--osirion-focus-ring-color. The label takes the color of its container, so it stays readable in a menu with its own
background, such as the Studio Blue frame.
Styling
| Class | Element |
|---|---|
osirion-theme-picker |
The outer <label> |
osirion-theme-picker-label |
The label text |
osirion-theme-picker-select |
The <select>; it reads --osirion-input-background, --osirion-input-text, --osirion-input-border and --osirion-input-radius |
To hide the label visually but keep it for screen readers, pass a Class and give
.your-class .osirion-theme-picker-label the same rules as Osirion's osirion-visually-hidden class in your stylesheet.
Related
- Palettes: the palettes, their contrast checks and how they are applied.
- ThemeToggle: switches between light and dark.
- OsirionStyles: links the palette stylesheet.