mergeProps

A utility function to merge props objects.

Overview

mergeProps is a utility function designed to merge multiple props objects. It's particularly useful for composing components with different prop sets or extending the functionality of existing components.

It is used internally by Bits UI components to merge the custom restProps you pass to a component with the props that Bits UI provides to the component.

Key Features

  • Merges multiple props objects
  • Chains event handlers with cancellation support
  • Combines class names
  • Merges style objects and strings
  • Chains non-event handler functions

Detailed Behavior

Event Handlers

Event handlers are chained in the order they're passed. If a handler calls event.preventDefault(), subsequent handlers in the chain are not executed.

	const props1 = { onclick: (e: MouseEvent) => console.log("First click") };
const props2 = { onclick: (e: MouseEvent) => console.log("Second click") };
 
const mergedProps = mergeProps(props1, props2);
mergedProps.onclick(new MouseEvent("click")); // Logs: "First click" then "Second click"

If preventDefault() is called:

	const props1 = { onclick: (e: MouseEvent) => console.log("First click") };
const props2 = {
	onclick: (e: MouseEvent) => {
		console.log("Second click");
		e.preventDefault();
	},
};
const props3 = { onclick: (e: MouseEvent) => console.log("Third click") };
 
const mergedProps = mergeProps(props1, props2, props3);
mergedProps.onclick(new MouseEvent("click")); // Logs: "First click" then "Second click" only

Since props2 called event.preventDefault(), props3's onclick handler will not be called.

Non-Event Handler Functions

Non-event handler functions are also chained, but without the ability to prevent subsequent functions from executing:

	const props1 = { doSomething: () => console.log("Action 1") };
const props2 = { doSomething: () => console.log("Action 2") };
 
const mergedProps = mergeProps(props1, props2);
mergedProps.doSomething(); // Logs: "Action 1" then "Action 2"

Classes

Class names are merged using clsx:

	const props1 = { class: "text-lg font-bold" };
const props2 = { class: ["bg-blue-500", "hover:bg-blue-600"] };
 
const mergedProps = mergeProps(props1, props2);
console.log(mergedProps.class); // "text-lg font-bold bg-blue-500 hover:bg-blue-600"

Styles

Style objects and strings are merged, with later properties overriding earlier ones:

	const props1 = { style: { color: "red", fontSize: "16px" } };
const props2 = { style: "background-color: blue; font-weight: bold;" };
 
const mergedProps = mergeProps(props1, props2);
console.log(mergedProps.style);
// "color: red; font-size: 16px; background-color: blue; font-weight: bold;"
	import { mergeProps } from "bits-ui";
 
const props1 = { style: "--foo: red" };
const props2 = { style: { "--foo": "green", color: "blue" } };
 
const mergedProps = mergeProps(props1, props2);
 
console.log(mergedProps.style); // "--foo: green; color: blue;"