Segmented control

Definition: A segmented control is a component that switches between different views, modes or settings.

Design

Add .btn-group-tabs class to the .btn-group to transform it in to segmented controls.


                                                        
                                                        
                                                            <div class="btn-group btn-group-tabs" role="group" aria-label="Segmented controls">
                                                           <button type="button" class="btn">Item 1</button>
                                                           <button type="button" class="btn active" aria-selected="true">Item 2</button>
                                                           <button type="button" class="btn">Item 3</button>
                                                        </div>
                                                        
                                                            
Storybook failed to load. Please connect to the VPN to access.

 

Small segments

Add .btn-group-tabs-sm class to wrapper or have it on a smaller size.


                                                        
                                                        
                                                            <div class="btn-group btn-group-tabs btn-group-tabs-sm" role="group" aria-label="Segmented controls">
                                                           <button type="button" class="btn">Item 1</button>
                                                           <button type="button" class="btn active" aria-selected="true">Item 2</button>
                                                           <button type="button" class="btn">Item 3</button>
                                                        </div>
                                                        
                                                            

 

Animated segmented controls

Add .btn-group-animation class to .btn-group-tabs wrapper.

The active button is highlighted by the pseudo-element :before attached to the .btn-group-animation container/wrapper.

To move the active button, you need to get the active button width and position relative to the left of the .btn-group-animation container, and add it to the :before pseudo-element.

You can target the :before pseudo-element directly from the script and assign the value to width and transform: translateX(...) attribute or by adding the value (like in our script example) attached to the .btn-group-animation container the CSS custome propertis / CSS variables: --btn-grp-animation-width the width value of the active button and --btn-grp-animation-offset for the active button X axis offset from the left.


                                                        
                                                        
                                                            <div class="btn-group btn-group-tabs btn-group-animation" role="group" aria-label="Segmented controls">
                                                           <button type="button" class="btn">Item 1</button>
                                                           <button type="button" class="btn active" aria-selected="true">Item 2</button>
                                                           <button type="button" class="btn">Item 3</button>
                                                        </div>
                                                        
                                                            

The functionality for this component, i.e. the script, is not provided! Example of the script for the segment controls with the option for animation as well:


                                                        
                                                        
                                                            document.addEventListener('DOMContentLoaded', ()=>{
                                                            // Demo for selected/active state for segment control
                                                            const segmentedModule = document.querySelectorAll('.btn-group-tabs');
                                                        
                                                            if(segmentedModule.length > 0) {
                                                                segmentedModule.forEach(el => {
                                                                    let children = el.querySelectorAll('.btn');
                                                                    let animation = false;
                                                                    let btnWidth = 0
                                                                    let btnOffset = 0;
                                                                    let elOffset = 0;
                                                                    let elStyle = el.currentStyle || window.getComputedStyle(el);
                                                                    let elPadding = parseInt(elStyle.getPropertyValue('padding-right'));
                                                        
                                                                    if(el.classList.contains('btn-group-animation')) {
                                                                        animation = true;
                                                        
                                                                        for (let btn of children) {
                                                                            if(btn.classList.contains('active')) {
                                                                                btnWidth = btn.clientWidth;
                                                                                elOffset = el.offsetLeft + elPadding;
                                                                                btnOffset = btn.offsetLeft - elOffset;
                                                                                el.style.setProperty('--btn-grp-animation-width', btnWidth + 'px');
                                                                                el.style.setProperty('--btn-grp-animation-offset', btnOffset + 'px');
                                                                                break;
                                                                            }
                                                                        }
                                                                    }
                                                        
                                                                    el.addEventListener('click', e => {
                                                                        let tr = e.target.closest('.btn');
                                                        
                                                                        if(tr) {
                                                                            children.forEach(elm => {
                                                                                elm.classList.remove('active');
                                                                                elm.ariaSelected = false;
                                                                            });
                                                        
                                                                            tr.classList.add('active');
                                                                            tr.ariaSelected = true;
                                                                            tr.blur();
                                                        
                                                                            if(animation) {
                                                                                let trWidth = tr.clientWidth;
                                                                                elOffset = el.offsetLeft + elPadding;
                                                                                let trOffset = tr.offsetLeft - elOffset;
                                                                                el.style.setProperty('--btn-grp-animation-width', trWidth + 'px');
                                                                                el.style.setProperty('--btn-grp-animation-offset', trOffset + 'px');
                                                                            }
                                                                        }
                                                                    });
                                                                });
                                                            }
                                                        });