Composition
A guide to composing Base UI components with your own React components.
Composing custom React components
Use the render prop to compose a Base UI part with your own React components.
For example, most triggers render a <button> by default.
The code snippet below shows how to use a custom button instead.
The custom component must forward the ref, and spread all the received props on its underlying DOM node.
Composing multiple components
In situations where you need to compose multiple Base UI components with custom React components, render props can be nested as deeply as necessary.
Working with Tooltip is a common example.
How props are merged
When the render prop receives an element, the part’s props and the element’s props are merged onto a single element.
For example, this toolbar button renders a menu trigger:
The rendered <button> gets:
className="menu-trigger toolbar-button": class names are combined, starting with the render element’s.style={{ color: 'blue', padding: 4 }}: style objects are merged, and the render element’s values win.- Both click handlers, starting with
handleMenuClick. Callingevent.preventBaseUIHandler()skips every handler that runs after it, so calling it inhandleMenuClickalso skipshandleToolbarClick. Some parts call it internally. - Both refs:
toolbarButtonRefandmenuTriggerRefpoint to the same element.
For other attributes set on both, such as id or title, the render element’s value wins.
Component props like disabled are read by each part separately, so a value on the render element doesn’t override the part’s own.
The render prop merges props with mergeProps, except for refs: mergeProps keeps only the rightmost ref, while the render prop keeps all of them.
Changing the default rendered element
You can also use the render prop to override the rendered element of the component.
For example, <Accordion.Header> renders an <h3> element by default.
The code snippet below shows how to render it as an <h2> element so that it fits the heading hierarchy of the page.
Each Base UI component renders the most appropriate element by default, and in most cases, rendering a different element is recommended only on a case-by-case basis.
Render function
If you are working in an extremely performance-sensitive application, you might want to pass a function to the render prop instead of a React element.
Using a function gives you complete control over spreading props and also allows you to render different content based on the component’s state.