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.

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>Input with button</h3>
    <Group passThrough={{ root: { style: { width: "full" } } }}>
      <Input placeholder="Search..." />
      <Button>Search</Button>
    </Group>
  </div>

  <div>
    <h3>Button on both sides</h3>
    <Group passThrough={{ root: { style: { width: "full" } } }}>
      <Button emphasis="secondary">-</Button>
      <Input placeholder="Enter value" />
      <Button emphasis="secondary">+</Button>
    </Group>
  </div>

  <div>
    <h3>Multiple inputs</h3>
    <Group passThrough={{ root: { style: { width: "full" } } }}>
      <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 appearance="tab-horizontal" name="group-tab-h" value="all" checked
        >All</Radio
      >
      <Radio appearance="tab-horizontal" name="group-tab-h" value="active"
        >Active</Radio
      >
      <Radio appearance="tab-horizontal" name="group-tab-h" value="archived"
        >Archived</Radio
      >
    </Group>
  </div>

  <div>
    <h3>Tab vertical</h3>
    <Group orientation="vertical">
      <Radio
        appearance="tab-vertical"
        name="group-tab-v"
        value="dashboard"
        checked>Dashboard</Radio
      >
      <Radio appearance="tab-vertical" name="group-tab-v" value="settings"
        >Settings</Radio
      >
      <Radio 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 appearance="button" size="md" name="view-v" value="list"
        >List</Radio
      >
      <Radio appearance="button" size="md" name="view-v" value="grid"
        >Grid</Radio
      >
      <Radio 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 appearance="button" size="md" name="view" value="list">List</Radio>
      <Radio appearance="button" size="md" name="view" value="grid">Grid</Radio>
      <Radio 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", width: "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: {
          style: { width: "full" },
          props: { "data-testid": "search-group" },
        },
      }}
    >
      <Input placeholder="Search..." />
      <Button>Search</Button>
    </Group>
  </div>
</div>

Props

Prop
feedback
feedback

Semantic feedback color scheme applied to the group outline. neutral: Default. primary: Primary color. success: Green. danger: Red. warning: Orange.

Type "neutral" | "primary" | "success" | "danger" | "warning"
Default "neutral"
Required No
size
size

Border radius matching the size of the inner controls. xs: Extra small. sm: Small. md: Default. lg: Large.

Type "xs" | "sm" | "md" | "lg"
Default "md"
Required No
passThrough
passThrough

Custom styling and props for the group root element.

Type { root?: { style?: SystemStyleObject; props?: Record<string, unknown> } }
Default undefined
Required No
...rest
...rest

Standard HTML div attributes passed to the group wrapper element.

Type HTMLAttributes<HTMLDivElement>
Default -
Required No