Manipulating Slot Content With OverrideNode
When you start using react-slots
, you'll notice a new pattern emerging in your
components. Instead of creating components with a massive list of props that
control every aspect of the component's rendered content, you'll be drawn to
creating components with "holes" meant to be filled with parent-provided
free-form content and some logic that binds these holes or slots together.
This is a good thing because it allows for a higher level of composability, and
maintaining small pieces independently is much easier than maintaining giant
components.
Despite its benefits, parent-provided free-form content has a drawback: it's a black box. It might have any shape, its props, event listeners, or styles, and all of it is hidden away from you. This makes it challenging to integrate free-form content into the specific logic of your components.
OverrideNode
gives you direct access to the parent-provided nodes and exposes
a convenient API to manipulate them right before they get rendered.
You can use OverrideNode
to:
- Enforce node types.
- Intercept element events and execute side-effects before or after their event handlers.
- Add or change element props.
- Add aria attributes for accessibility.
- Change the nodes in any way.
OverrideNode
is just a React element. It can be included as a direct child of
a slot element. When present, it has the ability to override parent-provided
content for the slot. Additionally, if the slot content is not provided, the
children within OverrideNode
will act as a fallback content and the override
will apply to them.
OverrideNode
always applies to the parent-provided content but only applies
to the section of the fallback content wrapped by the OverrideNode
.
Let's take a look at some high-level examples before delving into the API documentation in the next sections:
import { OverrideNode } from "@beqa/react-slots";
// Throw an error if the parent provides any element other than "h1", "h2", "h3".
// The rule doesn't apply to fallback content.
<slot.default>
<OverrideNode allowedNodes={["h1", "h2", "h3"]} />
<div>
<h2>Fallback</h2>
</div>
</slot.default>;
// Remove any node other than a button from the parent's provided "trigger" slot content.
// If the parent provides a button, intercept its onClick event.
// The rule also applies to fallback, which is <button>Trigger</button>.
<slot.trigger>
<OverrideNode
allowedNodes={["button"]}
enforce="remove"
props={{ onClick: OverrideNode.chainAfter(() => alert("Button clicked")) }}
>
<button>Trigger</button>
</OverrideNode>
</slot.trigger>;