Group

Arrange controls in horizontal or vertical groups

Group arranges related controls horizontally or vertically, squares off the border radius where items meet, and passes disabled state to its children.

Features

  • Automatic border radius where items meet

  • Vertical or horizontal alignment

  • Independent sizing for each child

  • Disabled state shared with children

Installation

Group is already installed in tamagui, or you can install it independently:

yarn add @tamagui/group

Usage

Use Group with Group.Item wrapping each child. The orientation property determines the layout direction.

Group zeros out the border radius on connecting sides of children: the first child keeps its start radius, the last keeps its end radius, and middle items have no radius on connecting sides. For YGroup, this affects top/bottom radius. For XGroup, left/right radius.

import { Button, XGroup } from 'tamagui'
export default () => (
<XGroup>
<XGroup.Item>
<Button>First</Button>
</XGroup.Item>
<XGroup.Item>
<Button>Second</Button>
</XGroup.Item>
<XGroup.Item>
<Button>Third</Button>
</XGroup.Item>
</XGroup>
)

Sizing

Children control their own sizing. Apply size props directly to the child components. For responsive sizing, use media queries on the children:

import { Activity, Airplay } from './components/icons' // your generated icons, see Lucide Icons
import { Button, XGroup } from 'tamagui'
export default () => (
<XGroup>
<XGroup.Item>
<Button size="sm" height="gtSm:5" icon={Activity}>
First
</Button>
</XGroup.Item>
<XGroup.Item>
<Button size="sm" height="gtSm:5" icon={Airplay}>
Second
</Button>
</XGroup.Item>
</XGroup>
)

Separators

Add separators manually between items:

import { ListItem, Separator, YGroup } from 'tamagui'
export default () => (
<YGroup>
<YGroup.Item>
<ListItem title="First" />
</YGroup.Item>
<Separator />
<YGroup.Item>
<ListItem title="Second" />
</YGroup.Item>
<Separator />
<YGroup.Item>
<ListItem title="Third" />
</YGroup.Item>
</YGroup>
)

Disabled

The disabled property will pass to children.

Custom components & nested items

Automatic index detection only works when Group.Item is a direct child of Group. If you wrap Group.Item inside a custom component, the automatic first/last detection won’t work.

You have a few options:

Option 1: use forcePlacement

forcePlacement

If you know the position ahead of time, use the forcePlacement prop:

function MyFirstItem({ children }) {
return <XGroup.Item forcePlacement="first">{children}</XGroup.Item>
}
export default () => (
<XGroup>
<MyFirstItem>
<Button>First</Button>
</MyFirstItem>
<XGroup.Item>
<Button>Second</Button>
</XGroup.Item>
</XGroup>
)

Option 2: use useGroupItem hook

useGroupItem

For full control, use the useGroupItem hook directly in your custom component:

import { useGroupItem } from '@tamagui/group'
function MyItem({ children, forcePlacement }) {
const groupItemProps = useGroupItem({ disabled: false }, forcePlacement)
return React.cloneElement(children, groupItemProps)
}

Option 3: pass placement from parent

Calculate positions in the parent and pass them down:

const items = ['First', 'Second', 'Third']
export default () => (
<XGroup>
{items.map((item, i) => (
<XGroup.Item key={item} forcePlacement={i === 0 ? 'first' : i === items.length - 1 ? 'last' : 'center'} >
<Button>{item}</Button>
</XGroup.Item>
))}
</XGroup>
)

API reference

Group

Group, XGroup and YGroup extend YStack, getting Tamagui standard props, plus:

Props

  • orientation

    "horizontal" | "vertical"

    Forces applying the border radius styles to left/right vs top/bottom. Defaults to horizontal for XGroup and vertical for YGroup.

  • disabled

    boolean

    Passes disabled state down to children.

  • unstyled

    boolean

    Removes all default Tamagui styles.

  • Group.Item

    Wrap each of XGroup or YGroup’s children in one of these. It lets Tamagui apply the needed styles to them. It accepts the following props:

    Props

  • children (required)

    ReactNode

    The child element to wrap.

  • forcePlacement

    "first" | "center" | "last"

    Forces the item to be a starting, center, or ending item and applies the respective styles.