Capítulo 40 de 43

Chapter 40: Slot (Utility)

Core Idea

Merges its own props/ref onto its single immediate child instead of rendering a wrapper element — the exact mechanism behind every Radix part's asChild prop, and reusable to build the same pattern into your own components.

Key Concepts

  • Slot.Root: swap in for a native tag (e.g. "button") when a consumer passes asChild to your own component, exactly how Radix parts implement asChild internally.
  • Slot.Slottable: needed when your component renders multiple children around the slotted one (e.g. icon + text) — marks which child should actually receive the merged props/ref, since Slot only merges onto a single element by default.
  • Event handler merging: when both Slot and the child define the same on* handler, the child's handler runs and takes precedence; if handler order matters for event.defaultPrevented checks, verify the composed order explicitly.

Code Examples

function Button({ asChild, ...props }) {
  const Comp = asChild ? Slot.Root : "button";
  return <Comp {...props} />;
}

// usage
<Button asChild><a href="/contact">Contact</a></Button>
  • What it demonstrates: the minimal pattern for adding your own asChild prop to a custom component, identical in spirit to how Radix's own parts implement it.

Key Takeaways

  1. Build asChild support into your own design-system primitives with this exact pattern whenever you want them composable the same way Radix's parts are.
  2. Use Slottable (not a second Slot.Root) when your component wraps the slotted child with sibling content — it tells Slot which specific child to merge onto.
  3. Event handlers merge with child-takes-precedence — audit this explicitly if your component's own handler relies on running first or on event.defaultPrevented.

Connects To

  • Composition guide: the conceptual overview of asChild this utility technically implements.