component

Group

A layout wrapper that combines inputs, buttons, checkboxes, radios, and other controls into a single cohesive unit. The group owns the border and focus outline — inner components surrender their own borders and rings so the group presents as one unified element.

Basic

Group buttons, checkbox buttons, or radio buttons into a single connected control. All variants suppress their own borders and focus rings so the group presents as one cohesive element.

Full width — search bar

Full width — segmented control

Input with button

Button on both sides

Multiple inputs

Button group

Mixed feedback buttons

Tab horizontal

Tab vertical

Vertical button group

Vertical checkbox group

Vertical radio button group

Checkbox button group

Radio button group

---
import Group from "../Group.astro";
import Input from "@pindoba/astro-input";
import Button from "@pindoba/astro-button";
import Checkbox from "@pindoba/astro-checkbox";
import Radio from "@pindoba/astro-radio";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "xl", direction: "column", width: "full" })}>
  <div>
    <h3>Full width — search bar</h3>
    <Group fullWidth>
      <Input fullWidth placeholder="Search..." />
      <Button>Search</Button>
    </Group>
  </div>

  <div>
    <h3>Full width — segmented control</h3>
    <Group fullWidth>
      <Radio
        id="group-fw-env-dev"
        appearance="button"
        name="group-fw-env"
        value="dev"
        fullWidth
        checked>Dev</Radio
      >
      <Radio
        id="group-fw-env-staging"
        appearance="button"
        name="group-fw-env"
        value="staging"
        fullWidth>Staging</Radio
      >
      <Radio
        id="group-fw-env-prod"
        appearance="button"
        name="group-fw-env"
        value="prod"
        fullWidth>Prod</Radio
      >
    </Group>
  </div>

  <div>
    <h3>Input with button</h3>
    <Group>
      <Input placeholder="Search..." />
      <Button>Search</Button>
    </Group>
  </div>

  <div>
    <h3>Button on both sides</h3>
    <Group>
      <Button emphasis="secondary">-</Button>
      <Input placeholder="Enter value" />
      <Button emphasis="secondary">+</Button>
    </Group>
  </div>

  <div>
    <h3>Multiple inputs</h3>
    <Group>
      <Input placeholder="First name" />
      <Input placeholder="Last name" />
    </Group>
  </div>

  <div>
    <h3>Button group</h3>
    <Group>
      <Button emphasis="secondary">Cut</Button>
      <Button emphasis="secondary">Copy</Button>
      <Button emphasis="secondary">Paste</Button>
    </Group>
  </div>

  <div>
    <h3>Mixed feedback buttons</h3>
    <Group>
      <Button feedback="success">Save</Button>
      <Button feedback="warning" emphasis="secondary">Draft</Button>
      <Button feedback="danger" emphasis="secondary">Delete</Button>
    </Group>
  </div>

  <div>
    <h3>Tab horizontal</h3>
    <Group>
      <Radio
        id="group-tab-h-all"
        appearance="tab-horizontal"
        name="group-tab-h"
        value="all"
        checked>All</Radio
      >
      <Radio
        id="group-tab-h-active"
        appearance="tab-horizontal"
        name="group-tab-h"
        value="active">Active</Radio
      >
      <Radio
        id="group-tab-h-archived"
        appearance="tab-horizontal"
        name="group-tab-h"
        value="archived">Archived</Radio
      >
    </Group>
  </div>

  <div>
    <h3>Tab vertical</h3>
    <Group orientation="vertical">
      <Radio
        id="group-tab-v-dashboard"
        appearance="tab-vertical"
        name="group-tab-v"
        value="dashboard"
        checked>Dashboard</Radio
      >
      <Radio
        id="group-tab-v-settings"
        appearance="tab-vertical"
        name="group-tab-v"
        value="settings">Settings</Radio
      >
      <Radio
        id="group-tab-v-profile"
        appearance="tab-vertical"
        name="group-tab-v"
        value="profile">Profile</Radio
      >
    </Group>
  </div>

  <div>
    <h3>Vertical button group</h3>
    <Group orientation="vertical">
      <Button emphasis="secondary">Cut</Button>
      <Button emphasis="secondary">Copy</Button>
      <Button emphasis="secondary">Paste</Button>
    </Group>
  </div>

  <div>
    <h3>Vertical checkbox group</h3>
    <Group orientation="vertical">
      <Checkbox appearance="button" size="md">Bold</Checkbox>
      <Checkbox appearance="button" size="md">Italic</Checkbox>
      <Checkbox appearance="button" size="md">Underline</Checkbox>
    </Group>
  </div>

  <div>
    <h3>Vertical radio button group</h3>
    <Group orientation="vertical">
      <Radio
        id="group-view-v-list"
        appearance="button"
        size="md"
        name="view-v"
        value="list">List</Radio
      >
      <Radio
        id="group-view-v-grid"
        appearance="button"
        size="md"
        name="view-v"
        value="grid">Grid</Radio
      >
      <Radio
        id="group-view-v-table"
        appearance="button"
        size="md"
        name="view-v"
        value="table">Table</Radio
      >
    </Group>
  </div>

  <div>
    <h3>Checkbox button group</h3>
    <Group>
      <Checkbox appearance="button" size="md">Bold</Checkbox>
      <Checkbox appearance="button" size="md">Italic</Checkbox>
      <Checkbox appearance="button" size="md">Underline</Checkbox>
    </Group>
  </div>

  <div>
    <h3>Radio button group</h3>
    <Group>
      <Radio
        id="group-view-list"
        appearance="button"
        size="md"
        name="view"
        value="list">List</Radio
      >
      <Radio
        id="group-view-grid"
        appearance="button"
        size="md"
        name="view"
        value="grid">Grid</Radio
      >
      <Radio
        id="group-view-table"
        appearance="button"
        size="md"
        name="view"
        value="table">Table</Radio
      >
    </Group>
  </div>
</div>

Feedback

Apply a semantic color to the group outline and pass matching feedback to the inner components.

---
import Group from "../Group.astro";
import Input from "@pindoba/astro-input";
import Button from "@pindoba/astro-button";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "md", direction: "column", width: "full" })}>
  <Group feedback="neutral">
    <Input placeholder="Neutral" />
    <Button>Go</Button>
  </Group>

  <Group feedback="primary">
    <Input feedback="primary" placeholder="Primary" />
    <Button>Go</Button>
  </Group>

  <Group feedback="success">
    <Input feedback="success" placeholder="Success" />
    <Button feedback="success">Go</Button>
  </Group>

  <Group feedback="danger">
    <Input feedback="danger" placeholder="Danger" />
    <Button feedback="danger">Go</Button>
  </Group>

  <Group feedback="warning">
    <Input feedback="warning" placeholder="Warning" />
    <Button feedback="warning">Go</Button>
  </Group>
</div>

Size

Use size to control the group’s border radius. Match it to the size of the inner controls so the rounding is proportional.

---
import Group from "../Group.astro";
import Input from "@pindoba/astro-input";
import Button from "@pindoba/astro-button";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "md", direction: "column", width: "full" })}>
  <Group size="xs">
    <Input size="xs" placeholder="Extra small" />
    <Button size="xs">Go</Button>
  </Group>

  <Group size="sm">
    <Input size="sm" placeholder="Small" />
    <Button size="sm">Go</Button>
  </Group>

  <Group size="md">
    <Input size="md" placeholder="Medium" />
    <Button size="md">Go</Button>
  </Group>

  <Group size="lg">
    <Input size="lg" placeholder="Large" />
    <Button size="lg">Go</Button>
  </Group>
</div>

Custom Styling

The passThrough prop provides an escape hatch for the root element: style accepts a Panda CSS SystemStyleObject and props forwards arbitrary HTML attributes.

Custom style via passThrough

Custom props via passThrough

---
import Group from "../Group.astro";
import Input from "@pindoba/astro-input";
import Button from "@pindoba/astro-button";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "xl", direction: "column" })}>
  <div>
    <h3>Custom style via passThrough</h3>
    <Group passThrough={{ root: { style: { borderRadius: "full" } } }}>
      <Input
        placeholder="Search..."
        passThrough={{ root: { style: { borderRadius: "full" } } }}
      />
      <Button shape="pill">Go</Button>
    </Group>
  </div>

  <div>
    <h3>Custom props via passThrough</h3>
    <Group
      passThrough={{
        root: {
          props: { "data-testid": "search-group" },
        },
      }}
    >
      <Input placeholder="Search..." />
      <Button>Search</Button>
    </Group>
  </div>
</div>

Props

props · 4 total
prop type default req description
feedback "neutral""primary""success""danger""warning" "neutral" Semantic feedback color scheme applied to the group outline. neutral: Default. primary: Primary color. success: Green. danger: Red. warning: Orange.
size "xs""sm""md""lg" "md" Border radius matching the size of the inner controls. xs: Extra small. sm: Small. md: Default. lg: Large.
passThrough { root?: { style?: SystemStyleObject; props?: Record<string, unknown> } } undefined Custom styling and props for the group root element.
...rest HTMLAttributes<HTMLDivElement> - Standard HTML div attributes passed to the group wrapper element.