Documentation Index Fetch the complete documentation index at: https://mintlify.com/zayne-labs/ui/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The Slot component merges its props with its child element, enabling prop forwarding and composition patterns. It’s useful for creating flexible, composable components that don’t add extra DOM nodes.
Import
import { Slot } from "@zayne-labs/ui-react/common/slot" ;
// or
import { SlotRoot , SlotSlottable } from "@zayne-labs/ui-react/common/slot" ;
Component Parts
Slot.Root Merges props into the child element
Slot.Slottable Marks content as the target for slotting
Slot.Root
Props
children
React.ReactElement
required
A single React element to merge props into. Must be a valid React element.
Ref to be composed with the child’s ref.
All other props are merged with the child element’s props.
Slot.Slottable
Props
The content to be slotted. Must be a single React element.
Usage Examples
Basic Prop Merging
function Button ({ asChild , ... props }) {
const Component = asChild ? Slot . Root : 'button' ;
return (
< Component className = "btn" { ... props } >
{ props . children }
</ Component >
);
}
// Usage - renders an <a> with merged classes and onClick
< Button asChild onClick = { handleClick } >
< a href = "/home" className = "link" > Go Home </ a >
</ Button >
// Result: <a href="/home" className="btn link" onClick={handleClick}>Go Home</a>
Ref Composition
function Input ({ asChild , ... props }) {
const internalRef = useRef ();
const Component = asChild ? Slot . Root : 'input' ;
return < Component ref = { internalRef } { ... props } /> ;
}
function Form () {
const externalRef = useRef ();
// Both refs will be set
return (
< Input asChild ref = { externalRef } >
< input type = "text" />
</ Input >
);
}
Event Handler Merging
function Clickable ({ asChild , onClick , ... props }) {
const handleInternalClick = ( e ) => {
console . log ( 'Internal click' );
onClick ?.( e );
};
const Component = asChild ? Slot . Root : 'div' ;
return < Component onClick = { handleInternalClick } { ... props } /> ;
}
// Both click handlers will fire
< Clickable asChild onClick = { () => console . log ( 'External click' ) } >
< button > Click me </ button >
</ Clickable >
Using Slottable
function Card ({ asChild , children }) {
const Component = asChild ? Slot . Root : 'div' ;
return (
< Component className = "card" >
< div className = "card-header" > Header </ div >
< Slot.Slottable > { children } </ Slot.Slottable >
< div className = "card-footer" > Footer </ div >
</ Component >
);
}
// The article element receives the card class
< Card asChild >
< article >
< h2 > Title </ h2 >
< p > Content </ p >
</ article >
</ Card >
// Result:
// <article className="card">
// <div className="card-header">Header</div>
// <h2>Title</h2>
// <p>Content</p>
// <div className="card-footer">Footer</div>
// </article>
Creating Polymorphic Components
function Text ({ asChild , size = 'md' , ... props }) {
const Component = asChild ? Slot . Root : 'span' ;
return (
< Component
className = { `text- ${ size } ` }
{ ... props }
/>
);
}
// Render as different elements
< Text > Default span </ Text >
< Text asChild >< p > Paragraph with text styles </ p ></ Text >
< Text asChild >< h1 > Heading with text styles </ h1 ></ Text >
Complex Composition
function Dialog ({ asChild , open , onOpenChange , children }) {
const Component = asChild ? Slot . Root : 'div' ;
return (
< Component
role = "dialog"
aria-hidden = { ! open }
data-state = { open ? 'open' : 'closed' }
>
{ children }
</ Component >
);
}
< Dialog asChild open = { isOpen } onOpenChange = { setIsOpen } >
< aside className = "sidebar" >
< DialogContent />
</ aside >
</ Dialog >
Style Merging
function Box ({ asChild , ... props }) {
const Component = asChild ? Slot . Root : 'div' ;
return (
< Component
style = { { padding: '1rem' , border: '1px solid' } }
{ ... props }
/>
);
}
// Styles are merged
< Box asChild >
< section style = { { backgroundColor: 'blue' } } >
Content
</ section >
</ Box >
// Result has both padding/border AND backgroundColor
With forwardRef
const CustomButton = forwardRef (({ asChild , ... props }, ref ) => {
const Component = asChild ? Slot . Root : 'button' ;
return (
< Component
ref = { ref }
className = "custom-btn"
{ ... props }
/>
);
});
function App () {
const btnRef = useRef ();
return (
< CustomButton asChild ref = { btnRef } >
< a href = "/" > Link Button </ a >
</ CustomButton >
);
}
Notes
The component only accepts a single child element (enforced via Children.only)
Props are merged using a custom mergeProps utility that handles event handlers and styles intelligently
Refs are composed so both parent and child refs work correctly
When the child is a Fragment, ref composition is skipped
Slot.Slottable helps preserve additional wrapper content while slotting the main child
Class names, styles, and event handlers are intelligently merged, not replaced
Based on Radix UI’s Slot implementation