Selection
Choose from options: checkboxes, radios, selects, chips, toggles and sliders.
Checkbox #
Single checkboxes and checkbox groups.
Checkbox #
Checkbox. The native <input> is the host: class, style and forwarded attributes (id, name, required, aria-*) land on it; classes.root styles the label row.
function Example() {
const updates = signal(true);
return (
<Checkbox
label="Email me about product updates"
checked={updates()}
onChange={(e) => updates.set((e.target as HTMLInputElement).checked)}
/>
);
}Slots: root input label
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
checked | boolean | Whether it is checked (controlled). | ||
disabled | boolean | Disables the checkbox. | ||
invalid | boolean | Marks the value invalid (aria-invalid and error styling). | ||
label | content | Label text or content, clickable to toggle. | ||
name | string | Field name submitted with the form. | ||
onChange | (e: Event) => void | Called on toggle; read e.target.checked. | ||
value | string | Native value submitted with the form. |
CheckboxGroup #
Multiple-choice checkboxes in a fieldset.
const regions = [
{ value: "fra1", label: "Frankfurt" },
{ value: "iad1", label: "Washington, D.C." },
{ value: "hnd1", label: "Tokyo" },
];
function Example() {
const selected = signal(["fra1"]);
return (
<CheckboxGroup
legend="Regions"
options={regions}
value={selected()}
onChange={selected.set}
/>
);
}Slots: root legend option
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
onChange | (value: string[]) => void | yes | Called with the new list of checked values. | |
options | { value: string; label: unknown; disabled?: boolean; }[] | yes | Options: value, label, optional disabled. | |
value | string[] | yes | Values of the checked options (controlled). | |
disabled | boolean | Disables every option. | ||
legend | content | Visible group label rendered as <legend>. |
Checklist #
Checklist of items with checkboxes.
2 of 3 done
function Example() {
const items = signal<ChecklistItemData[]>([
{ id: "domain", label: "Connect a domain", done: true },
{ id: "invite", label: "Invite your team", done: true },
{ id: "deploy", label: "Ship your first deploy" },
]);
const done = () => items().filter((i) => i.done).length;
return (
<Stack gap="0.5rem">
<Checklist items={items()} onChange={items.set} />
<Text muted>
{done()} of {items().length} done
</Text>
</Stack>
);
}Slots: root checkbox item label
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
items | ChecklistItemData[] | yes | The checklist items (controlled). | |
onChange | (items: ChecklistItemData[]) => void | yes | Called with the updated items after a tick changes. |
ChecklistItemData
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Item id. |
label | string | yes | Item text. |
done | boolean | Whether the item is ticked. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
RadioGroup #
Radio group (role="radiogroup"). Forwarded attributes land on the group.
const plans = [
{ value: "free", label: "Free" },
{ value: "pro", label: "Pro" },
{ value: "team", label: "Team" },
];
function Example() {
const plan = signal("pro");
return (
<RadioGroup
label="Plan"
name="plan"
options={plans}
value={plan()}
onChange={(e) => plan.set((e.target as HTMLInputElement).value)}
/>
);
}Slots: root input label option
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | yes | Shared name of the radio inputs (also the form field name). | |
options | RadioOption[] | yes | The options, in order. | |
disabled | boolean | Disables every option. | ||
inline | boolean | Lay options out in a row. | ||
label | string | Accessible name for the group. | ||
onChange | (e: Event) => void | Called when the selection changes; read e.target.value. | ||
value | string | Selected option's value (controlled). |
RadioOption
| Field | Type | Required | Description |
|---|---|---|---|
value | string | yes | Option value (what value / onChange use). |
label | content | yes | Text or content shown for the option. |
disabled | boolean | Shown but can't be chosen. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Switch #
Toggle switch (role="switch"). Like {@link Checkbox}, the <input> (the visible track) is the host; classes.root styles the label row.
function Example() {
const previews = signal(true);
return (
<Switch
label="Preview deploys"
checked={previews()}
onChange={(e) => previews.set((e.target as HTMLInputElement).checked)}
/>
);
}Slots: root input label
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
checked | boolean | Whether it is on (controlled). | ||
disabled | boolean | Disables the switch. | ||
label | content | Label text or content, clickable to toggle. | ||
name | string | Field name submitted with the form. | ||
onChange | (e: Event) => void | Called on toggle; read e.target.checked. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Select #
Pick one or many options from a list.
Select #
Native select; forwarded attributes land on <select>.
const plans = [
{ value: "free", label: "Free" },
{ value: "pro", label: "Pro" },
{ value: "team", label: "Team" },
];
function Example() {
const plan = signal("pro");
return (
<Select
aria-label="Plan"
options={plans}
value={plan()}
onChange={(e) => plan.set((e.target as HTMLInputElement).value)}
/>
);
}| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
options | SelectOption[] | yes | The options, in order. | |
disabled | boolean | Disables the select. | ||
invalid | boolean | Marks the value invalid (aria-invalid and error styling). | ||
name | string | Field name submitted with the form. | ||
onChange | (e: Event) => void | Called when the selection changes; read e.target.value. | ||
placeholder | string | Empty first option shown while nothing is selected. | ||
value | string | "" | Selected option's value (controlled). |
SelectOption
| Field | Type | Required | Description |
|---|---|---|---|
value | string | yes | Option value (what value / onChange use). |
label | string | yes | Text shown for the option. |
disabled | boolean | Shown but can't be chosen. |
NativeSelect #
Native <select> with a value callback.
const regions = [
{ value: "fra1", label: "Frankfurt" },
{ value: "iad1", label: "Washington, D.C." },
{ value: "hnd1", label: "Tokyo" },
];
function Example() {
const region = signal("fra1");
return (
<NativeSelect
aria-label="Region"
options={regions}
value={region()}
onChange={region.set}
/>
);
}| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
onChange | (value: string) => void | yes | Called with the selected value. | |
options | { value: string; label: string; disabled?: boolean; }[] | yes | Options: value, label, optional disabled. | |
disabled | boolean | Disables the select. | ||
invalid | boolean | Marks the value invalid (aria-invalid and error styling). | ||
name | string | Field name submitted with the form. | ||
placeholder | string | Empty first option shown while nothing is selected. | ||
value | string | "" | Selected option's value (controlled). |
MultiSelect #
Multi-choice listbox dropdown.
const regions = [
{ value: "fra1", label: "Frankfurt" },
{ value: "iad1", label: "Washington, D.C." },
{ value: "hnd1", label: "Tokyo" },
];
function Example() {
const selected = signal(["fra1", "iad1"]);
return (
<MultiSelect
aria-label="Regions"
options={regions}
value={selected()}
onChange={selected.set}
/>
);
}Slots: root control menu option
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
onChange | (value: string[]) => void | yes | Called with the new list of selected values. | |
options | { value: string; label: string; disabled?: boolean; }[] | yes | Options: value, label, optional disabled. | |
value | string[] | yes | Values of the selected options (controlled). | |
disabled | boolean | Disables the control. | ||
placeholder | string | "Select…" | Trigger text while nothing is selected. |
Autocomplete #
Combobox with suggestion list (↑ ↓ Enter Escape, aria-activedescendant). The <input> is the host; classes.root styles the wrapper.
function Example() {
const country = signal("");
return (
<Autocomplete
aria-label="Country"
placeholder="Start typing a country"
value={country()}
options={["Germany", "Japan", "United Kingdom", "United States"]}
onChange={country.set}
/>
);
}Slots: root input menu option
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
onChange | (value: string) => void | yes | Called with the new text as the user types or picks a suggestion. | |
options | string[] | yes | Suggestions, filtered by the typed text. | |
value | string | yes | Current text (controlled). | |
disabled | boolean | Disables the field. | ||
invalid | boolean | Marks the value invalid (aria-invalid and error styling). | ||
limit | number | 8 | Max suggestions shown (default 8). | |
name | string | Field name submitted with the form. | ||
placeholder | string | Hint shown while empty. | ||
renderOption | (option: string) => unknown | Render an option (default: the text). |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
ChoiceCard #
Selectable card wrapping a native radio/checkbox.
function Example() {
const plan = signal("pro");
return (
<Group gap="0.75rem">
<ChoiceCard
type="radio"
name="plan"
value="free"
checked={plan() === "free"}
label="Free"
description="For side projects"
onChange={(checked) => checked && plan.set("free")}
/>
<ChoiceCard
type="radio"
name="plan"
value="pro"
checked={plan() === "pro"}
label="Pro"
description="$20 per seat / month"
onChange={(checked) => checked && plan.set("pro")}
/>
</Group>
);
}Slots: root body description input label
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
checked | boolean | yes | Whether this card is selected (controlled). | |
label | content | yes | Card title. | |
onChange | (checked: boolean) => void | yes | Called with the new checked state. | |
description | content | Text under the title. | ||
disabled | boolean | Disables the card. | ||
name | string | Input name; cards with the same name form a radio group. | ||
type | "checkbox" | "radio" | "radio" | radio for one-of-many cards (share a name), checkbox for independent ones. | |
value | string | Value submitted with the form. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Chips #
Toggleable chips.
Chip #
Toggleable pill (aria-pressed).
function Example() {
const on = signal(true);
return (
<Chip checked={on()} onChange={on.set}>
TypeScript
</Chip>
);
}| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
checked | boolean | Whether the chip is selected (controlled). | ||
children | content | Chip label. | ||
disabled | boolean | Disables the chip. | ||
icon | content | Leading icon. | ||
onChange | (checked: boolean) => void | Called with the new checked state. |
ChipGroup #
Single or multiple choice chips.
function Example() {
const frameworks = signal(["arachne"]);
return (
<ChipGroup
legend="Frameworks"
multiple
options={[
{ value: "arachne", label: "Arachne" },
{ value: "solid", label: "Solid" },
{ value: "svelte", label: "Svelte" },
]}
value={frameworks()}
onChange={frameworks.set}
/>
);
}Slots: root chip legend
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
onChange | (value: string[]) => void | yes | Called with the new list of selected values. | |
options | { value: string; label: unknown; disabled?: boolean; }[] | yes | Chips: value, label, optional disabled. | |
value | string[] | yes | Values of the selected chips (controlled). | |
disabled | boolean | Disables every chip. | ||
legend | content | Group caption (the group's accessible name). | ||
multiple | boolean | Allow several chips selected; otherwise picking one replaces the other. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Segmented & toggle group #
Pick one (or several) of a few options.
Segmented #
Pressed-button group.
function Example() {
const range = signal("7d");
return (
<Segmented
label="Range"
items={[
{ id: "24h", label: "24h" },
{ id: "7d", label: "7 days" },
{ id: "30d", label: "30 days" },
]}
value={range()}
onChange={range.set}
/>
);
}Slots: root segment
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
items | { id: string; label: string; disabled?: boolean; }[] | yes | Options: id, label and optional disabled. | |
onChange | (id: string) => void | yes | Called with the id the user picks. | |
value | string | yes | Id of the selected option. | |
label | string | "Options" | Accessible name for the group (default "Options"). |
ToggleGroup #
Pressed-toggle group.
function Example() {
const formats = signal<string[]>(["bold"]);
return (
<ToggleGroup
label="Formatting"
multiple
items={[
{ id: "bold", label: "Bold" },
{ id: "italic", label: "Italic" },
{ id: "underline", label: "Underline" },
]}
value={formats()}
onChange={(next) => formats.set(Array.isArray(next) ? next : next ? [next] : [])}
/>
);
}Slots: root item
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
items | ToggleItem[] | yes | The options, in order. | |
onChange | (value: string | string[] | null) => void | yes | Called with the new pressed id(s) (null when the pressed single option is released). | |
value | string | string[] | yes | Pressed id (single), ids (multiple), or null for none. | |
label | string | Accessible name for the group. | ||
multiple | boolean | Allow several options pressed at once (value is an array). |
ToggleItem
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Option id, passed to onChange and matched against value. |
label | content | yes | Option text or content. |
disabled | boolean | Shown but can't be toggled. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Sliders #
Pick a value, a range or an angle.
Slider #
Range input; forwarded attributes land on <input type="range">.
Volume: 60
function Example() {
const volume = signal(60);
return (
<>
<Slider aria-label="Volume" value={volume()} onChange={volume.set} />
<Text muted>Volume: {volume()}</Text>
</>
);
}| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
onChange | (value: number) => void | yes | Called with the new value while dragging or using the keyboard. | |
value | number | yes | Current value (controlled). | |
disabled | boolean | Disables the slider. | ||
max | number | 100 | Highest value. | |
min | number | 0 | Lowest value. | |
step | number | 1 | Increment between values (also for arrow keys). |
RangeSlider #
Two-thumb range.
$40 – $120
function Example() {
const range = signal<[number, number]>([40, 120]);
return (
<>
<RangeSlider
aria-label="Price range"
min={0}
max={200}
value={range()}
onChange={range.set}
/>
<Text muted>
${range()[0]} – ${range()[1]}
</Text>
</>
);
}Slots: root end start
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
onChange | (value: [number, number]) => void | yes | Called with the new [start, end]; handles can't cross. | |
value | [number, number] | yes | Start and end of the range (controlled). | |
disabled | boolean | Disables both handles. | ||
endLabel | string | "Range end" | Accessible name of the end handle. | |
max | number | 100 | Highest value. | |
min | number | 0 | Lowest value. | |
startLabel | string | "Range start" | Accessible name of the start handle. | |
step | number | 1 | Increment between values. |
AngleSlider #
Circular slider for an angle.
135°
function Example() {
const angle = signal(135);
return (
<Group gap="0.75rem">
<AngleSlider value={angle()} onChange={angle.set} />
<Text muted>{angle()}°</Text>
</Group>
);
}Slots: root arm hub knob label svg track
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
onChange | (deg: number) => void | yes | Called with the new angle while dragging or using the arrow keys. | |
value | number | yes | Angle in degrees, 0–359 (controlled). | |
label | string | "Angle" | Accessible name (default "Angle"). | |
size | number | 120 | Diameter in pixels. | |
step | number | 5 | Degrees per arrow key press (default 5). |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Rating #
Star rating (radio pattern with roving tabindex, arrow keys).
function Example() {
const stars = signal(4);
return <Rating aria-label="Rating" value={stars()} onChange={stars.set} />;
}Slots: root star
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
onChange | (value: number) => void | yes | Called with the picked rating. | |
value | number | yes | Current rating (controlled; 0 for none). | |
count | number | 5 | Number of stars. | |
disabled | boolean | Read-only display. | ||
starLabel | (n: number) => string | Accessible label per star, e.g. (n) => \${n} of 5``. | ||
symbol | content | "★" | Star glyph (default ★). |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
TransferList #
Dual-list mover (Mantine TransferList). Rows keep their DOM between moves.
Available
Selected
function Example() {
const lists = signal({ left: ["Frankfurt", "Tokyo", "São Paulo"], right: ["Washington, D.C."] });
return (
<TransferList
leftTitle="Available"
rightTitle="Selected"
left={lists().left}
right={lists().right}
onChange={lists.set}
/>
);
}Slots: root actions item list pane title
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
left | string[] | yes | Items in the left list. | |
onChange | (next: { left: string[]; right: string[]; }) => void | yes | Called with both lists after items are moved. | |
right | string[] | yes | Items in the right list. | |
leftTitle | string | "Available" | Heading of the left list. | |
rightTitle | string | "Selected" | Heading of the right list. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Preference toggles #
View, density, theme and language switches.
ViewToggle #
List / grid toggle.
Showing a list
function Example() {
const view = signal<"list" | "grid">("list");
return (
<Group gap="0.75rem">
<ViewToggle value={view()} onChange={view.set} />
<Text muted>Showing a {view()}</Text>
</Group>
);
}Slots: root option
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
onChange | (value: "grid" | "list") => void | yes | Called with the view the user picks. | |
value | "grid" | "list" | yes | Current view. |
DensityToggle #
Compact / comfortable density switch.
Density: compact
function Example() {
const density = signal<Density>("compact");
return (
<Group gap="0.75rem">
<DensityToggle value={density()} onChange={density.set} />
<Text muted>Density: {density()}</Text>
</Group>
);
}Slots: root option
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
onChange | (value: Density) => void | yes | Called with the density the user picks. | |
value | Density | yes | Current density. | |
label | string | "Density" | Accessible name (default "Density"). |
Density
type Density = "comfortable" | "compact";ThemeToggle #
Toggle between light and dark themes.
This panel is in the light theme.
function Example() {
const theme = signal<"light" | "dark">("light");
return (
<Paper withBorder class={theme() === "dark" ? "a-theme-dark" : undefined}>
<Group gap="0.75rem">
<ThemeToggle value={theme()} onChange={theme.set} />
<Text>This panel is in the {theme()} theme.</Text>
</Group>
</Paper>
);
}| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
onChange | (theme: "dark" | "light") => void | yes | Called with the theme to switch to; apply it yourself (e.g. data-theme on <html>). | |
value | "dark" | "light" | yes | Current theme. |
LocaleSwitcher #
Inline language picker.
function Example() {
const locale = signal("en");
return (
<LocaleSwitcher
label="Language"
value={locale()}
options={[
{ value: "en", label: "English" },
{ value: "de", label: "Deutsch" },
{ value: "ja", label: "日本語" },
]}
onChange={locale.set}
/>
);
}Slots: root option
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
onChange | (value: string) => void | yes | Called with the picked locale code. | |
options | LocaleOption[] | yes | Available languages. | |
value | string | yes | Current locale code (controlled). | |
label | string | "Language" | Accessible name (default "Language"). |
LocaleOption
| Field | Type | Required | Description |
|---|---|---|---|
value | string | yes | Locale code, e.g. de. |
label | string | yes | Language name shown to the user. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.