# Composition

URL: https://ark-ui.com/docs/guides/composition
Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/guides/composition.mdx

Learn how to compose default components with custom elements

---

## The asChild Prop

In Ark Ripple, `asChild` lets you integrate custom components, ensuring consistent styling and behavior while
promoting flexibility and reusability. All Ark components that render a DOM element accept `asChild`.

Here's an example using `asChild` to integrate a custom `Button` component within a `Popover`:

<ExampleCode id="as-child" component="popover" />

In this example, `asChild` allows the `Button` to be used as the trigger for the `Popover`, inheriting its
behaviors from Popover.Trigger.

## The Ark Factory

You can use the `ark` factory to create your own elements that work just like Ark Ripple components.

<ExampleCode id="factory" component="popover" />

This will produce the following HTML:

```html
<span id="child" class="parent child" style="background: red; color: blue;">Ark UI</span>
```

## ID Composition

When composing components that need to work together, share IDs between them using the `ids` prop for proper
accessibility and interaction.

```ripple
import { Avatar } from 'ark-ripple/avatar'
import { Tooltip } from 'ark-ripple/tooltip'

export component TooltipWithAvatar() {
  const id = ':ark-avatar'

  <Tooltip.Root ids={{ trigger: id }}>
    <Tooltip.Trigger>
      component asChild({ propsFn }){
        <Avatar.Root {...propsFn({ ids: { root: id } })}>
          <Avatar.Image src="https://bit.ly/sage-adebayo" />
          <Avatar.Fallback>{"SA"}</Avatar.Fallback>
        </Avatar.Root>
      }
    </Tooltip.Trigger>
    <Tooltip.Positioner>
      <Tooltip.Content>{"Abraham Aremu is online"}</Tooltip.Content>
    </Tooltip.Positioner>
  </Tooltip.Root>
}
```

Both components share the same `id` through their `ids` props, creating proper accessibility bindings, `aria-*`
attributes and interaction behavior.

## Limitations

Certain components, such as `Checkbox.Root` or `RadioGroup.Item`, have specific requirements for their child elements.
For instance, they may require a label element as a child. If you change the underlying element type, ensure it remains
accessible and functional.