Skip to content

Button Group

<loomi-button-group> and <loomi-button-group-item> - a horizontal row of segmented toggle buttons with shared sizing, radius, icons, colors, outline mode, and disabled states.

Terminal window
npm install @loomidev/button-group lit
import "@loomidev/button-group";

Place <loomi-button-group-item> elements inside a group. One item can be marked selected for the initial state.

<loomi-button-group>
<loomi-button-group-item label="Day" value="day" selected></loomi-button-group-item>
<loomi-button-group-item label="Week" value="week"></loomi-button-group-item>
<loomi-button-group-item label="Month" value="month"></loomi-button-group-item>
</loomi-button-group>

Listen for selection changes on the group:

<loomi-button-group id="range">
<loomi-button-group-item label="Day" value="day" selected></loomi-button-group-item>
<loomi-button-group-item label="Week" value="week"></loomi-button-group-item>
</loomi-button-group>
<script type="module">
document.querySelector("#range").addEventListener("loomi-button-group-change", (event) => {
console.log(event.detail.value);
});
</script>

Use the same built-in icon names as <loomi-button>. Set icon-right to place the icon after the label.

<loomi-button-group>
<loomi-button-group-item label="List" value="list" icon="list" selected></loomi-button-group-item>
<loomi-button-group-item label="Grid" value="grid" icon="grid-2x2"></loomi-button-group-item>
</loomi-button-group>

Icon-only items work too. Set icon-only on the group when every item should be compact, or on one item when only that button should hide its label.

<loomi-button-group color="primary" icon-only aria-label="Text formatting">
<loomi-button-group-item label="Bold" value="bold" icon="bold" selected></loomi-button-group-item>
<loomi-button-group-item label="Italic" value="italic" icon="italic"></loomi-button-group-item>
</loomi-button-group>

Set circle (on the group or on a single item) to render a full-radius icon button - for icon-only buttons. It implies icon-only, and overrides the group’s radius.

<loomi-button-group circle color="primary" aria-label="Row actions">
<loomi-button-group-item icon="pencil" value="edit" aria-label="Edit"></loomi-button-group-item>
<loomi-button-group-item icon="trash" value="delete" aria-label="Delete"></loomi-button-group-item>
</loomi-button-group>
<!-- one circular item in an otherwise labeled group -->
<loomi-button-group aria-label="Views">
<loomi-button-group-item label="Day" value="day" selected></loomi-button-group-item>
<loomi-button-group-item label="Week" value="week"></loomi-button-group-item>
<loomi-button-group-item circle icon="plus" value="add" aria-label="Add view"></loomi-button-group-item>
</loomi-button-group>

Set tooltip on an item for a built-in <loomi-tooltip> on hover and keyboard focus; tooltip-position picks the side (top by default, flipping when there’s no room). No wrapping needed, and selection, sizing and the segmented look are unchanged. Tooltip text that differs from the item’s name is also exposed as its accessible description.

<loomi-button-group icon-only aria-label="Views">
<loomi-button-group-item icon="list-bullet" label="View as list" tooltip="View as list" selected></loomi-button-group-item>
<loomi-button-group-item icon="map" label="View as map" tooltip="View as map"></loomi-button-group-item>
</loomi-button-group>

size accepts tiny, small, regular (default), medium, and big. radius accepts the same values as <loomi-button>: none, small, medium (default), and full. The segmented bar is shrink-wrapped, so it ends with the last button instead of filling the parent width.

The selected item uses the same surface fill, accent text, and subtle shadow as <loomi-tabs tab-style="system">. color accepts any Loomi color name and tints the selected text plus focus ring. Add outline for a transparent, outline-only variant.

<loomi-button-group size="small" radius="full" color="success">
<loomi-button-group-item label="Left" value="left" selected></loomi-button-group-item>
<loomi-button-group-item label="Right" value="right"></loomi-button-group-item>
</loomi-button-group>
<loomi-button-group outline radius="small" color="error">
<loomi-button-group-item label="Open" value="open" selected></loomi-button-group-item>
<loomi-button-group-item label="Closed" value="closed"></loomi-button-group-item>
</loomi-button-group>

Disable a single item with disabled on <loomi-button-group-item>, or disable the entire group with disabled on <loomi-button-group>.

<loomi-button-group disabled>
<loomi-button-group-item label="Day" value="day" selected></loomi-button-group-item>
<loomi-button-group-item label="Week" value="week"></loomi-button-group-item>
</loomi-button-group>
  • Supports keyboard focus with visible :focus-visible styling on each button.
  • Whenever an item’s label is visually hidden (icon-only or circle on the group or the item), its inner button gets an aria-label from the item’s own aria-label, else its label, so it announces as e.g. “View as list, toggle button, pressed”. Give every icon-only item one or the other.

For the library-wide baseline, see Foundations - Accessibility.

For dense layouts, let the component keep its natural shrink-wrapped width and give the surrounding layout room to scroll or wrap. For long labels or user-provided content, prefer concise text instead of fixed pixel assumptions.

For the shared container and viewport rules, see Foundations - Responsive behavior.

For theme activation, token overrides, and contrast guidance, see Foundations - Dark mode.

AttributeDefaultDescription
colorprimaryAccent color for the selected item text and focus ring. Accepts any Loomi color name.
sizeregularButton size. tiny | small | regular | medium | big. See Sizing.
radiusmediumBar corner radius. none | small | medium | full.
outlinefalseOutline-only treatment: transparent track and selected item outline. (boolean)
icon-onlyfalseHide every item label visually and render square icon buttons. (boolean)
circlefalseFull-radius icon buttons for every item; implies icon-only, overrides radius. (boolean)
aria-label(blank)Accessible label for the internal role="group" wrapper.
disabledfalseDisable every item in the group. (boolean)
AttributeDefaultDescription
label(blank)Visible label text. Also used as the accessible name when icon-only is set.
value(blank)Value emitted in loomi-button-group-change; falls back to the label or text content.
icon(blank)Built-in icon name from @loomidev/icons.
icon-rightfalsePlace the icon after the label. (boolean)
icon-onlyfalseHide this item’s label visually and render a square icon button. (boolean)
circlefalseFull-radius icon button for this item; implies icon-only, overrides the group’s radius. (boolean)
aria-label(blank)Accessible label for icon-only items when label is not enough.
tooltip(blank)Tooltip text shown on hover and keyboard focus.
tooltip-positiontoptop | bottom | left | right; flips when there isn’t room.
selectedfalseMark this item as active. (boolean)
disabledfalseDisable only this item. (boolean)
SlotDescription
(default)Content placed inside the component.
EventDetail
loomi-bg-click{ value } from the activated group item
loomi-button-group-change{ value, label, index } when the selected item changes
  • @loomidev/core
  • @loomidev/icons
  • @loomidev/theme
  • @loomidev/tooltip