JavaScript Button Group

@lemonadejs/buttongroup · ✓ 20 contract checks · framework-agnostic · zero dependencies

<ButtonGroup /> — a fused row (or column) of buttons (LemonadeJS v6 block)

One block covering both plain action groups and toggle selection: selectable=” plain action buttons — onclick(value, event) selectable=‘single’ exclusive selection — click selects, click again deselects (value | null) selectable=‘multiple’ toggle set — the value is always an array

The selection follows the dropdown model, divisor-free: bind=”${state}” the live two-way selection (single value or array) external writes land silently; user toggles fire onchange (.set)

Example

live
import { html } from 'lemonadejs';
import ButtonGroup from '@lemonadejs/buttongroup';

const App = (props, { state }) => {
    const period = state('month');
    const channels = state(['email']);

    return html`<div>
        <p>Report period</p>
        <${ButtonGroup} selectable="single" variant="outlined" bind="${period}"
            options="${[
                { value: 'week', label: 'Week' },
                { value: 'month', label: 'Month' },
                { value: 'quarter', label: 'Quarter' },
                { value: 'year', label: 'Year' },
            ]}" />
        <p>Notify me by</p>
        <${ButtonGroup} selectable="multiple" bind="${channels}"
            options="${[
                { value: 'email', label: 'Email' },
                { value: 'sms', label: 'SMS' },
                { value: 'slack', label: 'Slack' },
            ]}" />
        <p>Sending the <b>${period}</b> report via <b>${() => channels.value.join(', ') || 'nothing'}</b></p>
    </div>`;
};

Installation

npm install @lemonadejs/buttongroup
import Buttongroup from '@lemonadejs/buttongroup';
import '@lemonadejs/buttongroup/style.css';

The icons come from Google Material Symbols. Load the font once per page:

<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined">

Three deployment forms, one component:

html`<${Buttongroup} />`                       // by value (no registration)
setComponents({ Buttongroup });               // then <Buttongroup /> by name anywhere
createWebComponent(Buttongroup);              // <lm-buttongroup> in plain HTML/any framework

Props

Every declared prop arrives as a live state — pass a value for a snapshot or a state for a two-way live wire. Attribute strings are coerced to the declared type.

PropTypeDefaultDescription
bindanyTwo-way bound value. .set() fires onchange; plain assignment is silent. selection: single value, array when multiple (any)
optionsarray{ value, label, icon, disabled } or strings
selectablestring''” action buttons
variantstring''” contained
colorstring''green
sizestring''small
orientationstring''” horizontal
disabledbooleanfalseblocks the whole group (native)
aria-labelstring''

Events

All event names are lowercase (the platform convention — LJS-305 warns otherwise).

  • onchange — (selection) on user toggles
  • onclick — (value, event) in plain mode

Styling

All classes follow the lm-buttongroup-* convention; visual variants are data-* attributes on the root. Override freely — there is no styling engine to fight.

Contract

The machine-readable schema ships with the package:

import contract from '@lemonadejs/buttongroup/contract.json';

verify.json carries the conformance proof produced by verify(Buttongroup).

Looking for the v5 plugin? See the archived v5 documentation.