Composition
Create adaptable user interfaces using component composition techniques.
Elemnts UI components are built with flexibility in mind, giving you two powerful ways to customize how components render: the as prop and the asChild prop. Both are powered by Ark UI.
Changing the HTML Element
The as prop lets you swap out the default HTML element while keeping all the component's styles and functionality intact.
When to use as:
- Need a different semantic HTML element (e.g., turning a
pinto aspan) - Want to maintain styling while changing the underlying tag
Composing Components
The asChild prop is perfect when you want to wrap Elemnts UI components around custom components—like framework-specific links (TanStack Router, Next.js Link) or your own UI elements.
When enabled, asChild passes all props and behavior to its direct child, effectively making the Elemnts UI component invisible in the DOM.
Key Rules for asChild
| Rule | Description |
|---|---|
| Single Child | Only one child element is allowed inside the component. |
| Prop Merging | If both parent and child define the same prop (e.g., onClick), both functions will execute. |
| Ref Forwarding | The child component must support ref forwarding to ensure compatibility with Ark UI. |
Building Your Own Components
Elemnts UI provides factory and styled to help you create polymorphic, styled components.
Using factory (Ark UI)
The factory (aliased from ark) lets you generate HTML elements that natively support the asChild prop.
Using styled
The styled function combines an element (or factory element) with a Panda CSS recipe or styles.
Custom Prop Filtering
By default, styled excludes style-related props from the DOM. You can override this with shouldForwardProp.
Best Practices
| Use Case | Prop | Why? |
|---|---|---|
Swapping HTML elements (e.g., p → span) | as | Simple and effective for semantic changes |
Wrapping framework-specific components (e.g., Router Link) | asChild | Ensures compatibility with custom logic |
| Maintaining accessibility | Both | Always verify ARIA roles and keyboard interactions when changing elements (e.g., as="button" on a div) |

