S
Toggle Field

Button Checkbox

Multiple selection using button-style toggles for visual multi-select.

stable
checkbox button multi-select toggle

Interactive demo of button checkbox field

Select all days you are available

Choose up to 4 amenities

/**
 * Button Checkbox Field Demo - Interactive examples of button checkbox fields
 */

import { Form, FormBuilder } from '@saastro/forms';

import { FormProvider } from '@/components/FormProvider';
import { TooltipProvider } from '@/components/ui/tooltip';

const config = FormBuilder.create('button-checkbox-demo')
  .layout('manual')
  .columns(12)
  .addField('days', (f) =>
    f
      .type('button-checkbox')
      .label('Available Days')
      .helperText('Select all days you are available')
      .options([
        { label: 'Mon', value: 'mon' },
        { label: 'Tue', value: 'tue' },
        { label: 'Wed', value: 'wed' },
        { label: 'Thu', value: 'thu' },
        { label: 'Fri', value: 'fri' },
        { label: 'Sat', value: 'sat' },
        { label: 'Sun', value: 'sun' },
      ])
      .value(['mon', 'wed', 'fri'])
      .required('Select at least one day')
      .columns({ default: 12 }),
  )
  .addField('amenities', (f) =>
    f
      .type('button-checkbox')
      .label('Amenities')
      .helperText('Choose up to 4 amenities')
      .options([
        { label: 'WiFi', value: 'wifi' },
        { label: 'Parking', value: 'parking' },
        { label: 'Pool', value: 'pool' },
        { label: 'Gym', value: 'gym' },
        { label: 'Spa', value: 'spa' },
        { label: 'Restaurant', value: 'restaurant' },
      ])
      .required()
      .itemCount(1, 4)
      .columns({ default: 12 }),
  )
  .addField('sizes', (f) =>
    f
      .type('button-checkbox')
      .label('Available Sizes')
      .options([
        { label: 'XS', value: 'xs' },
        { label: 'S', value: 's' },
        { label: 'M', value: 'm' },
        { label: 'L', value: 'l' },
        { label: 'XL', value: 'xl' },
      ])
      .value(['s', 'm', 'l'])
      .optional()
      .columns({ default: 12 }),
  )
  .addStep('main', ['days', 'amenities', 'sizes'])
  .build();

export default function ButtonCheckboxDemo() {
  const handleSubmit = (data: Record<string, unknown>) => {
    console.log('Form submitted:', data);
    alert('Form submitted! Check console for data.');
  };

  return (
    <TooltipProvider>
      <FormProvider>
        <Form config={config} onSubmit={handleSubmit} className="space-y-4" />
      </FormProvider>
    </TooltipProvider>
  );
}

Overview

The button checkbox field presents checkbox options as toggleable buttons. Users can select multiple options with a more visual, compact interface than traditional checkboxes.

Usage

Basic Button Checkbox

import { FormBuilder } from '@saastro/forms';

const config = FormBuilder.create('form')
  .addField('days', (f) =>
    f
      .type('button-checkbox')
      .label('Available Days')
      .options([
        { label: 'Mon', value: 'mon' },
        { label: 'Tue', value: 'tue' },
        { label: 'Wed', value: 'wed' },
        { label: 'Thu', value: 'thu' },
        { label: 'Fri', value: 'fri' },
      ])
      .required('Select at least one day'),
  )
  .addStep('main', ['days'])
  .build();

With Default Values

.addField('features', (f) =>
  f.type('button-checkbox')
    .label('Features')
    .options([
      { label: 'WiFi', value: 'wifi' },
      { label: 'Parking', value: 'parking' },
      { label: 'Pool', value: 'pool' },
      { label: 'Gym', value: 'gym' },
    ])
    .value(['wifi', 'parking'])
    .optional()
)

With Selection Limits

.addField('toppings', (f) =>
  f.type('button-checkbox')
    .label('Toppings')
    .helperText('Choose up to 3 toppings')
    .options([
      { label: 'Cheese', value: 'cheese' },
      { label: 'Pepperoni', value: 'pepperoni' },
      { label: 'Mushrooms', value: 'mushrooms' },
      { label: 'Olives', value: 'olives' },
      { label: 'Peppers', value: 'peppers' },
    ])
    .required()
    .itemCount(1, 3)
)

JSON Configuration

{
  "type": "button-checkbox",
  "label": "Available Days",
  "options": [
    { "label": "Mon", "value": "mon" },
    { "label": "Tue", "value": "tue" },
    { "label": "Wed", "value": "wed" },
    { "label": "Thu", "value": "thu" },
    { "label": "Fri", "value": "fri" }
  ],
  "value": ["mon", "wed", "fri"],
  "schema": { "required": true, "minItems": 1 }
}

Props

PropTypeDefaultDescription
type'button-checkbox'-Field type (required)
labelstring-Group label
helperTextstring-Help text below field
optionsOption[]-Array of button options
valuestring[][]Default selected values
optionsClassNamestring-CSS classes for buttons container
columnsPartial<Record<Breakpoint, number>>-Grid columns by breakpoint
disabledboolean | function | ConditionGroupfalseDisable all buttons
hiddenboolean | function | ConditionGroup | ResponsivefalseHide the field

Validation

At Least One Selection

.addField('skills', (f) =>
  f.type('button-checkbox')
    .label('Skills')
    .options([...])
    .required('Select at least one skill')
)

Selection Range

.addField('preferences', (f) =>
  f.type('button-checkbox')
    .label('Preferences')
    .options([...])
    .required()
    .itemCount(2, 4)
)

Styling

Custom Classes

.addField('days', (f) =>
  f.type('button-checkbox')
    .label('Available Days')
    .options([...])
    .required()
    .classNames({
      wrapper: 'bg-muted/30 p-4 rounded-lg',
      label: 'text-lg font-semibold mb-3',
      error: 'text-destructive text-sm',
    })
)

Options Layout with optionsClassName

Control button arrangement:

{
  "type": "button-checkbox",
  "label": "Days",
  "optionsClassName": "flex flex-wrap gap-2",
  "options": [...]
}

Responsive Layout

.addField('amenities', (f) =>
  f.type('button-checkbox')
    .label('Amenities')
    .options([...])
    .columns({ default: 12, md: 8 })
)

JSON Styling

{
  "type": "button-checkbox",
  "label": "Days",
  "wrapper_className": "bg-muted/30 p-4 rounded-lg",
  "label_className": "text-lg font-semibold",
  "optionsClassName": "inline-flex flex-wrap gap-1",
  "columns": { "default": 12 }
}

Accessibility

  • Uses Radix UI ToggleGroup (multiple mode)
  • Keyboard navigation
  • ARIA roles for toggle buttons
  • Focus visible states