SelectionButtonGroup
This library is a work-in-progress. We are releasing it early to gather feedback, but it is not ready for production.
A button-styled selection UI for single (radio) or multiple (checkbox) selection. Ideal for compact option toggles, filter controls, and inline selections.
Examples
Live Preview
Radio Group (Single Selection)
Selected:
Checkbox Group (Multiple Selection)
Selected: None
Theme Variants
Default (Primary)
Success
Info
Warning
Error
Monochrome
Size Variants
Small (sm)
Medium (md) - Default
Large (lg)
Shape Variants
Default (rectangular)
Rounded
Capsule (pill)
Disabled State
Disabled Individual Button State
View Vue Code
<template>
<div class="examples-container">
<!-- Radio Group -->
<section class="example-section">
<h3>Radio Group (Single Selection)</h3>
<VueSelectionButtonGroup
type="radio"
name="payment-method"
legend="Select payment method"
shape="rounded"
@selection-change="handleChange"
>
<VueSelectionButton value="card" label="Credit Card">
Credit Card
</VueSelectionButton>
<VueSelectionButton value="paypal" label="PayPal">
PayPal
</VueSelectionButton>
<VueSelectionButton value="bank" label="Bank Transfer">
Bank Transfer
</VueSelectionButton>
</VueSelectionButtonGroup>
<p class="selection-output">Selected: {{ radioSelection }}</p>
</section>
<!-- Checkbox Group -->
<section class="example-section">
<h3>Checkbox Group (Multiple Selection)</h3>
<VueSelectionButtonGroup
type="checkbox"
name="toppings"
legend="Select toppings"
shape="rounded"
@selection-change="handleCheckboxChange"
>
<VueSelectionButton value="cheese" label="Extra Cheese">
Extra Cheese
</VueSelectionButton>
<VueSelectionButton value="pepperoni" label="Pepperoni">
Pepperoni
</VueSelectionButton>
<VueSelectionButton value="mushrooms" label="Mushrooms">
Mushrooms
</VueSelectionButton>
<VueSelectionButton value="olives" label="Olives">
Olives
</VueSelectionButton>
</VueSelectionButtonGroup>
<p class="selection-output">Selected: {{ checkboxSelection.join(', ') || 'None' }}</p>
</section>
<!-- Theme Variants -->
<section class="example-section">
<h3>Theme Variants</h3>
<div class="theme-grid">
<div>
<p class="theme-label">Default (Primary)</p>
<VueSelectionButtonGroup
type="radio"
name="theme-default"
legend="Default theme"
legend-hidden
shape="rounded"
>
<VueSelectionButton value="a" label="Option A">A</VueSelectionButton>
<VueSelectionButton value="b" label="Option B">B</VueSelectionButton>
</VueSelectionButtonGroup>
</div>
<div>
<p class="theme-label">Success</p>
<VueSelectionButtonGroup
type="radio"
name="theme-success"
legend="Success theme"
legend-hidden
theme="success"
shape="rounded"
>
<VueSelectionButton value="a" label="Option A">A</VueSelectionButton>
<VueSelectionButton value="b" label="Option B">B</VueSelectionButton>
</VueSelectionButtonGroup>
</div>
<div>
<p class="theme-label">Info</p>
<VueSelectionButtonGroup
type="radio"
name="theme-info"
legend="Info theme"
legend-hidden
theme="info"
shape="rounded"
>
<VueSelectionButton value="a" label="Option A">A</VueSelectionButton>
<VueSelectionButton value="b" label="Option B">B</VueSelectionButton>
</VueSelectionButtonGroup>
</div>
<div>
<p class="theme-label">Warning</p>
<VueSelectionButtonGroup
type="radio"
name="theme-warning"
legend="Warning theme"
legend-hidden
theme="warning"
shape="rounded"
>
<VueSelectionButton value="a" label="Option A">A</VueSelectionButton>
<VueSelectionButton value="b" label="Option B">B</VueSelectionButton>
</VueSelectionButtonGroup>
</div>
<div>
<p class="theme-label">Error</p>
<VueSelectionButtonGroup
type="radio"
name="theme-error"
legend="Error theme"
legend-hidden
theme="error"
shape="rounded"
>
<VueSelectionButton value="a" label="Option A">A</VueSelectionButton>
<VueSelectionButton value="b" label="Option B">B</VueSelectionButton>
</VueSelectionButtonGroup>
</div>
<div>
<p class="theme-label">Monochrome</p>
<VueSelectionButtonGroup
type="radio"
name="theme-monochrome"
legend="Monochrome theme"
legend-hidden
theme="monochrome"
shape="rounded"
>
<VueSelectionButton value="a" label="Option A">A</VueSelectionButton>
<VueSelectionButton value="b" label="Option B">B</VueSelectionButton>
</VueSelectionButtonGroup>
</div>
</div>
</section>
<!-- Size Variants -->
<section class="example-section">
<h3>Size Variants</h3>
<div class="size-grid">
<div>
<p class="size-label">Small (sm)</p>
<VueSelectionButtonGroup
type="radio"
name="size-sm"
legend="Small size"
legend-hidden
size="sm"
shape="rounded"
>
<VueSelectionButton value="a" label="Option A">Option A</VueSelectionButton>
<VueSelectionButton value="b" label="Option B">Option B</VueSelectionButton>
</VueSelectionButtonGroup>
</div>
<div>
<p class="size-label">Medium (md) - Default</p>
<VueSelectionButtonGroup
type="radio"
name="size-md"
legend="Medium size"
legend-hidden
size="md"
shape="rounded"
>
<VueSelectionButton value="a" label="Option A">Option A</VueSelectionButton>
<VueSelectionButton value="b" label="Option B">Option B</VueSelectionButton>
</VueSelectionButtonGroup>
</div>
<div>
<p class="size-label">Large (lg)</p>
<VueSelectionButtonGroup
type="radio"
name="size-lg"
legend="Large size"
legend-hidden
size="lg"
shape="rounded"
>
<VueSelectionButton value="a" label="Option A">Option A</VueSelectionButton>
<VueSelectionButton value="b" label="Option B">Option B</VueSelectionButton>
</VueSelectionButtonGroup>
</div>
</div>
</section>
<!-- Shape Variants -->
<section class="example-section">
<h3>Shape Variants</h3>
<div class="shape-grid">
<div>
<p class="shape-label">Default (rectangular)</p>
<VueSelectionButtonGroup
type="radio"
name="shape-default"
legend="Default shape"
legend-hidden
>
<VueSelectionButton value="a" label="Option A">Option A</VueSelectionButton>
<VueSelectionButton value="b" label="Option B">Option B</VueSelectionButton>
</VueSelectionButtonGroup>
</div>
<div>
<p class="shape-label">Rounded</p>
<VueSelectionButtonGroup
type="radio"
name="shape-rounded"
legend="Rounded shape"
legend-hidden
shape="rounded"
>
<VueSelectionButton value="a" label="Option A">Option A</VueSelectionButton>
<VueSelectionButton value="b" label="Option B">Option B</VueSelectionButton>
</VueSelectionButtonGroup>
</div>
<div>
<p class="shape-label">Capsule (pill)</p>
<VueSelectionButtonGroup
type="radio"
name="shape-capsule"
legend="Capsule shape"
legend-hidden
shape="capsule"
>
<VueSelectionButton value="a" label="Option A">Option A</VueSelectionButton>
<VueSelectionButton value="b" label="Option B">Option B</VueSelectionButton>
</VueSelectionButtonGroup>
</div>
</div>
</section>
<!-- Disabled State -->
<section class="example-section">
<h3>Disabled State</h3>
<VueSelectionButtonGroup
type="radio"
name="disabled-example"
legend="Disabled group"
shape="rounded"
disabled
>
<VueSelectionButton value="a" label="Option A">Option A</VueSelectionButton>
<VueSelectionButton value="b" label="Option B">Option B</VueSelectionButton>
<VueSelectionButton value="c" label="Option C">Option C</VueSelectionButton>
</VueSelectionButtonGroup>
</section>
<section class="example-section">
<h3>Disabled Individual Button State</h3>
<VueSelectionButtonGroup
type="radio"
name="disabled-button-example"
legend="Disabled individual"
shape="rounded"
>
<VueSelectionButton value="a" label="Option A">Option A</VueSelectionButton>
<VueSelectionButton disabled value="b" label="Option B">Option B</VueSelectionButton>
<VueSelectionButton value="c" label="Option C">Option C</VueSelectionButton>
<VueSelectionButton disabled value="d" label="Option D">Option D</VueSelectionButton>
<VueSelectionButton value="e" label="Option E">Option E</VueSelectionButton>
</VueSelectionButtonGroup>
</section>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { VueSelectionButtonGroup } from 'agnosticui-core/selection-button-group/vue';
import { VueSelectionButton } from 'agnosticui-core/selection-button/vue';
const radioSelection = ref('');
const checkboxSelection = ref<string[]>([]);
const handleChange = (e: CustomEvent) => {
radioSelection.value = e.detail.selectedValues[0] || '';
};
const handleCheckboxChange = (e: CustomEvent) => {
checkboxSelection.value = e.detail.selectedValues;
};
</script>
<style scoped>
.examples-container {
display: flex;
flex-direction: column;
gap: 2rem;
}
.example-section {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.example-section h3 {
margin: 0;
font-size: 1rem;
font-weight: 600;
}
.selection-output {
margin: 0;
font-size: 0.875rem;
color: var(--vp-c-text-2);
}
.theme-grid,
.size-grid,
.shape-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
.theme-label,
.size-label,
.shape-label {
margin: 0 0 0.5rem 0;
font-size: 0.875rem;
color: var(--vp-c-text-2);
}
</style>
Live Preview
View Lit / Web Component Code
import { LitElement, html, css } from 'lit';
import 'agnosticui-core/selection-button-group';
import 'agnosticui-core/selection-button';
export class SelectionButtonGroupLitExamples extends LitElement {
static styles = css`
:host {
display: block;
}
.examples-container {
display: flex;
flex-direction: column;
gap: 2rem;
}
.example-section {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.example-section h3 {
margin: 0;
font-size: 1rem;
font-weight: 600;
}
.selection-output {
margin: 0;
font-size: 0.875rem;
color: var(--vp-c-text-2, #666);
}
.theme-grid,
.size-grid,
.shape-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
.theme-label,
.size-label,
.shape-label {
margin: 0 0 0.5rem 0;
font-size: 0.875rem;
color: var(--vp-c-text-2, #666);
}
`;
static properties = {
radioSelection: { type: String },
checkboxSelection: { type: Array },
};
constructor() {
super();
this.radioSelection = '';
this.checkboxSelection = [];
}
_handleRadioChange(e) {
this.radioSelection = e.detail.selectedValues[0] || '';
}
_handleCheckboxChange(e) {
this.checkboxSelection = [...e.detail.selectedValues];
}
render() {
return html`
<div class="examples-container">
<!-- Radio Group -->
<section class="example-section">
<h3>Radio Group (Single Selection)</h3>
<ag-selection-button-group
type="radio"
name="payment-method"
legend="Select payment method"
shape="rounded"
@selection-change=${this._handleRadioChange}
>
<ag-selection-button value="card" label="Credit Card">
Credit Card
</ag-selection-button>
<ag-selection-button value="paypal" label="PayPal">
PayPal
</ag-selection-button>
<ag-selection-button value="bank" label="Bank Transfer">
Bank Transfer
</ag-selection-button>
</ag-selection-button-group>
<p class="selection-output">Selected: ${this.radioSelection || 'None'}</p>
</section>
<!-- Checkbox Group -->
<section class="example-section">
<h3>Checkbox Group (Multiple Selection)</h3>
<ag-selection-button-group
type="checkbox"
name="toppings"
legend="Select toppings"
shape="rounded"
@selection-change=${this._handleCheckboxChange}
>
<ag-selection-button value="cheese" label="Extra Cheese">
Extra Cheese
</ag-selection-button>
<ag-selection-button value="pepperoni" label="Pepperoni">
Pepperoni
</ag-selection-button>
<ag-selection-button value="mushrooms" label="Mushrooms">
Mushrooms
</ag-selection-button>
<ag-selection-button value="olives" label="Olives">
Olives
</ag-selection-button>
</ag-selection-button-group>
<p class="selection-output">Selected: ${this.checkboxSelection.join(', ') || 'None'}</p>
</section>
<!-- Theme Variants -->
<section class="example-section">
<h3>Theme Variants</h3>
<div class="theme-grid">
<div>
<p class="theme-label">Default (Primary)</p>
<ag-selection-button-group
type="radio"
name="theme-default"
legend="Default theme"
legend-hidden
shape="rounded"
>
<ag-selection-button value="a" label="Option A">A</ag-selection-button>
<ag-selection-button value="b" label="Option B">B</ag-selection-button>
</ag-selection-button-group>
</div>
<div>
<p class="theme-label">Success</p>
<ag-selection-button-group
type="radio"
name="theme-success"
legend="Success theme"
legend-hidden
theme="success"
shape="rounded"
>
<ag-selection-button value="a" label="Option A">A</ag-selection-button>
<ag-selection-button value="b" label="Option B">B</ag-selection-button>
</ag-selection-button-group>
</div>
<div>
<p class="theme-label">Info</p>
<ag-selection-button-group
type="radio"
name="theme-info"
legend="Info theme"
legend-hidden
theme="info"
shape="rounded"
>
<ag-selection-button value="a" label="Option A">A</ag-selection-button>
<ag-selection-button value="b" label="Option B">B</ag-selection-button>
</ag-selection-button-group>
</div>
<div>
<p class="theme-label">Warning</p>
<ag-selection-button-group
type="radio"
name="theme-warning"
legend="Warning theme"
legend-hidden
theme="warning"
shape="rounded"
>
<ag-selection-button value="a" label="Option A">A</ag-selection-button>
<ag-selection-button value="b" label="Option B">B</ag-selection-button>
</ag-selection-button-group>
</div>
<div>
<p class="theme-label">Error</p>
<ag-selection-button-group
type="radio"
name="theme-error"
legend="Error theme"
legend-hidden
theme="error"
shape="rounded"
>
<ag-selection-button value="a" label="Option A">A</ag-selection-button>
<ag-selection-button value="b" label="Option B">B</ag-selection-button>
</ag-selection-button-group>
</div>
<div>
<p class="theme-label">Monochrome</p>
<ag-selection-button-group
type="radio"
name="theme-monochrome"
legend="Monochrome theme"
legend-hidden
theme="monochrome"
shape="rounded"
>
<ag-selection-button value="a" label="Option A">A</ag-selection-button>
<ag-selection-button value="b" label="Option B">B</ag-selection-button>
</ag-selection-button-group>
</div>
</div>
</section>
<!-- Size Variants -->
<section class="example-section">
<h3>Size Variants</h3>
<div class="size-grid">
<div>
<p class="size-label">Small (sm)</p>
<ag-selection-button-group
type="radio"
name="size-sm"
legend="Small size"
legend-hidden
size="sm"
shape="rounded"
>
<ag-selection-button value="a" label="Option A">Option A</ag-selection-button>
<ag-selection-button value="b" label="Option B">Option B</ag-selection-button>
</ag-selection-button-group>
</div>
<div>
<p class="size-label">Medium (md) - Default</p>
<ag-selection-button-group
type="radio"
name="size-md"
legend="Medium size"
legend-hidden
size="md"
shape="rounded"
>
<ag-selection-button value="a" label="Option A">Option A</ag-selection-button>
<ag-selection-button value="b" label="Option B">Option B</ag-selection-button>
</ag-selection-button-group>
</div>
<div>
<p class="size-label">Large (lg)</p>
<ag-selection-button-group
type="radio"
name="size-lg"
legend="Large size"
legend-hidden
size="lg"
shape="rounded"
>
<ag-selection-button value="a" label="Option A">Option A</ag-selection-button>
<ag-selection-button value="b" label="Option B">Option B</ag-selection-button>
</ag-selection-button-group>
</div>
</div>
</section>
<!-- Shape Variants -->
<section class="example-section">
<h3>Shape Variants</h3>
<div class="shape-grid">
<div>
<p class="shape-label">Default (rectangular)</p>
<ag-selection-button-group
type="radio"
name="shape-default"
legend="Default shape"
legend-hidden
>
<ag-selection-button value="a" label="Option A">Option A</ag-selection-button>
<ag-selection-button value="b" label="Option B">Option B</ag-selection-button>
</ag-selection-button-group>
</div>
<div>
<p class="shape-label">Rounded</p>
<ag-selection-button-group
type="radio"
name="shape-rounded"
legend="Rounded shape"
legend-hidden
shape="rounded"
>
<ag-selection-button value="a" label="Option A">Option A</ag-selection-button>
<ag-selection-button value="b" label="Option B">Option B</ag-selection-button>
</ag-selection-button-group>
</div>
<div>
<p class="shape-label">Capsule (pill)</p>
<ag-selection-button-group
type="radio"
name="shape-capsule"
legend="Capsule shape"
legend-hidden
shape="capsule"
>
<ag-selection-button value="a" label="Option A">Option A</ag-selection-button>
<ag-selection-button value="b" label="Option B">Option B</ag-selection-button>
</ag-selection-button-group>
</div>
</div>
</section>
<!-- Disabled Group State -->
<section class="example-section">
<h3>Disabled Group State</h3>
<ag-selection-button-group
type="radio"
name="disabled-group-example"
legend="Disabled group"
shape="rounded"
disabled
>
<ag-selection-button value="a" label="Option A">Option A</ag-selection-button>
<ag-selection-button value="b" label="Option B">Option B</ag-selection-button>
<ag-selection-button value="c" label="Option C">Option C</ag-selection-button>
</ag-selection-button-group>
</section>
<!-- Disabled Buttons State -->
<section class="example-section">
<h3>Disabled Individual Buttons State</h3>
<ag-selection-button-group
type="radio"
name="disabled-buttons-example"
legend="Disabled individual buttons"
shape="rounded"
>
<ag-selection-button value="a" label="Option A">Option A</ag-selection-button>
<ag-selection-button disabled value="b" label="Option B">Option B</ag-selection-button>
<ag-selection-button value="c" label="Option C">Option C</ag-selection-button>
<ag-selection-button disabled value="d" label="Option D">Option D</ag-selection-button>
<ag-selection-button value="e" label="Option E">Option E</ag-selection-button>
</ag-selection-button-group>
</section>
</div>
`;
}
}
customElements.define('selection-button-group-lit-examples', SelectionButtonGroupLitExamples);
Interactive Preview: Click the "Open in StackBlitz" button below to see this example running live in an interactive playground.
View React Code
import { useState } from 'react';
import { ReactSelectionButtonGroup } from 'agnosticui-core/selection-button-group/react';
import { ReactSelectionButton } from 'agnosticui-core/selection-button/react';
export default function SelectionButtonGroupReactExamples() {
const [radioSelection, setRadioSelection] = useState('');
const [checkboxSelection, setCheckboxSelection] = useState([]);
const handleRadioChange = (e) => {
setRadioSelection(e.detail.selectedValues[0] || '');
};
const handleCheckboxChange = (e) => {
setCheckboxSelection(e.detail.selectedValues);
};
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
{/* Radio Group */}
<section style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
<h3 style={{ margin: 0, fontSize: '1rem', fontWeight: 600 }}>
Radio Group (Single Selection)
</h3>
<ReactSelectionButtonGroup
type="radio"
name="payment-method"
legend="Select payment method"
shape="rounded"
onSelectionChange={handleRadioChange}
>
<ReactSelectionButton value="card" label="Credit Card">
Credit Card
</ReactSelectionButton>
<ReactSelectionButton value="paypal" label="PayPal">
PayPal
</ReactSelectionButton>
<ReactSelectionButton value="bank" label="Bank Transfer">
Bank Transfer
</ReactSelectionButton>
</ReactSelectionButtonGroup>
<p style={{ margin: 0, fontSize: '0.875rem', color: '#666' }}>
Selected: {radioSelection || 'None'}
</p>
</section>
{/* Checkbox Group */}
<section style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
<h3 style={{ margin: 0, fontSize: '1rem', fontWeight: 600 }}>
Checkbox Group (Multiple Selection)
</h3>
<ReactSelectionButtonGroup
type="checkbox"
name="toppings"
legend="Select toppings"
shape="rounded"
onSelectionChange={handleCheckboxChange}
>
<ReactSelectionButton value="cheese" label="Extra Cheese">
Extra Cheese
</ReactSelectionButton>
<ReactSelectionButton value="pepperoni" label="Pepperoni">
Pepperoni
</ReactSelectionButton>
<ReactSelectionButton value="mushrooms" label="Mushrooms">
Mushrooms
</ReactSelectionButton>
<ReactSelectionButton value="olives" label="Olives">
Olives
</ReactSelectionButton>
</ReactSelectionButtonGroup>
<p style={{ margin: 0, fontSize: '0.875rem', color: '#666' }}>
Selected: {checkboxSelection.join(', ') || 'None'}
</p>
</section>
{/* Theme Variants */}
<section style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
<h3 style={{ margin: 0, fontSize: '1rem', fontWeight: 600 }}>Theme Variants</h3>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '1rem' }}>
<div>
<p style={{ margin: '0 0 0.5rem 0', fontSize: '0.875rem', color: '#666' }}>Default (Primary)</p>
<ReactSelectionButtonGroup
type="radio"
name="theme-default"
legend="Default theme"
legendHidden
shape="rounded"
>
<ReactSelectionButton value="a" label="Option A">A</ReactSelectionButton>
<ReactSelectionButton value="b" label="Option B">B</ReactSelectionButton>
</ReactSelectionButtonGroup>
</div>
<div>
<p style={{ margin: '0 0 0.5rem 0', fontSize: '0.875rem', color: '#666' }}>Success</p>
<ReactSelectionButtonGroup
type="radio"
name="theme-success"
legend="Success theme"
legendHidden
theme="success"
shape="rounded"
>
<ReactSelectionButton value="a" label="Option A">A</ReactSelectionButton>
<ReactSelectionButton value="b" label="Option B">B</ReactSelectionButton>
</ReactSelectionButtonGroup>
</div>
<div>
<p style={{ margin: '0 0 0.5rem 0', fontSize: '0.875rem', color: '#666' }}>Info</p>
<ReactSelectionButtonGroup
type="radio"
name="theme-info"
legend="Info theme"
legendHidden
theme="info"
shape="rounded"
>
<ReactSelectionButton value="a" label="Option A">A</ReactSelectionButton>
<ReactSelectionButton value="b" label="Option B">B</ReactSelectionButton>
</ReactSelectionButtonGroup>
</div>
<div>
<p style={{ margin: '0 0 0.5rem 0', fontSize: '0.875rem', color: '#666' }}>Warning</p>
<ReactSelectionButtonGroup
type="radio"
name="theme-warning"
legend="Warning theme"
legendHidden
theme="warning"
shape="rounded"
>
<ReactSelectionButton value="a" label="Option A">A</ReactSelectionButton>
<ReactSelectionButton value="b" label="Option B">B</ReactSelectionButton>
</ReactSelectionButtonGroup>
</div>
<div>
<p style={{ margin: '0 0 0.5rem 0', fontSize: '0.875rem', color: '#666' }}>Error</p>
<ReactSelectionButtonGroup
type="radio"
name="theme-error"
legend="Error theme"
legendHidden
theme="error"
shape="rounded"
>
<ReactSelectionButton value="a" label="Option A">A</ReactSelectionButton>
<ReactSelectionButton value="b" label="Option B">B</ReactSelectionButton>
</ReactSelectionButtonGroup>
</div>
<div>
<p style={{ margin: '0 0 0.5rem 0', fontSize: '0.875rem', color: '#666' }}>Monochrome</p>
<ReactSelectionButtonGroup
type="radio"
name="theme-monochrome"
legend="Monochrome theme"
legendHidden
theme="monochrome"
shape="rounded"
>
<ReactSelectionButton value="a" label="Option A">A</ReactSelectionButton>
<ReactSelectionButton value="b" label="Option B">B</ReactSelectionButton>
</ReactSelectionButtonGroup>
</div>
</div>
</section>
{/* Size Variants */}
<section style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
<h3 style={{ margin: 0, fontSize: '1rem', fontWeight: 600 }}>Size Variants</h3>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '1rem' }}>
<div>
<p style={{ margin: '0 0 0.5rem 0', fontSize: '0.875rem', color: '#666' }}>Small (sm)</p>
<ReactSelectionButtonGroup
type="radio"
name="size-sm"
legend="Small size"
legendHidden
size="sm"
shape="rounded"
>
<ReactSelectionButton value="a" label="Option A">Option A</ReactSelectionButton>
<ReactSelectionButton value="b" label="Option B">Option B</ReactSelectionButton>
</ReactSelectionButtonGroup>
</div>
<div>
<p style={{ margin: '0 0 0.5rem 0', fontSize: '0.875rem', color: '#666' }}>Medium (md) - Default</p>
<ReactSelectionButtonGroup
type="radio"
name="size-md"
legend="Medium size"
legendHidden
size="md"
shape="rounded"
>
<ReactSelectionButton value="a" label="Option A">Option A</ReactSelectionButton>
<ReactSelectionButton value="b" label="Option B">Option B</ReactSelectionButton>
</ReactSelectionButtonGroup>
</div>
<div>
<p style={{ margin: '0 0 0.5rem 0', fontSize: '0.875rem', color: '#666' }}>Large (lg)</p>
<ReactSelectionButtonGroup
type="radio"
name="size-lg"
legend="Large size"
legendHidden
size="lg"
shape="rounded"
>
<ReactSelectionButton value="a" label="Option A">Option A</ReactSelectionButton>
<ReactSelectionButton value="b" label="Option B">Option B</ReactSelectionButton>
</ReactSelectionButtonGroup>
</div>
</div>
</section>
{/* Shape Variants */}
<section style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
<h3 style={{ margin: 0, fontSize: '1rem', fontWeight: 600 }}>Shape Variants</h3>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '1rem' }}>
<div>
<p style={{ margin: '0 0 0.5rem 0', fontSize: '0.875rem', color: '#666' }}>Default (rectangular)</p>
<ReactSelectionButtonGroup
type="radio"
name="shape-default"
legend="Default shape"
legendHidden
>
<ReactSelectionButton value="a" label="Option A">Option A</ReactSelectionButton>
<ReactSelectionButton value="b" label="Option B">Option B</ReactSelectionButton>
</ReactSelectionButtonGroup>
</div>
<div>
<p style={{ margin: '0 0 0.5rem 0', fontSize: '0.875rem', color: '#666' }}>Rounded</p>
<ReactSelectionButtonGroup
type="radio"
name="shape-rounded"
legend="Rounded shape"
legendHidden
shape="rounded"
>
<ReactSelectionButton value="a" label="Option A">Option A</ReactSelectionButton>
<ReactSelectionButton value="b" label="Option B">Option B</ReactSelectionButton>
</ReactSelectionButtonGroup>
</div>
<div>
<p style={{ margin: '0 0 0.5rem 0', fontSize: '0.875rem', color: '#666' }}>Capsule (pill)</p>
<ReactSelectionButtonGroup
type="radio"
name="shape-capsule"
legend="Capsule shape"
legendHidden
shape="capsule"
>
<ReactSelectionButton value="a" label="Option A">Option A</ReactSelectionButton>
<ReactSelectionButton value="b" label="Option B">Option B</ReactSelectionButton>
</ReactSelectionButtonGroup>
</div>
</div>
</section>
{/* Disabled State */}
<section style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
<h3 style={{ margin: 0, fontSize: '1rem', fontWeight: 600 }}>Disabled Group State</h3>
<ReactSelectionButtonGroup
type="radio"
name="disabled-example"
legend="Disabled group"
shape="rounded"
disabled
>
<ReactSelectionButton value="a" label="Option A">Option A</ReactSelectionButton>
<ReactSelectionButton value="b" label="Option B">Option B</ReactSelectionButton>
<ReactSelectionButton value="c" label="Option C">Option C</ReactSelectionButton>
</ReactSelectionButtonGroup>
</section>
{/* Disabled State */}
<section style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
<h3 style={{ margin: 0, fontSize: '1rem', fontWeight: 600 }}>Disabled Individual Button State</h3>
<ReactSelectionButtonGroup
type="radio"
name="disabled-buttons-example"
legend="Disabled buttons"
shape="rounded"
>
<ReactSelectionButton value="a" label="Option A">Option A</ReactSelectionButton>
<ReactSelectionButton disabled value="b" label="Option B">Option B</ReactSelectionButton>
<ReactSelectionButton value="c" label="Option C">Option C</ReactSelectionButton>
<ReactSelectionButton disabled value="c" label="Option D">Option D</ReactSelectionButton>
<ReactSelectionButton value="c" label="Option E">Option E</ReactSelectionButton>
</ReactSelectionButtonGroup>
</section>
</div>
);
}
Usage
TIP
The framework examples below import AgnosticUI as an npm package. Alternatively, you can use the CLI for complete control, AI/LLM visibility, and full code ownership:
npx ag init --framework FRAMEWORK # react, vue, lit, svelte, etc.
npx ag add SelectionButtonGroup
npx ag add SelectionButtonThe CLI copies source code directly into your project, giving you full visibility and control. After running npx ag add, you'll receive exact import instructions.
Vue
<template>
<VueSelectionButtonGroup
type="radio"
name="payment"
legend="Select payment method"
shape="rounded"
@selection-change="handleChange"
>
<VueSelectionButton value="card" label="Credit Card">
Credit Card
</VueSelectionButton>
<VueSelectionButton value="paypal" label="PayPal">
PayPal
</VueSelectionButton>
</VueSelectionButtonGroup>
</template>
<script setup>
import { VueSelectionButtonGroup } from 'agnosticui-core/selection-button-group/vue';
import { VueSelectionButton } from 'agnosticui-core/selection-button/vue';
const handleChange = (e) => {
console.log('Selected:', e.detail.selectedValues);
};
</script>React
import { ReactSelectionButtonGroup } from "agnosticui-core/selection-button-group/react";
import { ReactSelectionButton } from "agnosticui-core/selection-button/react";
export default function Example() {
const handleChange = (e) => {
console.log('Selected:', e.detail.selectedValues);
};
return (
<ReactSelectionButtonGroup
type="radio"
name="payment"
legend="Select payment method"
shape="rounded"
onSelectionChange={handleChange}
>
<ReactSelectionButton value="card" label="Credit Card">
Credit Card
</ReactSelectionButton>
<ReactSelectionButton value="paypal" label="PayPal">
PayPal
</ReactSelectionButton>
</ReactSelectionButtonGroup>
);
}Lit (Web Components)
<script type="module">
import "agnosticui-core/selection-button-group";
import "agnosticui-core/selection-button";
const group = document.querySelector('ag-selection-button-group');
group.addEventListener('selection-change', (e) => {
console.log('Selected:', e.detail.selectedValues);
});
</script>
<ag-selection-button-group type="radio" name="payment" legend="Select payment method" shape="rounded">
<ag-selection-button value="card" label="Credit Card">
Credit Card
</ag-selection-button>
<ag-selection-button value="paypal" label="PayPal">
PayPal
</ag-selection-button>
</ag-selection-button-group>Props
SelectionButtonGroup
| Prop | Type | Default | Description |
|---|---|---|---|
type | 'radio' | 'checkbox' | 'radio' | Selection mode |
name | string | '' | Input name attribute (required) |
legend | string | '' | Accessible group label |
legend-hidden | boolean | false | Visually hide legend |
theme | '' | 'success' | 'info' | 'warning' | 'error' | 'monochrome' | '' | Theme variant (empty = primary/blue) |
size | 'sm' | 'md' | 'lg' | 'md' | Button size |
shape | '' | 'rounded' | 'capsule' | '' | Button shape (empty = rectangular) |
value | string | '' | Controlled value (radio) |
values | string[] | [] | Controlled values (checkbox) |
disabled | boolean | false | Disable all buttons |
SelectionButton
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | '' | Unique value (required) |
label | string | '' | Accessible label (required) |
checked | boolean | false | Selection state (managed by group) |
disabled | boolean | false | Disable this button |
Events
selection-change
Fired when selection changes.
interface SelectionChangeEventDetail {
value: string; // Value that triggered the change
checked: boolean; // Whether the button is now selected
selectedValues: string[]; // All currently selected values
}Themes
The theme prop controls the color scheme for selected buttons:
| Theme | Description |
|---|---|
'' (default) | Primary blue - uses --ag-primary-* tokens |
success | Green - uses --ag-success-* tokens |
info | Cyan/blue - uses --ag-info-* tokens |
warning | Yellow/orange - uses --ag-warning-* tokens |
error | Red - uses --ag-danger-* tokens |
monochrome | Black/white - uses --ag-black and inverted tokens |
<!-- Success theme with capsule shape -->
<ag-selection-button-group type="radio" name="status" theme="success" shape="capsule">
...
</ag-selection-button-group>Sizes
| Size | Description |
|---|---|
sm | Small - compact height, smaller font |
md | Medium (default) - standard size |
lg | Large - taller height, larger font |
Shapes
| Shape | Description |
|---|---|
'' (default) | Rectangular with no border radius |
rounded | Moderate border radius |
capsule | Fully rounded (pill shape) |
Styling
CSS Custom Properties
/* Group layout */
--ag-selection-button-group-gap: var(--ag-space-2);
/* Button sizing (per size variant) */
/* Size-specific heights and padding are built into the component */
/* Button colors - unchecked */
/* Uses theme tokens (--ag-primary, --ag-success, etc.) for borders and text */
/* Button colors - checked */
/* Filled background using theme tokens */CSS Parts
SelectionButtonGroup
| Part | Description |
|---|---|
ag-selection-button-group-fieldset | The fieldset element |
ag-selection-button-group-legend | The legend element |
ag-selection-button-group-content | The content wrapper (flex container) |
SelectionButton
| Part | Description |
|---|---|
ag-selection-button-container | The outer clickable label |
ag-selection-button-control | The hidden input element |
ag-selection-button-indicator | The selection indicator (circle with dot for radio, circle with checkmark for checkbox) |
ag-selection-button-content | The slotted content wrapper |
CSS Parts Example
/* Custom gap between buttons */
ag-selection-button-group::part(ag-selection-button-group-content) {
gap: var(--ag-space-4);
}
/* Custom button styling */
ag-selection-button::part(ag-selection-button-container) {
font-weight: 600;
}
/* Hide the indicator for a cleaner look */
ag-selection-button::part(ag-selection-button-indicator) {
display: none;
}Accessibility
- Uses
<fieldset>and<legend>for proper group semantics - Each button has a required
labelprop for screen readers - Keyboard navigation:
- Arrow keys: Navigate between buttons (selects in radio mode)
- Space/Enter: Toggle selection
- Home/End: Jump to first/last button
- Focus ring visible on keyboard navigation
role="radiogroup"for radio mode,role="group"for checkbox mode
Comparison with SelectionCardGroup
| Feature | SelectionButtonGroup | SelectionCardGroup |
|---|---|---|
| Use case | Compact inline options | Rich content cards |
| Size variants | Yes (sm/md/lg) | No |
| Shape variants | Yes (rounded/capsule) | No |
| Content | Text labels | Rich slotted content |
| Layout | Inline flex | Grid |