Skip to content
Navigation

Button Group

Related buttons joined into one segmented control. For choosing between mutually exclusive options use ToggleGroup instead — a button group is a set of actions, not a value.

Added 14 October 2026

React

Codecomponents/react/button-group-demo.tsx
import {Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText} from '@stroeer-labs/design-library/react';
import {ChevronDownIcon, MinusIcon, PlusIcon} from 'lucide-react';

export function ButtonGroupDemo() {
    return (
        <div className="space-y-6">
            <div className="space-y-2">
                <p className="text-xs font-medium text-muted-foreground">Horizontal</p>
                <ButtonGroup aria-label="Date granularity">
                    <Button variant="outline">Day</Button>
                    <Button variant="outline">Week</Button>
                    <Button variant="outline">Month</Button>
                </ButtonGroup>
            </div>
            <div className="space-y-2">
                <p className="text-xs font-medium text-muted-foreground">Vertical</p>
                <ButtonGroup orientation="vertical" aria-label="Row position">
                    <Button variant="outline">Top</Button>
                    <ButtonGroupSeparator />
                    <Button variant="outline">Middle</Button>
                    <Button variant="outline">Bottom</Button>
                </ButtonGroup>
            </div>
            <div className="space-y-2">
                <p className="text-xs font-medium text-muted-foreground">Split button (separator)</p>
                <ButtonGroup aria-label="Export">
                    <Button variant="outline">Export</Button>
                    <ButtonGroupSeparator />
                    <Button variant="outline" size="icon" aria-label="More export options">
                        <ChevronDownIcon />
                    </Button>
                </ButtonGroup>
            </div>
            <div className="space-y-2">
                <p className="text-xs font-medium text-muted-foreground">With text label</p>
                <ButtonGroup aria-label="Slot count">
                    <Button variant="outline" size="icon" aria-label="Remove one slot">
                        <MinusIcon />
                    </Button>
                    <ButtonGroupText>12 slots</ButtonGroupText>
                    <Button variant="outline" size="icon" aria-label="Add one slot">
                        <PlusIcon />
                    </Button>
                </ButtonGroup>
            </div>
            <div className="space-y-2">
                <p className="text-xs font-medium text-muted-foreground">Filled variant</p>
                <ButtonGroup aria-label="Save options">
                    <Button>Save</Button>
                    <Button>Save and close</Button>
                </ButtonGroup>
            </div>
            <div className="space-y-2">
                <p className="text-xs font-medium text-muted-foreground">Floating (map controls — bg-muted stands in for the map)</p>
                <div className="flex items-start gap-4 rounded-lg bg-muted p-4">
                    <ButtonGroup orientation="vertical" aria-label="Map zoom">
                        <Button variant="floating" size="icon" aria-label="Zoom in">
                            <PlusIcon />
                        </Button>
                        <Button variant="floating" size="icon" aria-label="Zoom out">
                            <MinusIcon />
                        </Button>
                    </ButtonGroup>
                    <ButtonGroup aria-label="Map view">
                        <Button variant="floating">Satellite</Button>
                        <Button variant="floating">Fit all</Button>
                    </ButtonGroup>
                    <Button variant="floating">Expand map</Button>
                </div>
            </div>
            <div className="space-y-2">
                <p className="text-xs font-medium text-muted-foreground">Sizes</p>
                <div className="flex flex-wrap items-center gap-3">
                    <ButtonGroup>
                        <Button variant="outline" size="sm">
                            Small
                        </Button>
                        <Button variant="outline" size="sm">
                            Group
                        </Button>
                    </ButtonGroup>
                    <ButtonGroup>
                        <Button variant="outline">Default</Button>
                        <Button variant="outline">Group</Button>
                    </ButtonGroup>
                    <ButtonGroup>
                        <Button variant="outline" size="lg">
                            Large
                        </Button>
                        <Button variant="outline" size="lg">
                            Group
                        </Button>
                    </ButtonGroup>
                </div>
            </div>
        </div>
    );
}

Angular

Codecomponents/angular/button-group-demo.ts
import {Component} from '@angular/core';
import {HlmButtonGroupImports, HlmButtonImports} from '@stroeer-labs/design-library/angular';
import {NgIcon, provideIcons} from '@ng-icons/core';
import {lucideChevronDown, lucideMinus, lucidePlus} from '@ng-icons/lucide';

@Component({
    selector: 'dl-button-group-demo',
    standalone: true,
    imports: [HlmButtonGroupImports, HlmButtonImports, NgIcon],
    providers: [provideIcons({lucideChevronDown, lucideMinus, lucidePlus})],
    template: `
        <div class="space-y-6">
            <div class="space-y-2">
                <p class="text-xs font-medium text-muted-foreground">Horizontal</p>
                <div hlmButtonGroup aria-label="Date granularity">
                    <button hlmBtn variant="outline">Day</button>
                    <button hlmBtn variant="outline">Week</button>
                    <button hlmBtn variant="outline">Month</button>
                </div>
            </div>
            <div class="space-y-2">
                <p class="text-xs font-medium text-muted-foreground">Vertical</p>
                <div hlmButtonGroup orientation="vertical" aria-label="Row position">
                    <button hlmBtn variant="outline">Top</button>
                    <hlm-button-group-separator />
                    <button hlmBtn variant="outline">Middle</button>
                    <button hlmBtn variant="outline">Bottom</button>
                </div>
            </div>
            <div class="space-y-2">
                <p class="text-xs font-medium text-muted-foreground">Split button (separator)</p>
                <div hlmButtonGroup aria-label="Export">
                    <button hlmBtn variant="outline">Export</button>
                    <hlm-button-group-separator />
                    <button hlmBtn variant="outline" size="icon" aria-label="More export options">
                        <ng-icon name="lucideChevronDown" />
                    </button>
                </div>
            </div>
            <div class="space-y-2">
                <p class="text-xs font-medium text-muted-foreground">With text label</p>
                <div hlmButtonGroup aria-label="Slot count">
                    <button hlmBtn variant="outline" size="icon" aria-label="Remove one slot">
                        <ng-icon name="lucideMinus" />
                    </button>
                    <div hlmButtonGroupText>12 slots</div>
                    <button hlmBtn variant="outline" size="icon" aria-label="Add one slot">
                        <ng-icon name="lucidePlus" />
                    </button>
                </div>
            </div>
            <div class="space-y-2">
                <p class="text-xs font-medium text-muted-foreground">Filled variant</p>
                <div hlmButtonGroup aria-label="Save options">
                    <button hlmBtn>Save</button>
                    <button hlmBtn>Save and close</button>
                </div>
            </div>
            <div class="space-y-2">
                <p class="text-xs font-medium text-muted-foreground">Floating (map controls — bg-muted stands in for the map)</p>
                <div class="flex items-start gap-4 rounded-lg bg-muted p-4">
                    <div hlmButtonGroup orientation="vertical" aria-label="Map zoom">
                        <button hlmBtn variant="floating" size="icon" aria-label="Zoom in"><ng-icon name="lucidePlus" /></button>
                        <button hlmBtn variant="floating" size="icon" aria-label="Zoom out"><ng-icon name="lucideMinus" /></button>
                    </div>
                    <div hlmButtonGroup aria-label="Map view">
                        <button hlmBtn variant="floating">Satellite</button>
                        <button hlmBtn variant="floating">Fit all</button>
                    </div>
                    <button hlmBtn variant="floating">Expand map</button>
                </div>
            </div>
            <div class="space-y-2">
                <p class="text-xs font-medium text-muted-foreground">Sizes</p>
                <div class="flex flex-wrap items-center gap-3">
                    <div hlmButtonGroup>
                        <button hlmBtn variant="outline" size="sm">Small</button>
                        <button hlmBtn variant="outline" size="sm">Group</button>
                    </div>
                    <div hlmButtonGroup>
                        <button hlmBtn variant="outline">Default</button>
                        <button hlmBtn variant="outline">Group</button>
                    </div>
                    <div hlmButtonGroup>
                        <button hlmBtn variant="outline" size="lg">Large</button>
                        <button hlmBtn variant="outline" size="lg">Group</button>
                    </div>
                </div>
            </div>
        </div>
    `,
})
export class ButtonGroupDemoComponent {}