Let a Primitive Render as Its Child
SHOULD: Give styled primitives an asChild / Slot escape hatch so they can render AS the element they wrap (a Button that is really an <a href>) instead of forcing a fixed tag or nesting interactive elements. Styling stays with the primitive; semantics stay with the child.
Give styled primitives an asChild / Slot escape hatch so a Button can BE a link instead of wrapping one
<Button asChild>
<a href="/pricing">Pricing</a>
</Button>Bad
Good
Why it matters
A `<Button>` that only ever renders a `<button>` forces a bad choice the moment you need it to navigate: either fake a link with an onClick (losing href, middle-click, open-in-new-tab, and the right role) or wrap it in an `<a>` and nest two interactive elements, which is invalid and confuses assistive tech. The `asChild` pattern — Radix's Slot — resolves it by merging the primitive's classes, refs, and event handlers onto the single child you pass, so `<Button asChild><a href>` renders one real anchor that looks and behaves like the button.
It keeps styling and semantics in separate hands: the primitive owns the look, the child owns what the element actually IS. This is how shadcn/ui buttons become links, menu items become `<Link>`s, and triggers wrap arbitrary controls without a prop explosion.