<button-group>
Group of exclusive push buttons
ElementInternals
to work like a built-in form elementBasic, no selected option:
<button-group>
<button>Design</button>
<button>Preview</button>
</button-group>
Providing values:
<button-group id="temporal" oninput="out.textContent = this.value">
<button value="">None</button>
<button value="d">Dates</button>
<button value="t">Times</button>
<button value="dt">Dates & Times</button>
</button-group>
<output id="out"></output>
Pre-selected state via aria-pressed
:
<button-group>
<button>Design</button>
<button aria-pressed="true">Preview</button>
</button-group>
Multiple:
<button-group multiple oninput="button_multiple_value.textContent = this.value">
<button value="b"><span style="font-weight: bold">B</span></button>
<button value="i"><span style="font-style: italic">I</span></button>
<button value="u"><span style="text-decoration: underline">U</span></button>
</button-group>
<output id="button_multiple_value"></output>
Participates in form submission (requires ElementInternals
support):
<form action="about:blank" target="_blank">
<button-group name="favorite_letter">
<button>A</button>
<button aria-pressed="true">B</button>
<button>C</button>
<button>D</button>
<button>E</button>
<button>F</button>
<button>G</button>
</button-group>
<button type=submit>Submit</button>
</form>
Vertical
<button-group name="type" vertical>
<button value="garlic" aria-pressed="true">Garlic</button>
<button value="msg">MSG</button>
<button value="salt">Salt</button>
</button-group>
Separate
<button-group name="type" separate>
<button>Salt</button>
<button>Pepper</button>
<button>Garlic</button>
<button>Cumin</button>
<button>Coriander</button>
<button>Dill</button>
<button>Parsley</button>
<button>Turmeric</button>
</button-group>
Dynamically setting element.value
:
<button-group id="group1">
<button>A</button>
<button aria-pressed="true">B</button>
<button>C</button>
</button-group>
<button onclick="group1.value = 'C'">Select C</button>
Dynamically adding aria-pressed
attribute:
<button-group id="group2">
<button>A</button>
<button aria-pressed="true">B</button>
<button>C</button>
</button-group>
<button onclick="group2.children[2].setAttribute('aria-pressed', 'true')">Select C</button>
Dynamically adding options:
<button-group id="group3">
<button>1</button>
<button>2</button>
<button aria-pressed="true">3</button>
</button-group>
<button onclick="window.counter ||= 3; group3.insertAdjacentHTML('beforeend', `<button aria-pressed=true>${++counter}</button>`)">Add option</button>
WIP:
<button-group>
has an implicit ARIA Role of region
, so adding an aria-label
should make it work as a landmark out of the box
(requires ElementInternals
support):
<button-group aria-label="View switcher">
<button>Design</button>
<button aria-pressed="true">Preview</button>
</button-group>
Regular labels should work too (requires ElementInternals
support):
<label for="view-switcher">View:</label>
<button-group id="view-switcher">
<button>Design</button>
<button aria-pressed="true">Preview</button>
</button-group>
You don't even need to use an actual <button>
, custom elements
should work too
(presentation needs work, but functionality is there):
<style>
sl-button[aria-pressed="true"]::part(base) {
background: var(--sl-color-primary-100);
border-color: var(--sl-color-primary-300);
}
</style>
<button-group>
<sl-button>1</sl-button>
<sl-button aria-pressed="true">2</sl-button>
<sl-button>3</sl-button>
</button-group>
Just include the component's JS file and you're good:
<script src="https://nudeui.com/button-group/button-group.js" type="module"></script>
In case you want to link to local files: CSS is fetched automatically, and assumed to be in the same directory as the JS file.