code/tamagui.dev/data/docs/components/group/2.0.0.mdx
<Highlights features={[ 'Accepts size prop for border radius.', 'Align vertically or horizontally.', 'Children control their own sizing.', 'Disabled prop passes to children.', ]} />
Group is already installed in tamagui, or you can install it independently:
npm install @tamagui/group
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>
)
In v2, 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 '@tamagui/lucide-icons-2'
import { Button, XGroup } from 'tamagui'
export default () => (
<XGroup>
<XGroup.Item>
<Button size="$3" $gtSm={{ size: '$5' }} icon={Activity}>
First
</Button>
</XGroup.Item>
<XGroup.Item>
<Button size="$3" $gtSm={{ size: '$5' }} icon={Airplay}>
Second
</Button>
</XGroup.Item>
</XGroup>
)
The size prop on Group itself only affects the border radius of the group container:
import { Button, XGroup } from 'tamagui'
export default () => (
<XGroup size="$6">
<XGroup.Item>
<Button>First</Button>
</XGroup.Item>
<XGroup.Item>
<Button>Second</Button>
</XGroup.Item>
<XGroup.Item>
<Button>Third</Button>
</XGroup.Item>
</XGroup>
)
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>
)
The disabled property will pass to children.
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:
forcePlacementIf 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>
)
useGroupItem hookFor 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)
}
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>
)
Group, XGroup and YGroup extend YStack, getting Tamagui standard props, plus:
<PropsTable
data={[
{
name: 'orientation',
required: false,
type: '"horizontal" | "vertical"',
description: Forces applying the border radius styles to left/right vs top/bottom. Defaults to horizontal for XGroup and vertical for YGroup.,
},
{
name: 'size',
required: false,
type: 'string | SizeTokens',
description: Sets the border radius of the Group container using your size tokens.,
},
{
name: 'disabled',
required: false,
type: 'boolean',
description: Passes disabled state down to children.,
},
{
name: 'unstyled',
required: false,
type: boolean,
description: Removes all default Tamagui styles.,
},
]}
/>
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:
<PropsTable
data={[
{
name: 'children',
required: true,
type: 'ReactNode',
description: The child element to wrap.,
},
{
name: 'forcePlacement',
required: false,
type: '"first" | "center" | "last"',
description: Forces the item to be a starting, center, or ending item and applies the respective styles.,
},
]}
/>