Veto
Components

Button group

Related buttons clustered into one control - attached, sized together, and separated where the grouping needs saying out loud.

Basic

Buttons in a group share their touching borders and only the outer corners stay rounded, so the cluster reads as one segmented control rather than three buttons that happen to be adjacent. Give the group a Label whenever the buttons alone do not say what the cluster is for.

razor
<VetoButtonGroup Label="View mode">
    <VetoButton Variant="VetoVariant.Outlined">Day</VetoButton>
    <VetoButton Variant="VetoVariant.Outlined">Week</VetoButton>
    <VetoButton Variant="VetoVariant.Outlined">Month</VetoButton>
</VetoButtonGroup>

Sizes

Size is set once on the group and applied to every button inside it, so a group cannot come out uneven because one button was left at the default. Setting Size on the individual buttons as well still works and is sometimes clearer - but it is no longer something you have to remember.

razor
@* Set once on the group - every button in it takes the same height. *@
<VetoButtonGroup Size="VetoSize.Small" Label="Small">
    <VetoButton Variant="VetoVariant.Outlined">Cut</VetoButton>
    <VetoButton Variant="VetoVariant.Outlined">Copy</VetoButton>
</VetoButtonGroup>

Separators: all of them, or only some

Separators draws a line between every child at once. For a line between only some of them - which is what clusters two related actions and then breaks before the next pair - leave it off and place a VetoButtonGroupSeparator exactly where the break belongs.

razor
@* Between every button: *@
<VetoButtonGroup Separators="true">
    <VetoButton Variant="VetoVariant.Outlined">One</VetoButton>
    <VetoButton Variant="VetoVariant.Outlined">Two</VetoButton>
</VetoButtonGroup>

@* Between only some of them: *@
<VetoButtonGroup>
    <VetoButton Variant="VetoVariant.Outlined">One</VetoButton>
    <VetoButton Variant="VetoVariant.Outlined">Two</VetoButton>
    <VetoButtonGroupSeparator />
    <VetoButton Variant="VetoVariant.Outlined">Three</VetoButton>
</VetoButtonGroup>

A label inside the group

ButtonGroupText embeds a non-interactive label in the cluster. It takes the group's height and joins the shared border, but is drawn on a muted background so nobody mistakes it for a button that refuses to work. Use it to name a toolbar section, or to prefix a group with a unit.

Zoom
minutes
razor
<VetoButtonGroup Label="Zoom">
    <VetoButtonGroupText>Zoom</VetoButtonGroupText>
    <VetoButton Variant="VetoVariant.Outlined">50%</VetoButton>
    <VetoButton Variant="VetoVariant.Outlined">100%</VetoButton>
</VetoButtonGroup>

A real toolbar

Several groups on one line, separated from each other - the pattern every rich-text editor and design tool converges on. Related actions cluster; unrelated ones are held apart. The outer container is the toolbar; the clusters inside it are groups, and a toolbar never contains another toolbar.

razor
<VetoButtonGroup IsToolbar="true" Attached="false" Label="Formatting">

    <VetoButtonGroup Size="VetoSize.Small" Label="History">
        <VetoIconButton Icon="@VetoIcons.Undo" Label="Undo" Variant="VetoVariant.Outlined" />
        <VetoIconButton Icon="@VetoIcons.Redo" Label="Redo" Variant="VetoVariant.Outlined" />
    </VetoButtonGroup>

    <VetoButtonGroupSeparator />

    <VetoButtonGroup Size="VetoSize.Small" Label="Text style">
        <VetoIconButton Icon="@VetoIcons.Bold" Label="Bold" Variant="VetoVariant.Outlined" />
        <VetoIconButton Icon="@VetoIcons.Italic" Label="Italic" Variant="VetoVariant.Outlined" />
    </VetoButtonGroup>

</VetoButtonGroup>

Detached, vertical and full width

Attached is what makes the cluster one control; turn it off for a plain spaced row. Orientation runs the group down instead of across, and FullWidth stretches it so the buttons share the space evenly.

razor
<VetoButtonGroup Attached="false">...</VetoButtonGroup>
<VetoButtonGroup Orientation="VetoOrientation.Vertical">...</VetoButtonGroup>
<VetoButtonGroup FullWidth="true">...</VetoButtonGroup>

Parameters

Parameter Type Default Description
ChildContent RenderFragment? null The buttons, separators and labels in the group.
Size VetoSize Medium The height every button in the group takes.
Orientation VetoOrientation Horizontal Whether the group runs across or down.
Attached bool true Share touching borders and round only the outer corners.
Separators bool false Draw a line between every child.
FullWidth bool false Stretch to fill, buttons sharing the width evenly.
Label string? null The group's accessible name.
IsToolbar bool false Report as an ARIA toolbar rather than a group. For the outermost container only.
VetoButtonGroupSeparator component — A line placed by hand, between only some of the buttons.
VetoButtonGroupText component — A non-interactive label inside the group, on a muted background.
Something went wrong. Reload 🗙