Switch
A sliding on/off control - and, bound to a bool?, a three-state one that also carries an indeterminate value.
On and off
Bound to a bool. Click the control or its label, or focus it and press Space.
<VetoSwitch TValue="bool"
Label="Email notifications"
HelperText="We will only mail you about things you asked for."
@bind-Value="_notify" />Three states
Set ThreeState and bind to a bool?, and the switch cycles off, on, indeterminate. Indeterminate is null - the state for a question nobody has answered yet, which a plain bool has nowhere to put. The thumb sits centred so the third state reads at a glance, and the control reports itself as an ARIA checkbox with aria-checked="mixed", the only role allowed to say so.
<VetoSwitch TValue="bool?"
ThreeState="true"
ShowIcons="true"
ShowStateText="true"
Label="Archived"
@bind-Value="_archived" />
@code {
private bool? _archived; // null is the indeterminate state
}Cycle order
Which way a three-state switch walks. The default puts on second, so the first press of an unset switch reads as a plain 'turn it on'. OffIndeterminateOn suits filters, where 'unset' sits naturally between exclude and include.
<VetoSwitch TValue="bool?" ThreeState="true" Label="Default" @bind-Value="_a" />
<VetoSwitch TValue="bool?"
ThreeState="true"
Order="VetoSwitchOrder.OffIndeterminateOn"
Label="Indeterminate in the middle"
@bind-Value="_b" />Sizes, colours and variants
The same size, colour and variant enums the rest of the library uses, all driven by modifier classes rather than inline styles.
<VetoSwitch TValue="bool" Size="VetoSize.Small" Label="Small" @bind-Value="_v" />
<VetoSwitch TValue="bool" Color="VetoColor.Success" Label="Success" @bind-Value="_v" />
<VetoSwitch TValue="bool" Variant="VetoVariant.Filled" Label="Filled" @bind-Value="_v" />Label placement and state text
The label goes after the control by default; put it first to line a column of switches up on the left, or above it to match the other inputs. ShowStateText prints the current state next to the control, and the three texts are yours to set.
<VetoSwitch TValue="bool"
LabelPlacement="VetoSwitchLabelPlacement.Start"
Label="Label first"
@bind-Value="_v" />
<VetoSwitch TValue="bool"
ShowStateText="true"
OnText="Public"
OffText="Private"
Label="Visibility"
@bind-Value="_visibility" />Disabled and read-only
Disabled cannot be focused. Read-only can be focused - so its state can still be read out - but will not change.
<VetoSwitch TValue="bool" Label="Disabled" Disabled="true" @bind-Value="_v" />
<VetoSwitch TValue="bool" Label="Read-only" ReadOnly="true" @bind-Value="_v" />Confirming or saving before the change
BeforeChange is asked with the state the switch is about to take, and can say no. While it runs the switch is busy - a spinner in the thumb, aria-busy, input ignored - which is what you want while a setting saves to the server. Loading shows the same busy state on demand.
<VetoSwitch TValue="bool" Label="Sync to cloud"
BeforeChange="SaveAsync" @bind-Value="_synced" />
@code {
private async Task<bool> SaveAsync(bool? next)
{
var response = await Http.PutAsJsonAsync("api/settings/sync", next);
return response.IsSuccessStatusCode; // false keeps the old state
}
}Validation
Inside an EditForm the switch picks up the model's validation attributes like any other input: it sets aria-invalid, swaps its helper text for the message, and announces it.
<EditForm Model="_form" OnValidSubmit="Save">
<DataAnnotationsValidator />
<VetoSwitch Label="I accept the terms"
Required="true"
HelperText="Required before you can continue."
@bind-Value="_form.AcceptedTerms" />
<button type="submit">Save</button>
</EditForm>
@code {
private sealed class FormModel
{
[Range(typeof(bool), "true", "true",
ErrorMessage = "You must accept the terms.")]
public bool AcceptedTerms { get; set; }
}
}Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
Value |
TValue? |
default |
The bound value. Use @bind-Value. TValue must be bool or bool?. |
ThreeState |
bool |
false |
Cycle off, on and indeterminate instead of two states. Requires TValue of bool?. |
Order |
VetoSwitchOrder |
OffOnIndeterminate |
The order a three-state switch walks its states in. |
Label |
string? |
null |
Text for the switch's label. No label element is rendered without it. |
LabelPlacement |
VetoSwitchLabelPlacement |
End |
End, Start or Top. |
HelperText |
string? |
null |
Guidance under the control, replaced by the validation message while invalid. |
ShowStateText |
bool |
false |
Render the current state's text beside the control. |
OnText / OffText / IndeterminateText |
string |
"On" / "Off" / "Indeterminate" |
The state texts. Also the accessible name when there is no label. |
ShowIcons |
bool |
false |
Draw an icon on the thumb for the current state. |
OnIcon / OffIcon / IndeterminateIcon |
string? |
Check / Close / Minus |
The thumb icons, when ShowIcons is set. |
Color |
VetoColor |
Primary |
The accent the track takes when on. |
Size |
VetoSize |
Medium |
ExtraSmall, Small, Medium, Large or ExtraLarge. |
Variant |
VetoVariant |
Outlined |
Outlined, Filled, Text, Soft, Underlined, Ghost or Elevated. |
Disabled |
bool |
false |
Cannot be focused or changed. |
ReadOnly |
bool |
false |
Can be focused, but will not change. |
Required |
bool |
false |
Renders the required marker and sets aria-required. Enforcement comes from the model. |
BeforeChange |
Func<bool?, Task<bool>>? |
null |
Asked before every change with the next state; return false to keep the current one. The switch is busy while it runs. |
Loading |
bool |
false |
Shows the busy state and ignores input. |
OnValueChanged |
EventCallback<TValue?> |
— |
Raised after the bound value changes. |
State |
bool? |
— |
Read-only: the current state, with null for indeterminate. |
ToggleAsync() / SetStateAsync(bool?) |
Task |
— |
Drive the switch from code; both respect Disabled and ReadOnly. |