-
Notifications
You must be signed in to change notification settings - Fork 10.3k
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
feat(gatsby-image): Add customProps as catchall #25283
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.
Personally not fond of this approach. If props need to be passed on in a vague manner, it should at least be better contained rather than relying on spreading remaining props.
I'm going to move this to draft for now as I'm not 100% sure we want to add this to gatsby-image. For discussion I would like us to move to the issue. |
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.
tagProps
isn't a good name, as there are multiple instances of Tag
and you're only wanting to use it for the wrapping element. Use wrapperAttrs
, that more clearly communicates it's for the wrapper only and is for passing element attributes not component props. attrProps
may also be valid since the wrapper is top-level.
You also need to add this to Image.propTypes
at the bottom of the file.
@@ -486,6 +487,7 @@ class Image extends React.Component { | |||
}} | |||
ref={this.handleRef} | |||
key={`fluid-${JSON.stringify(image.srcSet)}`} | |||
{...tagProps} |
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 should be the first prop, place it above all others, otherwise it introduces the possibility to override all prior props for this component.
@@ -601,6 +603,7 @@ class Image extends React.Component { | |||
style={divStyle} | |||
ref={this.handleRef} | |||
key={`fixed-${JSON.stringify(image.srcSet)}`} | |||
{...tagProps} |
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.
Same as other comment, order matters, place this above all other props.
Hey! Thanks so much for opening a pull request! We decided to go not forward with the issue and feature request. So, I'll be closing this PR. We absolutely want to have you as a contributor, so please take a look at our open issues for ideas, and please reach out to us on Twitter at @gatsbyjs with questions. We offer pair programming sessions if you’d like to work with one of our maintainers to make another contribution. Thanks again, and we look forward to seeing more PRs from you in the future! 💪💜 |
@wardpeet It should have been ok to go ahead with this if the change request from my review was done. It shouldn't cause any problems or maintenance concerns if done that way. Related issue stated reasoning for closing as:
I'm not sure what weird bugs or other issues will arise? Originally it was an issue because of how props were being provided to It's not possible to assign aria attributes otherwise? What is the suggested workaround? I believe the related issue had some comments for why relying on additional wrapping layer is undersirable. |
Oh, I think Github bailed on me. It still had the old code and didn't show a refresh button. I still think this is not a great addition and lots of it can be done with working on the wrapper. I'll re-open as it seems like some people see it as a valuable option. Note that this will be removed in the next major version. |
@@ -437,6 +437,7 @@ class Image extends React.Component { | |||
itemProp, | |||
loading, | |||
draggable, | |||
tagProps = {}, |
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.
Let's be extra explicit here
tagProps = {}, | |
imageTagProps = {}, |
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.
It's not for the img
element though? It's for the div
(default tag) wrapper element. My review suggested wrapperAttrs
or attrProps
which is more clear what the purpose of this props is(attributes for passing to the top-level element). We have lots of "image"/"tag"/"props" keywords in the file already, so I definitely think it's more clearer in all that keyword noise to be more specific it's about attributes.
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.
Can you update tests & documentation please.
Thank you for working on this!
Seems like I'm having a bad day... Went a bit more thoroughly through the PR. After properly reading it I don't see a use case for this cause this can easily be negated by a wrapper component and using React composition. I don't see value in adding another prop to the gatsby-image. import * as React from 'react';
import GatsbyImage from 'gatsby-image';
export default function Image({ tagProps, ...props }) {
return <div {...tagProps}><GatsbyImage {...props} /></div>
} |
@wardpeet can you elaborate on that? I don't know if there's been any internal discussion about v3 of This feature should be fine to keep as the attributes are contained in a prop and only intended for the top-level wrapping element since we prevent arbitrary props being passed down anyway. |
@wardpeet That's layering on another div, which has some disadvantages iirc due to CSS. On the related issue another user cited their own use case. EDIT: I just applied your suggestion of a wrapper: const Test = ({ className, tagProps, ...props }) => (
<div className={className} {...tagProps}><Img {...props} /></div>
)
// Previously used `Img` instead of `Test`
const GridCell = styled(Test)` And my images are wrongly sized now. The 2ndry div wrapper needs the inline styles that That could simply be avoided and be seamless for existing projects that want to add the a11y or any other attributes, without all the other hassle. |
I get that it seems like adding 1 extra prop doesn't seem like a big deal. But see it from our angle, another prop means 1 more codepath to support. It's a big project and these things add up. I'm happy to accept PRs that add features that can't be worked around. You can still fix your grid example by applying different css. a11Y isn't a concern here cause you can just apply these things on the container. Stay tuned for a gatsby-image to make these things easier and pluck the things you need. |
I am, as someone who contributes to
Fair, but this isn't doing much with that prop, it spreads them on the wrapper div, and any additional props on that wrapper div will override those attr props. If any issues were caused by it, it'd be pretty obvious and easy to verify due to the single prop to group all attributes, as opposed to the bad practice initially submitted in the PR.
I don't see that as a valid reason to decline the PR. It solves the issue this user and others have run into, and my simple example shows how your workaround isn't particularly pleasant and caused an unexpected breakage. Not only do I need to modify my own CSS(+abstraction through additional wrapper), I have to modify the internal Any project that wants to later add an attribute like a11y, needs to introduce such a workaround, due to
I ask again. Is this being worked on internally somewhere? I was willing to collaborate on the v3 component, but you're giving me the impression this is being done away from public and will just be revealed at some point...? |
Adding // Hacky workaround 'gatsby-image' wrapper not supporting attribute passthrough
// 'className' is for styled-components to correctly target due to splitting props
// 'style' alternatively if 'className' isn't needed(regular inline styles) for
// the top-level wrapper.
// 'null' on internal styles will erase the previous definitions via object spread
// May break if internal styles are updated..
// See: https://github.com/gatsbyjs/gatsby/pull/25283#issuecomment-653834820
// 'internalStyle' is the original 'style' prop, for the 'gatsby-image-wrapper' element
// in the event it's internal logic causes problems, which it might with 'fixed' images.
/* eslint-disable react/jsx-props-no-spreading */
const DoubleWrappedImg = ({ className, style, internalStyle, tagProps, ...props }) => (
<div
className={className}
style={{
position: "relative",
overflow: "hidden",
...style,
}}
{...tagProps}
>
<Img {...props} style={{ position: null, overflow: null, ...internalStyle }} />
</div>
)
/* eslint-enable react/jsx-props-no-spreading */
const GridCell = styled(DoubleWrappedImg) And then adding gatsby/packages/gatsby-image/src/index.js Lines 483 to 484 in b5926cc
Instead of being convenient with a rather simple and light maintenance PR solution, maintenance burden is raised but considered acceptable since it's shifted onto every user that will ever need such functionality, instead of them leveraging the collective(and far lighter) maintenance cost by having this merged in I don't imagine this type of need is too uncommon compared to some of the specially catered niche props supported by |
Another caveat is for handling this logic in gatsby/packages/gatsby-image/src/index.js Lines 594 to 596 in b5926cc
My snippet only accounted for
gatsby/packages/gatsby-image/src/index.js Lines 588 to 590 in b5926cc
I haven't tested if that'd cause any issues with the workaround, so passing another prop for the internal wrapper styles may be sufficient should it be an issue. I'll update the workaround snippet. |
Description
Allow
gatsby-image
to accept custom props. This is important for accessibility (i.e.aria-label
androle
attributes) along with some other use cases mentioned in #24876.Documentation
I'm not sure where the appropriate documentation changes would need to go. I assume a one-line
added to wherever is relevant will do.
@gatsbyjs/learning
Related Issues
Fixes #24876.