}>
  The `asChild` pattern is the key to composing primitives with your own design system. No wrapper divs, no prop drilling  -  just clean composition.

## The problem

You want a Dialog trigger, but it should be a link, not a button. Or you want a Popover trigger that's a custom component from your design system. Without composition, you'd need wrapper divs or forked components.

## The solution: `asChild`

Every primitive element supports `asChild`. When true, the primitive doesn't render its own element. Instead, it passes all its props (ARIA attributes, event handlers, refs, data attributes) to the child element.

```tsx
// Instead of wrapping:
<div onClick={open}>
  <Dialog.Trigger>
    <MyFancyButton>Open</MyFancyButton>
  </Dialog.Trigger>
</div>

// Compose directly:
<Dialog.Trigger asChild>
  <MyFancyButton>Open</MyFancyButton>
</Dialog.Trigger>
```

The `MyFancyButton` receives all of Dialog.Trigger's props (`aria-haspopup`, `aria-expanded`, `onClick`, `data-state`, etc.) merged with its own props.

***

## Common patterns

### Link as trigger

```tsx
<Popover.Trigger asChild>
  <a href="#" className="text-blue-600 underline">Show details</a>
</Popover.Trigger>
```

### Custom component as content

```tsx
<Dialog.Content asChild>
  <motion.div
    initial={{ opacity: 0, y: 20 }}
    animate={{ opacity: 1, y: 0 }}
    exit={{ opacity: 0, y: 20 }}
    className="bg-white rounded-lg p-6"
  >
    <Dialog.Title>Animated dialog</Dialog.Title>
  </motion.div>
</Dialog.Content>
```

### Icon button as close

```tsx
<Dialog.Close asChild>
  <button aria-label="Close" className="absolute top-2 right-2">
    <XIcon />
  </button>
</Dialog.Close>
```

***

## Rules

} className="[&_ol]:my-0">
  Keep these rules in mind when using `asChild`:

  1. `asChild` requires **exactly one** child element.
  2. The child must accept a `ref` (use `React.forwardRef` for custom components).
  3. Event handlers compose (both the primitive's and the child's handlers fire).
  4. The child's props take precedence for non-handler, non-style props.

***

## Building reusable styled components

A common pattern is to create styled wrappers around primitives:

```tsx
import * as DialogPrimitive from '@gentleduck/primitives/dialog'

export const Dialog = DialogPrimitive.Root

export const DialogContent = React.forwardRef<
  React.ComponentRef<typeof DialogPrimitive.Content>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, children, ...props }, ref) => (
  <DialogPrimitive.Portal>
    <DialogPrimitive.Overlay className="fixed inset-0 bg-black/50" />
    <DialogPrimitive.Content
      ref={ref}
      className={cn("fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white rounded-lg p-6", className)}
      {...props}
    >
      {children}
    </DialogPrimitive.Content>
  </DialogPrimitive.Portal>
))
```

}>
  This gives you a styled component that still accepts all primitive props and supports `asChild`.