Advanced
Multiple OverrideNode Elements

Using Multiple OverrideNode Elements

You can include multiple OverrideNode elements for a single slot as long as they are all top-level children. When you use multiple OverrideNode elements, their overrides are applied from top to bottom to the parent-provided content. The result of the previous override becomes the input for the next OverrideNode. When the parent doesn't provide content, only the OverrideNode elements that wrap the fallback content will be applied.

In this example, a component restricts the node type for the "trigger" slot to be either a button element or a string and then handles their overrides separately:

<slot.trigger>
  <OverrideNode allowedNodes={["button", String]} />
  {/* Override string nodes */}
  <OverrideNode
    allowedNodes={[String]}
    enforce="ignore" // Don't throw an error if not a string
    node={(node) => {
      <button onClick={myClickHandler}>{node}</button>;
    }}
  />
  {/* Override button elements */}
  <OverrideNode
    allowedNodes={["button"]}
    enforce="ignore" // Don't throw an error if not a button
    props={{
      onClick: OverrideNode.chainAfter(myClickHandler),
    }}
  />
  {/* Nothing was provided, render fallback */}
  <button onClick={myClickHandler}>Trigger</button>
</slot.trigger>

Here's an example that demonstrates the difference between applying overrides to provided content versus fallback content:

function MyComponent(children) {
  const { slot } = useSlot(children);
 
  return (
    <slot.default>
      <OverrideNode node={(node) => <div>{node}</div>} />
      <OverrideNode props={{ className: () => "added-class" }}>
        <span>Fallback</span>
      </OverrideNode>
      <OverrideNode allowedNodes={["div"]} props={{ id: () => "added-id" }}>
        <div>Second Fallback</div>
      </OverrideNode>
    </slot.default>
  );
}
 
// Providing content:
<MyComponent>Content</MyComponent>;
// Expected HTML output:
<div class="added-class" id="added-id">
  Content
</div>;
 
// No content:
<MyComponent />;
// Expected HTML output:
<span class="added-class">Fallback</span>;
<div id="added-id">Second Fallback</div>;