Description
Provide a general summary of the issue here
When it comes to expanding on the the slots that an RAC provides, it's impossible to maintain the parent context and implement new slots without running into errors.
I'm providing a concrete example based on a single RAC, but this pattern applies to all RAC. The overall concept of named slots is currently very hardcoded and inflexible
🤔 Expected Behavior?
It should be possible to add named slots to any context without errors being thrown within RAC. Conflicts between DS and RAC slot names should only result in warnings and should merge on all applicable props as intended
😯 Current Behavior
Given the scenario:
DSButton
consumes a new DSButtonContext
and is built on top of the RAC Button
DSGridListItem
implements a DSButtonContext
with named slots that don't match the RAC GridListItem
ButtonContext
named slots
An error is thrown or functionality is lost
For context, RAC GridListItem provides DEFAULT_SLOT and "drag" as a named slot
Error Thrown:
If the DSGridListItem
implements a named slot of "foobar", and the DSButton
attempts to utilize that slot, RAC will throw an error that only "drag" is a valid named slot and that "foobar" is an invalid named slot
It's also not possible to override the slot prop from the DSButtonContext
, because local props always take precedence. For example, if the "foobar" slot were to try and pass slot: DEAFULT_SLOT,
, the error is still thrown because the component has the higher precedence prop slot="foobar"
already on it
Functionality Lost:
If the DSGridListItem
were to implement the RAC ButtonContext
with the named slot "foobar", then all props for the slots provided by RAC are lost
💁 Possible Solution
Make the RAC slot validation (
) dev environment only warnings instead of errors🔦 Context
While we have had a workaround solution (#6610), my team has been discussing how to align more closely with the guidance provided by RAC folks. The main guidance we've been provided is to utilize the new context for every DS component approach.
This is why we created a wrapper for all of the simple, low level components that are not receiving direct DS attention:
function wrap<P extends object, E extends HTMLElement>(
Component: (props: P & RefAttributes<E>) => ReactElement | null
) {
const Context = createContext<ContextValue<P, E>>(null);
return {
Component: forwardRef(function WrappedComponent(
props: P,
ref: ForwardedRef<E>
) {
[props, ref] = useContextProps(props, ref, Context);
return <Component {...props} ref={ref} />;
}),
Context,
};
}
export const { Component: AriaText, Context: AriaTextContext } = wrap(Text);
🖥️ Steps to Reproduce
https://codesandbox.io/p/sandbox/delicate-worker-9dmh72
Version
"@react-aria/utils": "3.25.1", "@react-stately/utils": "3.10.1", "react-aria": "3.33.1", "react-aria-components": "1.2.1", "react-stately": "3.31.1",
What browsers are you seeing the problem on?
Chrome
If other, please specify.
No response
What operating system are you using?
Mac & Windows
🧢 Your Company/Team
No response
🕷 Tracking Issue
No response