-
Notifications
You must be signed in to change notification settings - Fork 26
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
[WIP] feat(radio-input): add components prop to radio input option #1139
Conversation
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.
Cool you picked this up so quickly!
@@ -29,7 +29,7 @@ const Group = props => { | |||
const optionElements = React.Children.map(props.children, (child, index) => { | |||
// NOTE: Allowing to intersperse other elements than `Option`. | |||
if (child && child.type.displayName === Option.displayName) { | |||
return React.cloneElement(child, { | |||
const option = React.cloneElement(child, { |
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: maybe children
as a name would be apt here.
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.
const clonedChild
?
@@ -41,6 +41,13 @@ const Group = props => { | |||
onFocus: props.onFocus, | |||
onBlur: props.onBlur, | |||
}); | |||
return child.props.components.WrapperComponent ? ( |
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! Wondering, as I always struggle to read <a
with a lowercase character if it is actually a React component. Would
const Wrapper = child.props.components.WrapperComponent || React.Fragment;
work to then just do:
<Wrapper>{children}</Wrapper>
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.
Hm, another approach we could go for just allows any child
but leave it up to the consumer to not allow prop spreading. That way we don't need a new components prop.
So for your case, you would do something like this. Basically capture the props in your wrapper then pass them to the component that should receive them (RadioOption).
const Wrapper = props => {
<ToolTip off={isTooltipOff}>
<RadioInput.Option {...props} />
<ToolTip>
}
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 like this self-service approach. Would we be recursively searching for an RadioInput.Option as a child for the invariant, or removing the check all together, what do you think?
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 would be fine with removing it. A recursive search could also be misleading. As in: somewhere in the component tree there is a Radio.Option
but it wasn't the one the developer but "nearby" his concern. So the invariant will maybe rarely give an appropriate hint.
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.
Hm, I'm not sure how we could do this though without making it a breaking change.
@@ -66,6 +67,16 @@ Option.propTypes = { | |||
PropTypes.element, | |||
PropTypes.func, | |||
]).isRequired, | |||
components: PropTypes.shape({ | |||
WrapperComponent: (props, propName) => { |
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.
is this really necessary? Can't we just make it optional?
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.
You mean the children
prop right?
@montezume @tdeekens
|
Hm, good question. So far we only swaped out default components while applying "internal" props to them. Correct me if that's wrong @montezume.
Sorry I am just thinking out loud. 🤔 would it make sense just not to render the wrapper component in the parent? It doesn't really solve the "issue" though. |
return new Error( | ||
`Invalid prop 'components.WrapperComponent' supplied to 'RadioInput.Option': the prop is not a valid React component` | ||
); | ||
wrapper: (props, propName) => { |
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.
Wondering. Is this almost the same as PropTypes.oneOf([PropTypes.func, PropTypes.array, PropTypes.elementType])
?
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.
Tried to restrict it to a function (1st if) that receives one argument (2nd if) and returns a valid react.element (3rd if)
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.
Maybe a bit over engineered and fails stupidly, thought it could help/guide the user maybe
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.
True. It's a nice idea! Maybe it's also something UIKit could share and reuse internally.
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 played around with it locally. Really nice approach. 🎉
Thanks @dogayuksel
@tdeekens do you want to review? |
Not sure why Percy didn't report ... it passed https://percy.io/commercetools-GmbH/ui-kit/builds/2967506 |
@@ -41,6 +41,8 @@ const Group = props => { | |||
onFocus: props.onFocus, | |||
onBlur: props.onBlur, | |||
}); | |||
const { wrapper } = child.props.components; | |||
return wrapper ? wrapper(clonedChild) : clonedChild; |
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 cool.
Summary
Allows passing in a react element to wrap RadioInput.Option with.