- Checkbox Group
- Examples
- Basic Checkbox Group
- Help Text
- Label with Tooltip
- Horizontal Checkbox Group
- Contained Checkbox Group
- Disabling Options
- Validation
- Custom Validity
- Usage
- When to Use a Checkbox Group
- When to Use Something Else
- Labels, Help Text, Etc.
- Testing
- With Cypress
- Component Props
- Slots
- Events
- Methods
- CSS Parts
Checkbox Group
sl-checkbox-group
Checkbox groups are used to group multiple checkboxes so they function as a single form control.
Examples
Basic Checkbox Group
A basic checkbox group lays out multiple checkbox items vertically.
<sl-checkbox-group label="Financial products permissions" name="a"> <sl-checkbox value="initiate-outbound">Initiate outbound transfers</sl-checkbox> <sl-checkbox value="approve-outbound">Approve outbound transfers </sl-checkbox> <sl-checkbox value="export">Export transactions</sl-checkbox> </sl-checkbox-group>
sl-checkbox-group[ label="Financial products permissions" name="a" ] sl-checkbox value="initiate-outbound" Initiate outbound transfers sl-checkbox value="approve-outbound" Approve outbound transfers sl-checkbox value="export" Export transactions
= ts_form_for ... do |f| = f.input :a, as: :check_boxes, label: "Financial products permissions", collection: [ ["Initiate outbound transfers", "initiate-outbound"], ["Approve outbound transfers", "approve-outbound"], ["Export transactions", "export"], ]
import SlRadio from '@teamshares/shoelace/dist/react/radio'; import SlRadioGroup from '@teamshares/shoelace/dist/react/radio-group'; const App = () => ( <SlRadioGroup label="Select an option" name="a" value="1"> <SlRadio value="1">Option 1</SlRadio> <SlRadio value="2">Option 2</SlRadio> <SlRadio value="3">Option 3</SlRadio> </SlRadioGroup> );
Help Text
Add descriptive help text to a checkbox group with the help-text
attribute. For help texts that
contain HTML, use the help-text
slot instead.
<sl-checkbox-group label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" name="a"> <sl-checkbox value="initiate-outbound">Initiate outbound transfers</sl-checkbox> <sl-checkbox value="approve-outbound">Approve outbound transfers </sl-checkbox> <sl-checkbox value="export">Export transactions</sl-checkbox> </sl-checkbox-group>
sl-checkbox-group[ label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" name="a" ] sl-checkbox value="initiate-outbound" Initiate outbound transfers sl-checkbox value="approve-outbound" Approve outbound transfers sl-checkbox value="export" Export transactions
= ts_form_for ... do |f| = f.input :a, as: :check_boxes, label: "Financial products permissions", collection: [ ["Initiate outbound transfers", "initiate-outbound"], ["Approve outbound transfers", "approve-outbound"], ["Export transactions", "export"], ], wrapper_html: { "help-text": "Outbound transfers require separate initiators and approvers", }
import SlRadio from '@teamshares/shoelace/dist/react/radio'; import SlRadioGroup from '@teamshares/shoelace/dist/react/radio-group'; const App = () => ( <SlRadioGroup label="Select an option" name="a" value="1"> <SlRadio value="1">Option 1</SlRadio> <SlRadio value="2">Option 2</SlRadio> <SlRadio value="3">Option 3</SlRadio> </SlRadioGroup> );
Label with Tooltip
Use the label-tooltip
attribute to add text that appears in a tooltip triggered by an info icon
next to the label.
Usage: Use a label tooltip to provide helpful but non-essential instructions or examples to guide people when making a selection from the checkbox group. Use help text to communicate instructions or requirements for making a selection without errors.
<sl-checkbox-group name="a" label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" label-tooltip="These apply to cash account only"> <sl-checkbox value="initiate-outbound">Initiate outbound transfers</sl-checkbox> <sl-checkbox value="approve-outbound">Approve outbound transfers </sl-checkbox> <sl-checkbox value="export">Export transactions</sl-checkbox> </sl-checkbox-group>
sl-checkbox-group[ name="a" label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" label-tooltip="These apply to cash account only" ] sl-checkbox value="initiate-outbound" Initiate outbound transfers sl-checkbox value="approve-outbound" Approve outbound transfers sl-checkbox value="export" Export transactions
= ts_form_for ... do |f| = f.input :a, as: :check_boxes, label: "Financial products permissions", collection: [ ["Initiate outbound transfers", "initiate-outbound"], ["Approve outbound transfers", "approve-outbound"], ["Export transactions", "export"], ], wrapper_html: { "help-text": "Outbound transfers require separate initiators and approvers", "label-tooltip": "These apply to cash account only", }
import SlRadio from '@teamshares/shoelace/dist/react/radio'; import SlRadioGroup from '@teamshares/shoelace/dist/react/radio-group'; const App = () => ( <SlRadioGroup label="Select an option" name="a" value="1"> <SlRadio value="1">Option 1</SlRadio> <SlRadio value="2">Option 2</SlRadio> <SlRadio value="3">Option 3</SlRadio> </SlRadioGroup> );
Horizontal Checkbox Group
Use the horizontal
attribute to lay out multiple checkbox items horizontally.
Making the horizontal checkbox group responsive: Use a container query to adjust the
layout of the checkbox group’s form-control-input
part (which wraps the checkbox items) at a
custom target breakpoint (the container’s width when the horizontal layout breaks). In the example below,
a container query checks the width of the checkbox group container and switches the layout to vertical
(setting flex-direction
to column
) when the container becomes too narrow for a
horizontal layout.
<sl-checkbox-group name="a" id="permissions" label="Financial products permissions" horizontal> <sl-checkbox value="manage-transfers">Manage transfers</sl-checkbox> <sl-checkbox value="export">Export transactions</sl-checkbox> </sl-checkbox-group> <style> sl-checkbox-group[id="permissions"] { container-type: inline-size; container-name: permissions; } @container permissions (max-width: 400px) { sl-checkbox-group[id="permissions"]::part(form-control-input) { flex-direction: column; } } </style>
sl-checkbox-group[ name="a" id="permissions" label="Financial products permissions" ] sl-checkbox value="manage-transfers" Manage transfers sl-checkbox value="export" Export transactions css: sl-checkbox-group[id="permissions"] { container-type: inline-size; container-name: permissions; } @container permissions (max-width: 400px) { sl-checkbox-group[id="permissions"]::part(form-control-input) { flex-direction: column; } }
= ts_form_for ... do |f| = f.input :a, as: :check_boxes, label: "Financial products permissions", collection: [ ["Manage transfers", "manage-transfers"], ["Export transactions", "export"], ], wrapper_html: { horizontal: true, id: "permissions", }
import SlRadio from '@teamshares/shoelace/dist/react/radio'; import SlRadioGroup from '@teamshares/shoelace/dist/react/radio-group'; const App = () => ( <SlRadioGroup label="Select an option" name="a" value="1"> <SlRadio value="1">Option 1</SlRadio> <SlRadio value="2">Option 2</SlRadio> <SlRadio value="3">Option 3</SlRadio> </SlRadioGroup> );
Contained Checkbox Group
Use the contained
attribute to draw a card-like container around each checkbox item in the
checkbox group. This style is useful for giving more emphasis to the list of options.
This option can be combined with the horizontal
attribute.
<sl-checkbox-group name="a" label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" contained> <sl-checkbox value="initiate-outbound">Initiate outbound transfers</sl-checkbox> <sl-checkbox value="approve-outbound">Approve outbound transfers </sl-checkbox> <sl-checkbox value="export">Export transactions</sl-checkbox> </sl-checkbox-group> <br/> <br/> <sl-checkbox-group name="b" label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" contained horizontal> <sl-checkbox value="initiate-outbound">Initiate outbound transfers</sl-checkbox> <sl-checkbox value="approve-outbound">Approve outbound transfers </sl-checkbox> </sl-checkbox-group>
sl-checkbox-group[ name="a" label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" contained=true ] sl-checkbox value="initiate-outbound" Initiate outbound transfers sl-checkbox value="approve-outbound" Approve outbound transfers sl-checkbox value="export" Export transactions br br sl-checkbox-group[ name="b" label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" contained=true horizontal=true ] sl-checkbox value="initiate-outbound" Initiate outbound transfers sl-checkbox value="approve-outbound" Approve outbound transfers
= ts_form_for ... do |f| = f.input :a, as: :check_boxes, label: "Financial products permissions", collection: [ ["Initiate outbound transfers", "initiate-outbound"], ["Approve outbound transfers", "approve-outbound"], ["Export transactions", "export"], ], wrapper_html: { "help-text": "Outbound transfers require separate initiators and approvers", contained: true, } = f.input :b, as: :check_boxes, label: "Financial products permissions", collection: [ ["Initiate outbound transfers", "initiate-outbound"], ["Approve outbound transfers", "approve-outbound"], ], wrapper_html: { "help-text": "Outbound transfers require separate initiators and approvers", contained: true, horizontal: true, }
import SlRadio from '@teamshares/shoelace/dist/react/radio'; import SlRadioGroup from '@teamshares/shoelace/dist/react/radio-group'; const App = () => ( <SlRadioGroup label="Select an option" name="a" value="1"> <SlRadio value="1">Option 1</SlRadio> <SlRadio value="2">Option 2</SlRadio> <SlRadio value="3">Option 3</SlRadio> </SlRadioGroup> );
When checkboxes are wrapped with the Checkbox Group , adding the
contained
attribute to the parent Checkbox Group or to any checkbox in the group
will create contained
checkboxes for the entire group.
Disabling Options
Checkboxes can be disabled by adding the disabled
attribute to the respective options inside
the checkbox group.
<sl-checkbox-group name="a" label="Financial products permissions" help-text="Exporting is currently disabled for all users" required> <sl-checkbox value="initiate-outbound">Initiate outbound transfers</sl-checkbox> <sl-checkbox value="approve-outbound">Approve outbound transfers </sl-checkbox> <sl-checkbox value="export" disabled>Export transactions</sl-checkbox> </sl-checkbox-group>
sl-checkbox-group[ name="a" label="Financial products permissions" ] sl-checkbox value="initiate-outbound" Initiate outbound transfers sl-checkbox value="approve-outbound" Approve outbound transfers sl-checkbox value="export" disabled=true Export transactions
/* When rendering `sl-checkbox-group` with ts_form_for, pass additional attributes such as `disabled` and `description` as extra items in the collection array after the label and value. By default Simple Form will use the first item as the label and the second item as the value, then pass any additional array items as attributes on the `sl-checkbox`. */ = ts_form_for ... do |f| = f.input :a, as: :check_boxes, label: "Financial products permissions", collection: [ [ "Initiate outbound transfers", "initiate-outbound", ], [ "Approve outbound transfers", "approve-outbound", ], [ "Export transactions", "export", disabled: true, ], ],
import SlRadio from '@teamshares/shoelace/dist/react/radio'; import SlRadioGroup from '@teamshares/shoelace/dist/react/radio-group'; const App = () => ( <SlRadioGroup label="Select an option" name="a" value="1"> <SlRadio value="1">Option 1</SlRadio> <SlRadio value="2">Option 2</SlRadio> <SlRadio value="3">Option 3</SlRadio> </SlRadioGroup> );
Validation
Set the required
attribute to make selecting at least one option mandatory. If at least one
value has not been selected, it will prevent the form from submitting and display an error message.
<form class="validation"> <sl-checkbox-group name="a" label="Select at least one option" required> <sl-checkbox value="option-1">Option 1</sl-checkbox> <sl-checkbox value="option-2">Option 2</sl-checkbox> <sl-checkbox value="option-3">Option 3</sl-checkbox> </sl-checkbox-group> <br /> <sl-button type="submit" variant="primary">Submit</sl-button> </form> <script type="module"> const form = document.querySelector('.validation'); // Wait for controls to be defined before attaching form listeners await Promise.all([ customElements.whenDefined('sl-checkbox-group'), ]).then(() => { form.addEventListener('submit', event => { event.preventDefault(); alert('All fields are valid!'); }); }); </script>
form.validation sl-radio-group[ name="a" label="Select at least one option" required=true ] sl-radio value="1" Option 1 sl-radio value="2" Option 2 sl-radio value="3" Option 3 br sl-button[ type="submit" variant="primary" ] | Submit javascript: const form = document.querySelector(.validation); // Wait for controls to be defined before attaching form listeners await Promise.all([ customElements.whenDefined('sl-checkbox-group'), ]).then(() => { // Handle form submit form.addEventListener(submit, event => { event.preventDefault(); alert(All fields are valid!); }); });
= ts_form_for ... do |f| = f.input :a, as: :check_boxes, label: "Select at least one option", collection: [ ["Option 1", "1"], ["Option 2", "2"], ["Option 3", "3"], ], wrapper_html: { required: true, } // ts_form_for automatically sets the form's submit button to variant="primary" = f.submit "Submit"
import SlButton from '@teamshares/shoelace/dist/react/button'; import SlIcon from '@teamshares/shoelace/dist/react/icon'; import SlRadio from '@teamshares/shoelace/dist/react/radio'; import SlRadioGroup from '@teamshares/shoelace/dist/react/radio-group'; const App = () => { function handleSubmit(event) { event.preventDefault(); alert('All fields are valid!'); } return ( <form class="custom-validity" onSubmit={handleSubmit}> <SlRadioGroup label="Select an option" name="a" required onSlChange={handleChange}> <SlRadio value="1"> Option 1 </SlRadio> <SlRadiovalue="2"> Option 2 </SlRadio> <SlRadio value="3"> Option 3 </SlRadio> </SlRadioGroup> <br /> <SlButton type="submit" variant="primary"> Submit </SlButton> </form> ); };
Custom Validity
Use the setCustomValidity()
method to set a custom validation message. This will prevent the
form from submitting and make the browser display the error message you provide. To clear the error, call
this function with an empty string.
<form class="custom-validity"> <sl-checkbox-group name="a" label="Select the third option" required> <sl-checkbox value="option-1">You can optionally choose me</sl-checkbox> <sl-checkbox value="option-2">I'm optional too</sl-checkbox> <sl-checkbox value="option-3">You must choose me</sl-checkbox> </sl-checkbox-group> <br /> <sl-button type="submit" variant="primary">Submit</sl-button> </form> <script type="module"> const form = document.querySelector('.custom-validity'); const checkboxGroup = form.querySelector('sl-checkbox-group'); const errorMessage = 'You must choose the last option'; // Set initial validity as soon as the element is defined customElements.whenDefined('sl-checkbox').then(() => { checkboxGroup.setCustomValidity(errorMessage); }); // Update validity when a selection is made form.addEventListener('sl-change', () => { const isValid = checkboxGroup.value.some(value => value.includes('option-3')); checkboxGroup.setCustomValidity(isValid ? '' : errorMessage); }); // Wait for controls to be defined before attaching form listeners await Promise.all([ customElements.whenDefined('sl-checkbox-group'), ]).then(() => { form.addEventListener('submit', event => { event.preventDefault(); alert('All fields are valid!'); }); }); </script>
form.validation sl-radio-group name="a" label="Select the third option" required=true sl-radio value="1" You can optionally choose me sl-radio value="2" I'm optional too sl-radio value="3" You must choose me br sl-button type="submit" variant="primary" Submit javascript: const form = document.querySelector(.custom-validity); const checkboxGroup = form.querySelector('sl-checkbox-group'); const errorMessage = 'You must choose the last option'; // Set initial validity as soon as the element is defined customElements.whenDefined('sl-checkbox').then(() => { checkboxGroup.setCustomValidity(errorMessage); }); // Update validity when a selection is made form.addEventListener('sl-change', () => { const isValid = checkboxGroup.value.some(value => value.includes('option-3')); checkboxGroup.setCustomValidity(isValid ? '' : errorMessage); }); // Wait for controls to be defined before attaching form listeners await Promise.all([ customElements.whenDefined('sl-checkbox-group'), ]).then(() => { // Handle form submit form.addEventListener(submit, event => { event.preventDefault(); alert(All fields are valid!); }); });
Usage
When to Use a Checkbox Group
- When you want people to choose one or more options from a list
- When presenting fewer than 7 options
- If letting people see all their options right away (without an additional click) is a priority
When to Use Something Else
- Use a radio group instead if presenting fewer than 5 to 7 options and you want to let people choose just one option
- Use a multi-select select instead if presenting more than 7 options or there isn’t enough room to present all the options
Labels, Help Text, Etc.
- For additional guidelines on checkbox and checkbox group labels, help text, and the label tooltip, refer to the Input component usage guidelines
Testing
With Cypress
Adding data-test-id
to a component
To test sl-checkbox-group
, add the data-test-id
attribute directly to the
component. To test checkbox items in the group, add data-test-id
to each item:
sl-checkbox-group[ label="Checkbox group text" name="input-name" data-test-id="checkbox-group-test" ] sl-checkbox[ value="option-1" data-test-id="item-test-1" ] | Option 1 sl-checkbox[ value="option-2" data-test-id="item-test-2" ] | Option 2 sl-checkbox[ value="option-3" data-test-id="item-test-3" ] | Option 3
To test sl-checkbox-group
implemented with ts_form_for
, add
data-test-id
to wrapper_html
. To test checkbox items in the group, add
data-test-id
to each item in the collection array:
= ts_form_for ... do |f| = f.input :input_name, as: :check_boxes, label: "Checkbox group text", collection: [ ["Option 1", :option-1, data: { test_id: "item-test-1" }], ["Option 2", :option-2, data: { test_id: "item-test-2" }], ["Option 3", :option-3, data: { test_id: "item-test-3" }], ], wrapper_html: { data: { test_id: "checkbox-group-test" } }
Cypress commands for sl-checkbox-group
To check any checkbox in the checkbox group:
cy.slCheckboxCheck(`[data-test-id="item-test-1"]`);
To uncheck any checkbox in a checkbox group:
cy.slCheckboxUncheck(`[data-test-id="item-test-1"]`);
To verify the checkbox group’s value, that certain items are checked:
cy.slCheckboxGroupValue(`[data-test-id="checkbox-group-test"]`, ["option-1", "option-2"]);
To verify the checkbox group’s value, that certain items are NOT checked:
cy.get(`[data-test-id="checkbox-group-test"]`).should("not.have.value", "option-3");
Component Props
Note: The following appear as options in the Properties table but are currently not part of the Teamshares Design System. Please check with the design team before using these options:
- Sizes
small
,large
Property | Default | Details |
---|---|---|
label
|
''
|
The checkbox group’s label. Required for proper accessibility. If you need to display HTML, use
the |
labelTooltip
label-tooltip
|
''
|
Text that appears in a tooltip next to the label. If you need to display HTML in the tooltip, use
the |
helpText
help-text
|
''
|
The checkbox groups’s help text. If you need to display HTML, use the |
name
|
''
|
The name of the checkbox group, submitted as a name/value pair with form data. |
value
|
[]
|
The current value of the checkbox group, submitted as a name/value pair with form data. |
size
|
'medium'
|
The checkbox group’s size. This size will be applied to all child checkboxes. |
horizontal
|
false
|
The checkbox group’s orientation. Changes the group’s layout from the default (vertical) to horizontal. |
contained
|
false
|
The checkbox group’s style. Changes the group’s style from the default (plain) style to the ‘contained’ style. This style will be applied to all child checkboxes. |
form
|
''
|
By default, form controls are associated with the nearest containing
|
required
|
false
|
Ensures at least one child checkbox is checked before allowing the containing form to submit. |
validity
|
— |
— Gets the validity state object |
validationMessage
|
— |
— Gets the validation message |
updateComplete
|
A read-only promise that resolves when the component has finished updating. |
Learn more about attributes and properties.
Slots
Name | Details |
---|---|
(default) | The default slot where <sl-checkbox> elements are placed. |
label
|
The checkbox group’s label. Required for proper accessibility. Alternatively, you can use the
label attribute.
|
label-tooltip
|
Used to add text that is displayed in a tooltip next to the label. Alternatively, you can use the
label-tooltip attribute.
|
help-text
|
Text that describes how to use the checkbox group. Alternatively, you can use the
help-text attribute.
|
Learn more about using slots.
Events
Name | Name | Name | React Event | Details | |
---|---|---|---|---|---|
sl-change
|
sl-change
|
sl-change
|
onSlChange
|
Emitted when the checkbox group’s selected value changes. |
|
sl-input
|
sl-input
|
sl-input
|
onSlInput
|
Emitted when the checkbox group receives user input. |
|
sl-invalid
|
sl-invalid
|
sl-invalid
|
onSlInvalid
|
Emitted when the form control has been checked for validity and its constraints aren’t satisfied. |
Learn more about events.
Methods
Name | Details |
---|---|
checkValidity()
|
Checks for validity but does not show a validation message. Returns |
getForm()
|
Gets the associated form, if one exists. |
reportValidity()
|
Checks for validity and shows the browser’s validation message if the control is invalid. |
setCustomValidity()
|
Sets a custom validation message. Pass an empty string to restore validity. |
Learn more about methods.
CSS Parts
Name | Description |
---|---|
form-control
|
The form control that wraps the label, input, and help text. |
form-control-label
|
The label’s wrapper. |
form-control-input
|
The input’s wrapper. |
form-control-help-text
|
The help text’s wrapper. |
Learn more about customizing CSS parts.