Horizontal

Default horizontal group with connected outline buttons.

<div class="btn-group" role="group" aria-label="Actions">
  <button class="btn" data-variant="outline">Save</button>
  <button class="btn" data-variant="outline">Edit</button>
  <button class="btn" data-variant="outline">Delete</button>
</div>

With icons

Icon-only button group for compact toolbars.

<div class="btn-group" role="group" aria-label="Formatting">
  <button class="btn" data-variant="outline" data-size="icon" aria-label="Bold">...</button>
  <button class="btn" data-variant="outline" data-size="icon" aria-label="Italic">...</button>
  <button class="btn" data-variant="outline" data-size="icon" aria-label="Underline">...</button>
</div>

Vertical

Stacked buttons with connected top/bottom borders.

<div class="btn-group" data-orientation="vertical" role="group" aria-label="Nav">
  <button class="btn" data-variant="outline">Top</button>
  <button class="btn" data-variant="outline">Middle</button>
  <button class="btn" data-variant="outline">Bottom</button>
</div>

Separator

Use <hr role="separator"> to visually divide non-outline buttons. Outline buttons don't need separators since they have visible borders.


<div class="btn-group" role="group" aria-label="Clipboard">
  <button class="btn" data-variant="default">Copy</button>
  <hr role="separator">
  <button class="btn" data-variant="default">Paste</button>
</div>

Sizes

Control button size with data-size on individual buttons.

<!-- Small -->
<div class="btn-group" role="group" aria-label="Actions">
  <button class="btn" data-variant="outline" data-size="sm">Save</button>
  <button class="btn" data-variant="outline" data-size="sm">Edit</button>
</div>

<!-- Large -->
<div class="btn-group" role="group" aria-label="Actions">
  <button class="btn" data-variant="outline" data-size="lg">Save</button>
  <button class="btn" data-variant="outline" data-size="lg">Edit</button>
</div>

Split button

A primary action button with a dropdown trigger.


<div class="btn-group" role="group" aria-label="Split action">
  <button class="btn" data-variant="outline">Save</button>
  <hr role="separator">
  <button class="btn" data-variant="outline" data-size="icon"
          aria-label="More options">
    <i data-lucide="chevron-down"></i>
  </button>
</div>

CSS view file

/* -- Button Group component ------------------------------------- */

@layer components {
  .btn-group {
    display: inline-flex;
    align-items: stretch;

    /* Collapse borders between adjacent buttons */
    & > .btn + .btn {
      margin-inline-start: -1px;
    }

    /* Remove internal radii for connected appearance */
    & > .btn:not(:first-child):not(:has(+ [role="separator"])) {
      border-start-start-radius: 0;
      border-end-start-radius: 0;
    }

    & > .btn:not(:last-child):not([role="separator"] + .btn) {
      border-start-end-radius: 0;
      border-end-end-radius: 0;
    }

    /* Buttons after a separator get start radii back */
    & > [role="separator"] + .btn {
      border-start-start-radius: var(--radius-md);
      border-end-start-radius: var(--radius-md);
    }

    /* Buttons before a separator get end radii back */
    & > .btn:has(+ [role="separator"]) {
      border-start-end-radius: var(--radius-md);
      border-end-end-radius: var(--radius-md);
    }

    /* Ensure hovered/focused button stacks above its neighbors */
    & > .btn:hover,
    & > .btn:focus-visible {
      position: relative;
      z-index: 1;
    }

    /* -- Separator ------------------------------------------- */
    & > [role="separator"] {
      width: 1px;
      align-self: stretch;
      background: var(--border);
      border: 0;
      margin: 0;
      padding: 0;
      flex-shrink: 0;
    }

    /* -- Vertical orientation -------------------------------- */
    &[data-orientation="vertical"] {
      flex-direction: column;
      align-items: stretch;

      & > .btn + .btn {
        margin-inline-start: 0;
        margin-top: -1px;
      }

      & > .btn:not(:first-child) {
        border-start-start-radius: 0;
        border-start-end-radius: 0;
        border-end-start-radius: var(--radius-md);
      }

      & > .btn:not(:last-child) {
        border-end-start-radius: 0;
        border-end-end-radius: 0;
        border-start-end-radius: var(--radius-md);
      }

      & > .btn:first-child {
        border-start-start-radius: var(--radius-md);
        border-start-end-radius: var(--radius-md);
      }

      & > .btn:last-child {
        border-end-start-radius: var(--radius-md);
        border-end-end-radius: var(--radius-md);
      }

      & > [role="separator"] {
        width: auto;
        height: 1px;
      }
    }
  }

  @media (forced-colors: active) {
    .btn-group > [role="separator"] {
      background: ButtonText;
    }
  }
}