button group

A container that groups related buttons together with consistent styling.

PreviousNext
import { Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import {
  lucideArchive,
  lucideArrowLeft,
  lucideCalendarPlus,
  lucideCheck,
  lucideChevronRight,
  lucideClock,
  lucideEllipsis,
  lucideListFilterPlus,
  lucideTag,
  lucideTrash,
} from '@ng-icons/lucide';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardButtonGroupComponent } from '@/shared/components/button-group/button-group.component';
import { ZardMenuImports } from '@/shared/components/menu/menu.imports';
import { ZardSeparatorComponent } from '@/shared/components/separator';

@Component({
  selector: 'z-demo-button-group-default',
  imports: [ZardButtonGroupComponent, ZardButtonComponent, NgIcon, ZardMenuImports, ZardSeparatorComponent],
  template: `
    <z-button-group>
      <z-button-group class="hidden sm:flex">
        <button type="button" z-button zType="outline" aria-label="Go Back">
          <ng-icon name="lucideArrowLeft" />
        </button>
      </z-button-group>

      <z-button-group>
        <button type="button" z-button zType="outline">Archive</button>
        <button type="button" z-button zType="outline">Report</button>
      </z-button-group>

      <z-button-group>
        <button type="button" z-button zType="outline">Snooze</button>
        <button type="button" z-button zType="outline" z-menu [zMenuTriggerFor]="menu">
          <ng-icon name="lucideEllipsis" />

          <ng-template #menu>
            <div z-menu-content class="w-48">
              <button type="button" z-menu-item>
                <ng-icon name="lucideCheck" />
                Mark as Read
              </button>
              <button type="button" z-menu-item>
                <ng-icon name="lucideArchive" />
                Archive
              </button>

              <z-separator class="my-2" />

              <button type="button" z-menu-item>
                <ng-icon name="lucideClock" />
                Snooze
              </button>
              <button type="button" z-menu-item>
                <ng-icon name="lucideCalendarPlus" />
                Add to Calendar
              </button>
              <button type="button" z-menu-item>
                <ng-icon name="lucideListFilterPlus" />
                Add to List
              </button>
              <button
                type="button"
                z-menu-item
                z-menu
                [zMenuTriggerFor]="subMenu"
                zPlacement="rightTop"
                class="justify-between"
              >
                <div class="flex items-center">
                  <ng-icon name="tag" class="mr-1" />
                  Label as
                </div>
                <ng-icon name="lucideChevronRight" />

                <ng-template #subMenu>
                  <div z-menu-content class="w-48">
                    <button type="button" z-menu-item>Personal</button>
                    <button type="button" z-menu-item>Work</button>
                    <button type="button" z-menu-item>Other</button>
                  </div>
                </ng-template>
              </button>

              <z-separator class="my-2" />

              <button type="button" z-menu-item class="text-red-500">
                <ng-icon name="lucideTrash" />
                Trash
              </button>
            </div>
          </ng-template>
        </button>
      </z-button-group>
    </z-button-group>
  `,
  viewProviders: [
    provideIcons({
      lucideArrowLeft,
      lucideEllipsis,
      lucideCheck,
      lucideArchive,
      lucideClock,
      lucideCalendarPlus,
      lucideListFilterPlus,
      lucideTag,
      lucideChevronRight,
      lucideTrash,
    }),
  ],
})
export class ZardDemoButtonGroupDefaultComponent {}

Installation

Copy
npx zard-cli@latest add button-group

Usage

import { ZardButtonGroupComponent } from '@/shared/components/button-group/button-group.component';
Copy
<z-button-group>
  <button z-button zType="outline">Left</button>
  <button z-button zType="outline">Center</button>
  <button z-button zType="outline">Right</button>
</z-button-group>
Copy

Examples

orientation

Set the zOrientation prop to change the button group layout.

import { Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideMinus, lucidePlus } from '@ng-icons/lucide';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardButtonGroupComponent } from '@/shared/components/button-group/button-group.component';

@Component({
  selector: 'z-demo-button-group-orientation',
  imports: [ZardButtonGroupComponent, ZardButtonComponent, NgIcon],
  template: `
    <z-button-group zOrientation="vertical">
      <button type="button" z-button zType="outline" zSize="icon" aria-label="Add">
        <ng-icon name="lucidePlus" />
      </button>
      <button type="button" z-button zType="outline" zSize="icon" aria-label="Remove">
        <ng-icon name="lucideMinus" />
      </button>
    </z-button-group>
  `,
  viewProviders: [provideIcons({ lucidePlus, lucideMinus })],
})
export class ZardDemoButtonGroupOrientationComponent {}

size

Control the size of buttons using the zSize prop on individual buttons.

import { Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucidePlus } from '@ng-icons/lucide';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardButtonGroupComponent } from '@/shared/components/button-group/button-group.component';

@Component({
  selector: 'z-demo-button-group-size',
  imports: [ZardButtonGroupComponent, ZardButtonComponent, NgIcon],
  template: `
    <z-button-group>
      <button type="button" z-button zType="outline" zSize="sm">Small</button>
      <button type="button" z-button zType="outline" zSize="sm">Button</button>
      <button type="button" z-button zType="outline" zSize="sm">Group</button>
      <button type="button" z-button zType="outline" zSize="icon-sm" aria-label="Add">
        <ng-icon name="lucidePlus" />
      </button>
    </z-button-group>

    <z-button-group>
      <button type="button" z-button zType="outline">Default</button>
      <button type="button" z-button zType="outline">Button</button>
      <button type="button" z-button zType="outline">Group</button>
      <button type="button" z-button zType="outline" zSize="icon" aria-label="Add">
        <ng-icon name="lucidePlus" />
      </button>
    </z-button-group>

    <z-button-group>
      <button type="button" z-button zType="outline" zSize="lg">Large</button>
      <button type="button" z-button zType="outline" zSize="lg">Button</button>
      <button type="button" z-button zType="outline" zSize="lg">Group</button>
      <button type="button" z-button zType="outline" zSize="icon-lg" aria-label="Add">
        <ng-icon name="lucidePlus" />
      </button>
    </z-button-group>
  `,
  viewProviders: [provideIcons({ lucidePlus })],
  host: {
    class: 'flex flex-col items-start gap-8',
  },
})
export class ZardDemoButtonGroupSizeComponent {}

nested

Nest z-button-group components to create button groups with spacing.

import { Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideAudioLines, lucidePlus } from '@ng-icons/lucide';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardButtonGroupComponent } from '@/shared/components/button-group/button-group.component';
import { ZardInputComponent } from '@/shared/components/input/input.component';
import { ZardInputGroupImports } from '@/shared/components/input-group/input-group.imports';
import { ZardTooltipDirective } from '@/shared/components/tooltip/tooltip';

@Component({
  selector: 'z-demo-button-group-nested',
  imports: [
    ZardButtonGroupComponent,
    ZardButtonComponent,
    ZardInputComponent,
    ...ZardInputGroupImports,
    ZardTooltipDirective,
    NgIcon,
  ],
  template: `
    <z-button-group>
      <z-button-group>
        <button type="button" z-button zType="outline" zSize="icon" aria-label="Add">
          <ng-icon name="lucidePlus" />
        </button>
      </z-button-group>
      <z-button-group>
        <z-input-group>
          <input z-input placeholder="Send a message..." />
          <z-input-group-addon zAlign="inline-end" zTooltip="Voice Mode">
            <ng-icon name="lucideAudioLines" />
          </z-input-group-addon>
        </z-input-group>
      </z-button-group>
    </z-button-group>
  `,
  viewProviders: [provideIcons({ lucidePlus, lucideAudioLines })],
})
export class ZardDemoButtonGroupNestedComponent {}

separator

The z-button-group-divider component visually divides buttons within a group. Buttons with zType="outline" do not need a separator since they have a border.

import { Component } from '@angular/core';

import { ZardButtonComponent } from '../../button/button.component';
import { ZardButtonGroupComponent, ZardButtonGroupDividerComponent } from '../button-group.component';

@Component({
  selector: 'z-demo-button-group-divider',
  imports: [ZardButtonGroupComponent, ZardButtonComponent, ZardButtonGroupDividerComponent],
  template: `
    <z-button-group>
      <button z-button zSize="sm" zType="secondary">Copy</button>
      <z-button-group-divider />
      <button z-button zSize="sm" zType="secondary">Paste</button>
    </z-button-group>
  `,
})
export class ZardDemoButtonGroupDividerComponent {}

split

Create a split button group by adding two buttons separated by a z-button-group-divider.

import { Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucidePlus } from '@ng-icons/lucide';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import {
  ZardButtonGroupComponent,
  ZardButtonGroupDividerComponent,
} from '@/shared/components/button-group/button-group.component';

@Component({
  selector: 'z-demo-button-group-split',
  imports: [ZardButtonGroupComponent, ZardButtonGroupDividerComponent, ZardButtonComponent, NgIcon],
  template: `
    <z-button-group>
      <button type="button" z-button zType="secondary">Button</button>
      <z-button-group-divider />
      <button type="button" z-button zType="secondary" zSize="icon" aria-label="Add">
        <ng-icon name="lucidePlus" />
      </button>
    </z-button-group>
  `,
  viewProviders: [provideIcons({ lucidePlus })],
})
export class ZardDemoButtonGroupSplitComponent {}

input

Wrap an Input component with buttons.

import { Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideSearch } from '@ng-icons/lucide';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardButtonGroupComponent } from '@/shared/components/button-group/button-group.component';
import { ZardInputComponent } from '@/shared/components/input';

@Component({
  selector: 'z-demo-button-group-input',
  imports: [ZardButtonGroupComponent, ZardButtonComponent, NgIcon, ZardInputComponent],
  template: `
    <z-button-group>
      <input z-input placeholder="Search..." />
      <button type="button" z-button zType="outline"><ng-icon name="lucideSearch" /></button>
    </z-button-group>
  `,
  viewProviders: [provideIcons({ lucideSearch })],
})
export class ZardDemoButtonGroupInputComponent {}

input group

Wrap an InputGroup component to create complex input layouts.

import { Component, signal } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideAudioLines, lucidePlus } from '@ng-icons/lucide';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardButtonGroupComponent } from '@/shared/components/button-group/button-group.component';
import { ZardInputComponent } from '@/shared/components/input/input.component';
import { ZardInputGroupImports } from '@/shared/components/input-group/input-group.imports';
import { ZardTooltipDirective } from '@/shared/components/tooltip/tooltip';

@Component({
  selector: 'z-demo-button-group-input-group',
  imports: [
    ZardButtonGroupComponent,
    ZardButtonComponent,
    ZardInputComponent,
    ...ZardInputGroupImports,
    ZardTooltipDirective,
    NgIcon,
  ],
  template: `
    <z-button-group class="[--radius:9999rem]">
      <z-button-group>
        <button type="button" z-button zType="outline" zSize="icon" aria-label="Add">
          <ng-icon name="lucidePlus" />
        </button>
      </z-button-group>
      <z-button-group>
        <z-input-group>
          <input
            z-input
            [placeholder]="voiceEnabled() ? 'Record and send audio...' : 'Send a message...'"
            [disabled]="voiceEnabled()"
          />
          <z-input-group-addon zAlign="inline-end">
            <button
              z-input-group-button
              zTooltip="Voice Mode"
              aria-label="Voice Mode"
              [attr.aria-pressed]="voiceEnabled()"
              [attr.data-active]="voiceEnabled() ? '' : null"
              class="data-[active]:bg-orange-100 data-[active]:text-orange-700 dark:data-[active]:bg-orange-800 dark:data-[active]:text-orange-100"
              (click)="toggleVoice()"
            >
              <ng-icon name="lucideAudioLines" />
            </button>
          </z-input-group-addon>
        </z-input-group>
      </z-button-group>
    </z-button-group>
  `,
  viewProviders: [provideIcons({ lucidePlus, lucideAudioLines })],
})
export class ZardDemoButtonGroupInputGroupComponent {
  protected readonly voiceEnabled = signal(false);

  protected toggleVoice(): void {
    this.voiceEnabled.update(value => !value);
  }
}

dropdown

Create a split button group with a Dropdown component.

import { Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import {
  lucideCheck,
  lucideChevronDown,
  lucideCopy,
  lucideShare,
  lucideTrash,
  lucideTriangleAlert,
  lucideUserRoundX,
  lucideVolumeOff,
} from '@ng-icons/lucide';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardButtonGroupComponent } from '@/shared/components/button-group/button-group.component';
import { ZardDropdownImports } from '@/shared/components/dropdown/dropdown.imports';
import { ZardSeparatorComponent } from '@/shared/components/separator/separator.component';

@Component({
  selector: 'z-demo-button-group-dropdown',
  imports: [ZardButtonGroupComponent, ZardButtonComponent, ZardSeparatorComponent, ...ZardDropdownImports, NgIcon],
  template: `
    <z-button-group>
      <button type="button" z-button zType="outline">Follow</button>
      <button
        type="button"
        z-button
        zType="outline"
        zSize="icon"
        z-dropdown
        [zDropdownMenu]="menu"
        aria-label="More options"
      >
        <ng-icon name="lucideChevronDown" />
      </button>
      <z-dropdown-menu-content #menu="zDropdownMenuContent" class="w-44">
        <z-dropdown-menu-item>
          <ng-icon name="lucideVolumeOff" />
          Mute Conversation
        </z-dropdown-menu-item>
        <z-dropdown-menu-item>
          <ng-icon name="lucideCheck" />
          Mark as Read
        </z-dropdown-menu-item>
        <z-dropdown-menu-item>
          <ng-icon name="lucideTriangleAlert" />
          Report Conversation
        </z-dropdown-menu-item>
        <z-dropdown-menu-item>
          <ng-icon name="lucideUserRoundX" />
          Block User
        </z-dropdown-menu-item>
        <z-dropdown-menu-item>
          <ng-icon name="lucideShare" />
          Share Conversation
        </z-dropdown-menu-item>
        <z-dropdown-menu-item>
          <ng-icon name="lucideCopy" />
          Copy Conversation
        </z-dropdown-menu-item>
        <z-separator class="my-1" />
        <z-dropdown-menu-item variant="destructive">
          <ng-icon name="lucideTrash" />
          Delete Conversation
        </z-dropdown-menu-item>
      </z-dropdown-menu-content>
    </z-button-group>
  `,
  viewProviders: [
    provideIcons({
      lucideChevronDown,
      lucideVolumeOff,
      lucideCheck,
      lucideTriangleAlert,
      lucideUserRoundX,
      lucideShare,
      lucideCopy,
      lucideTrash,
    }),
  ],
})
export class ZardDemoButtonGroupDropdownComponent {}

select

Pair with a Select component.

import { Component, signal } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideArrowRight } from '@ng-icons/lucide';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardButtonGroupComponent } from '@/shared/components/button-group/button-group.component';
import { ZardInputComponent } from '@/shared/components/input/input.component';
import { ZardSelectItemComponent } from '@/shared/components/select/select-item.component';
import { ZardSelectComponent } from '@/shared/components/select/select.component';

@Component({
  selector: 'z-demo-button-group-select',
  imports: [
    ZardButtonGroupComponent,
    ZardButtonComponent,
    ZardInputComponent,
    ZardSelectComponent,
    ZardSelectItemComponent,
    NgIcon,
  ],
  template: `
    <z-button-group>
      <z-button-group>
        <z-select [(zValue)]="currency" [zLabel]="currency()" class="w-fit [&_button]:font-mono">
          @for (cur of CURRENCIES; track cur.value) {
            <z-select-item [zValue]="cur.value">
              {{ cur.value }}
              <span class="text-muted-foreground">{{ cur.label }}</span>
            </z-select-item>
          }
        </z-select>
        <input z-input placeholder="10.00" pattern="[0-9]*" />
      </z-button-group>
      <z-button-group>
        <button type="button" z-button zType="outline" zSize="icon" aria-label="Send">
          <ng-icon name="lucideArrowRight" />
        </button>
      </z-button-group>
    </z-button-group>
  `,
  viewProviders: [provideIcons({ lucideArrowRight })],
})
export class ZardDemoButtonGroupSelectComponent {
  protected readonly CURRENCIES = [
    { value: '$', label: 'US Dollar' },
    { value: '€', label: 'Euro' },
    { value: '£', label: 'British Pound' },
  ];

  protected readonly currency = signal('$');
}

popover

Use with a Popover component.

import { Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideBot, lucideChevronDown } from '@ng-icons/lucide';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardButtonGroupComponent } from '@/shared/components/button-group/button-group.component';
import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardPopoverComponent, ZardPopoverDirective } from '@/shared/components/popover/popover.component';
import { ZardTextareaComponent } from '@/shared/components/textarea/textarea.component';

@Component({
  selector: 'z-demo-button-group-popover',
  imports: [
    ZardButtonGroupComponent,
    ZardButtonComponent,
    ZardPopoverComponent,
    ZardPopoverDirective,
    ZardTextareaComponent,
    ...ZardFieldImports,
    NgIcon,
  ],
  template: `
    <z-button-group>
      <button type="button" z-button zType="outline">
        <ng-icon name="lucideBot" />
        Copilot
      </button>
      <button
        type="button"
        z-button
        zType="outline"
        zSize="icon"
        zPopover
        [zContent]="popoverContent"
        zAlign="end"
        aria-label="Open Popover"
      >
        <ng-icon name="lucideChevronDown" />
      </button>
      <ng-template #popoverContent>
        <z-popover class="w-80 rounded-xl p-0 text-sm">
          <div class="border-b px-4 py-3">
            <p class="font-medium">Start a new task with Copilot</p>
            <p class="text-muted-foreground text-sm">Describe your task in natural language.</p>
          </div>
          <div z-field class="p-4">
            <label z-field-label for="task" class="sr-only">Task Description</label>
            <textarea z-textarea id="task" placeholder="I need to..." class="resize-none"></textarea>
            <p z-field-description>Copilot will open a pull request for review.</p>
          </div>
        </z-popover>
      </ng-template>
    </z-button-group>
  `,
  viewProviders: [provideIcons({ lucideBot, lucideChevronDown })],
})
export class ZardDemoButtonGroupPopoverComponent {}

API Reference

z-button-groupComponent

A container that groups related buttons together with consistent styling.

PropertyDescriptionTypeDefault
zOrientation Orientation of the button group 'horizontal' | 'vertical' 'horizontal'

z-button-group-dividerComponent

A visual divider between buttons in a group.

PropertyDescriptionTypeDefault
zOrientation Override for divider orientation, by default it uses the parent's orientation 'horizontal' | 'vertical' null

z-button-group-textComponent

Applies styles to text elements so that they conform with the rest of the group, for example a label.

PropertyDescriptionTypeDefault
github iconwhatsapp icondiscord iconX icon

Made with in Brazil. Open source and available on GitHub .