-
Notifications
You must be signed in to change notification settings - Fork 879
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[@labs/react] support multiple children with multiple slots #2985
base: main
Are you sure you want to change the base?
Conversation
🦋 Changeset detectedLatest commit: 05d4b5f The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments; we also need to add documentation to the readme for this.
key: slot, | ||
slot, | ||
}, | ||
children |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I expected this to be an array. Why isn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is arguable and we should sync up on this before changing the code, but I think it's preferable to set slot attributes where possible rather than to create a wrapper DOM node.
However, if a wrapper node is needed, probably we should just make one and not set slots. So, this would involve iterating the children until you find a non-element node (text nodes or component references): if so making the wrapper; if not, cloneElement and set slots.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe React.ReactNode can be any value that react will render: string array ref node element. Children are passed through a single property name in react / jsx (or as "children"). So when a child
is asked to createSlottedChild
it wraps the entire prop to a slot via one wrap.
I figured this was less operations for the same behavior, choosing to wrap the entire children prop in a single function than search and create multiple. If the CSS display contents
let's us avoid styling I figured this would be the most direct way to slot quickly and cheaply
A clarifying question: Are we expecting a user to pass in some value than a React.ReactNode?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating the wrapper DOM node itself is likely the most expensive part. If we can avoid it and just set slot attributes, we probably should. I wanted to explore what was possible via their API and so made this experiment which might be useful.
React: typeof ReactModule, | ||
tagName: string, | ||
elementClass: Constructor<I>, | ||
events?: E, | ||
displayName?: string | ||
displayName?: string, | ||
children?: C |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it makes more sense to call this argument slots
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good!
) => { | ||
const Component = React.Component; | ||
const createElement = React.createElement; | ||
const reactChildren = children; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why rename this? Let's just choose a better name as suggested above.
@@ -73,11 +73,18 @@ suite('createComponent', () => { | |||
onBar: 'bar', | |||
}; | |||
|
|||
const basicElementChildren = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, recommend calling this basicElementSlots
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good!
@@ -333,6 +340,19 @@ suite('createComponent', () => { | |||
assert.equal(el.firstElementChild!.localName, 'div'); | |||
}); | |||
|
|||
test('can set multiple children to multiple slots', async () => { | |||
const children = window.React.createElement('div'); | |||
const foos = window.React.createElement('div'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to test that you can specify a a set of children for a slot. Ideally we'd be testing with JSX here as well. I think in that case it would be a JSX fragment and without JSX I guess you can make that via a React.createElement(React.Fragment, ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Yah I'll add that test case
|
||
assert.equal(el.childNodes.length, 3); | ||
assert.equal(el.children?.[0].getAttribute('slot'), null); | ||
assert.equal(el.children?.[1].getAttribute('slot'), 'slot-a'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be display: contents
right? Let's test for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yah let's! Sounds good
Ugh dumb thumbs, how do I cancel this review ;_; |
React: typeof ReactModule, | ||
tagName: string, | ||
elementClass: Constructor<I>, | ||
events?: E, | ||
displayName?: string | ||
displayName?: string, | ||
children?: C |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit (naming): The fact that children
is ambiguous enough that it needs to be renamed below is a smell... I'd prefer calling this slotMap
or something like that; same with events
-> eventMap
(along with the types Children
-> SlotMap
and Events
-> EventMap
.
Could I ask for why this is not being merged? Thank you. |
Related to #2734
This PR supports multiple children by assigning them to multiple slots by wrapping them in a
<div styles="display: contents">
.A client can provide a
children
map similar to how we account forevents
.The syntax is as follows:
Which results in a
children
config like:Tests are added to verify rendered elements are rendered with the correct
slot
names.