> ## Documentation Index
> Fetch the complete documentation index at: https://docs.uniwind.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Group Variants

> Style descendants based on a parent's interaction state using Tailwind group variants

## Overview

<Tip>
  **No context providers, no re-renders.** Mark a parent with `group`, use `group-active:*` or `group-focus:*` on any descendant, and Uniwind Pro propagates the parent's state through the native shadow tree. No React re-renders, no prop drilling.
</Tip>

Uniwind Pro supports Tailwind's [`group` variants](https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-parent-state) natively. A parent component marked with `group` propagates its interaction state (pressed, focused) to any descendant using `group-*` variants.

<Info>
  Group variants work on React Native with the same classNames you'd use on the web. Migrating a web codebase stays trivial. No conditional logic, no platform-specific hooks.
</Info>

## Usage

### Basic group

Wrap descendants in a component marked with `group`, then use `group-active:*` (press) or `group-focus:*` on any child:

```tsx theme={null}
import { Pressable, Text, View } from 'react-native'

<Pressable className="group p-4 bg-base rounded-xl">
    <Text className="text-default group-active:text-primary">
        Press the card
    </Text>
    <View className="size-8 bg-blue-500 rounded group-active:bg-red-500" />
</Pressable>
```

When parent `Pressable` is pressed, both `Text` color and `View` background animate to their `group-active:*` values. On release, they revert.

### Named groups

Distinguish specific ancestors by giving a group a name with `group/{name}` syntax. Descendants target that name with `group-active/{name}:*`:

```tsx theme={null}
<Pressable className="group/outer p-4 bg-base rounded-xl items-center gap-3 w-64">
    <Text className="text-default text-sm">Outer (press me)</Text>
    <View className="size-12 rounded-lg bg-primary group-active/outer:bg-secondary" />
</Pressable>
```

Descendant only reacts to the named ancestor, so nested interactive containers never collide.

<Tip>
  Named groups let you nest multiple interactive containers without collision. Each descendant picks the group it follows by name.
</Tip>

### Multiple descendants

One press fans out to any number of descendants. No tree traversal per press, just a lookup of pre-indexed group descendants:

```tsx theme={null}
<Pressable className="group p-4 bg-base rounded-xl items-center gap-3">
    <Text className="text-default text-sm">Press me</Text>
    <View className="flex-row gap-3">
        <View className="size-12 bg-blue-500 rounded-lg group-active:bg-red-500" />
        <View className="size-12 bg-green-500 rounded-lg group-active:bg-yellow-500" />
        <View className="size-12 bg-purple-500 rounded-lg group-active:bg-pink-500" />
    </View>
</Pressable>
```

## Supported States

| Variant          | Triggered by                                                    |
| ---------------- | --------------------------------------------------------------- |
| `group-active:*` | Parent is pressed (touch-down)                                  |
| `group-focus:*`  | Parent receives focus (TV remote, keyboard, or `TextInput` tap) |

<Info>
  React Native has no pointer hover. Use `group-active:*` for press state. `group-hover:*` is a web-only Tailwind variant and has no effect in Uniwind native.
</Info>

## Supported Group Parents

Only components that drive shadow-tree updates from their own press/focus events can act as a `group` container:

| Component   | Supported events           |
| ----------- | -------------------------- |
| `Pressable` | press, focus               |
| `Text`      | press (requires `onPress`) |

<Warning>
  `Text` only fires press events when `onPress` (or `onLongPress`) is set. If you use `Text` as a group parent, add an `onPress` handler, even an empty one, so press events propagate:

  ```tsx theme={null}
  <Text onPress={() => {}} className="group text-2xl text-primary">
      Hello <Text className="group-active:text-secondary">world</Text>
  </Text>
  ```
</Warning>

<Info>
  `TouchableOpacity`, `TouchableHighlight`, `TouchableWithoutFeedback`, and `TextInput` do not act as group parents. Wrap them in a `Pressable` marked `group` if you need group propagation around one.
</Info>

## Zero Cost for Non-Group Components

If a component doesn't use any `group` or `group-*` class, it pays zero cost for this feature:

* No extra hooks, no context subscriptions
* No entry in any group map
* No event handlers wired up

The C++ engine only tracks families flagged `isGroup` or `hasGroupDependency` at link time. Everything else bypasses the group pipeline.

## Unsupported Patterns

<AccordionGroup>
  <Accordion title="group-hover">
    React Native has no pointer hover state. Use `group-active:*` for press. `group-hover:*` is not parsed on native.
  </Accordion>

  <Accordion title="Arbitrary group selectors">
    Web Tailwind supports `group-[.is-published]:block` and similar selector-based group variants. These have no equivalent in a non-CSS engine and are not supported on React Native.
  </Accordion>

  <Accordion title="group-disabled">
    `disabled` is a static prop in React Native, not an interaction state. When it changes, React re-renders the subtree and children read their own props. `group-disabled:*` is parsed but does not trigger shadow tree updates at runtime.
  </Accordion>

  <Accordion title="Implicit in-*">
    Tailwind 4's implicit `in-*` variants (styling any ancestor match) are not supported. Use explicit `group` markers instead.
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="Shadow Tree Updates" icon="bolt" href="/pro/shadow-tree-updates">
    The C++ engine that powers group propagation
  </Card>

  <Card title="Tailwind: group variants" icon="book" href="https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-parent-state">
    Reference for Tailwind's group variant syntax
  </Card>
</CardGroup>
