-
Notifications
You must be signed in to change notification settings - Fork 77
feat: refactor Tile removing ProductTile component #548
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
Conversation
|
Deploy preview for fundamental-react ready! Built with commit da92e76 |
jbadan
left a comment
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.
src/Tile/Tile.js
Outdated
| Tile.defaultProps = { | ||
| productTile: false | ||
| }; | ||
|
|
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.
If a prop's default is false, you don't need to include it in the defaultProps object -- it will automatically be evaluated as falsy.
src/Tile/_TileContent.js
Outdated
| return ( | ||
| <div {...rest} className={tileContentClasses}> | ||
| <HeadingTag {...titleProps} className='fd-tile__title'>{title}</HeadingTag> | ||
| <HeadingTag {...titleProps} className={productTile ? 'fd-product-tile__title' : 'fd-tile__title'}>{title}</HeadingTag> |
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 probably be extracted out into a variable that uses classnames.
| @@ -1,37 +1,10 @@ | |||
| import classnames from 'classnames'; | |||
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 this sub-component can be removed altogether as the only thing it does is pass a productTile prop to TileContent. This can be done by cloning children with the Tile component and passing the top-level productTile prop.
src/Tile/ProductTile.js
Outdated
| disabled: PropTypes.bool | ||
| }; | ||
|
|
||
| ProductTile.Content = ProductTileContent; |
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 can be changed to ProductTile.Content = TileContent; (see other related comments)
| colorAccent: PropTypes.number, | ||
| columnSpan: CustomPropTypes.range(1, 6), | ||
| disabled: PropTypes.bool, | ||
| productTile: PropTypes.bool, |
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 this component should clone children and pass the top-level productTile prop to each child so the prop only needs to be added at the top-level component. (see related comments)
src/Tile/_ProductTileMedia.js
Outdated
| ProductTileMedia.propTypes = { | ||
| image: PropTypes.string.isRequired, | ||
| className: PropTypes.string | ||
| image: PropTypes.string.isRequired |
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.
In the propDescriptions for this prop, it should probably say "URL of the background image" so it's clearer to the consumer what is to be expected.
|
@hertweckhr1 @jbadan Ok, I've been looking at this some more. It's sort of a strange assembly of components and sub-components. Looking at the docs site examples (and playground), there seems to be three types: simple, media and product. They are very similar, but the media aspect of media and product tiles is different -- one accepts children, which seem best suited for an What about something like this? Simple: <Tile>
<Tile.Content title="Text">
Some content
</Tile.Content>
</Tile>Media: <Tile>
<Tile.Media>
<Image />
</Tile.Media>
<Tile.Content title="Text">
Some content
</Tile.Content>
</Tile>Product: <Tile backgroundImage="http://some.url/image" productTile>
<Tile.Content title="Text">
Some content
</Tile.Content>
</Tile>That would get rid of all the Thoughts? |
|
@greg-a-smith @jbadan - this sounds good to me. Would it end up being 4 different types with Tile actions being added on as well? Or is having actions on a tile an option for all 3 simple, media, and product? |
|
@hertweckhr1 To me, I think this really converts the different "types" of tiles to patterns rather than components. In this single component model (with sub-components), you could technically put actions or media (image) on a product tile or put a background image on a non-product tile, but those are not supported patterns. I think the examples on the docs site should just show how to use the components to create each option:
|
src/Tile/_TileMedia.js
Outdated
| TileMedia.displayName = 'Tile.Media'; | ||
|
|
||
| TileMedia.propTypes = { | ||
| backgroundImage: PropTypes.string, |
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 was thinking this prop would/could be on the Tile component since that already has a prop called backgroundColor. To me, TileMedia is more designed as a wrapper for children (images) rather than a URL string prop.
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.
@greg-a-smith would you have the style tag for backgroundImage go on Tile itself then instead of media or would you pass down the backroundImage prop to media? When I originally put it on Tile, it did not format correctly: the image took up the entire background of the Title portion as well and was not big enough, so thought to keep it in Media where there is the 'fd-product-tile__media' class has previously lived maybe making it easier for the consumer to associate media with a photo in general? (whether it be background of small icon).
Either if fine with me - can you confirm if you want it on tile I should put the style tag on tile and add the fd-product-tile__media class name as well?
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 the final emitted markup would be the same as you have it now, but Tile would have the prop and would render the child <div> where it needs it to go. You are right, the way the styles are written, placing the style attribute on the top-level tile <div> would not be correct.
jbadan
left a comment
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 looking great!!! I just have a few small changes.
src/Tile/Tile.js
Outdated
| className={tileClasses}> | ||
| {children} | ||
| {React.Children.toArray(children).map(child => { | ||
| if (child.type !== TileActions) { |
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's slightly safer to do this equality (or non-equality) check using the displayName (see TreeView code).
| {children} | ||
| {productTile && | ||
| <div className='fd-product-tile__media' style={{ backgroundImage: 'url(' + backgroundImage + ')' }} /> | ||
| } |
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 created a conditional for product tile rather than if the background image exists bc product tiles should have background images with them always. This will eliminate the issue Jenna mentioned with background image rendering undefined for tiles that are not product.
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.
Well, technically it won't. There are really two props needed for a product tile: productTile and backgroundImage so it's possible the consumer passes one, but not the other. That said, this has become more of a pattern-based component so I think this is a good change. We could make productTile a shape prop with a required backgroundImage, but that might be overkill here. As we've said in this PR, the consumer just wants to know which props to pass and the example page will help them with 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.
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.
The code changes look great! I am just wondering about cleaning up the examples a bit. We show a disabled product tile, but the disabled prop actually works for all types of tiles. Should we add example of those? Or, (thinking out loud here) should we remove the disabled examples until the clickability of tiles is addressed. Otherwise, there is really nothing to "disable". If we did leave disabled examples, how about a single "Disabled" example with a simple, a media, a simple with actions and product tile?
We also definitely need a follow-up story to address the clickability of tiles. Adding the role="button" is adding some hover styling that would indicate the tile is clickable, however, there is nothing in the API that would handle that. It seems like an onClick prop should be passed, which then can add roles, aria labels, use different elements, etc.
Addendum: we also have to be careful about tiles with actions as a clickable element cannot also have children that are clickable.
greg-a-smith
left a comment
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.
All aboard! 🚢


Description
Refactored Tile to reduce redundancy:
New prop productTile(boolean) was created and passed down.
Questions to consider:
fixes #440