Skip to content

Commit

Permalink
Feature: placeholderClass prop for gatsby-image (#9187)
Browse files Browse the repository at this point in the history
Adds the ability to provide a class prop to the placeholder element in gatsby-image as described in #8916.
  • Loading branch information
baukevanderlaan authored and DSchau committed Oct 30, 2018
1 parent 49d4da1 commit 6cb7762
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 43 deletions.
33 changes: 17 additions & 16 deletions packages/gatsby-image/README.md
Expand Up @@ -261,22 +261,23 @@ prop. e.g. `<Img fluid={fluid} />`

## `gatsby-image` props

| Name | Type | Description |
| ------------------ | ------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `fixed` | `object` | Data returned from the `fixed` query |
| `fluid` | `object` | Data returned from the `fluid` query |
| `fadeIn` | `bool` | Defaults to fading in the image on load |
| `title` | `string` | Passed to the `img` element |
| `alt` | `string` | Passed to the `img` element |
| `className` | `string` / `object` | Passed to the wrapper element. Object is needed to support Glamor's css prop |
| `style` | `object` | Spread into the default styles of the wrapper element |
| `imgStyle` | `object` | Spread into the default styles of the actual `img` element |
| `placeholderStyle` | `object` | Spread into the default styles of the placeholder `img` element |
| `backgroundColor` | `string` / `bool` | Set a colored background placeholder. If true, uses "lightgray" for the color. You can also pass in any valid color string. |
| `onLoad` | `func` | A callback that is called when the full-size image has loaded. |
| `onError` | `func` | A callback that is called when the image fails to load. |
| `Tag` | `string` | Which HTML tag to use for wrapping elements. Defaults to `div`. |
| `critical` | `bool` | Opt-out of lazy-loading behavior. Defaults to `false`. |
| Name | Type | Description |
| -----------------------| ------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `fixed` | `object` | Data returned from the `fixed` query |
| `fluid` | `object` | Data returned from the `fluid` query |
| `fadeIn` | `bool` | Defaults to fading in the image on load |
| `title` | `string` | Passed to the `img` element |
| `alt` | `string` | Passed to the `img` element |
| `className` | `string` / `object` | Passed to the wrapper element. Object is needed to support Glamor's css prop |
| `style` | `object` | Spread into the default styles of the wrapper element |
| `imgStyle` | `object` | Spread into the default styles of the actual `img` element |
| `placeholderStyle` | `object` | Spread into the default styles of the placeholder `img` element |
| `placeholderClassName` | `string` | A class that is passed to the placeholder `img` element |
| `backgroundColor` | `string` / `bool` | Set a colored background placeholder. If true, uses "lightgray" for the color. You can also pass in any valid color string. |
| `onLoad` | `func` | A callback that is called when the full-size image has loaded. |
| `onError` | `func` | A callback that is called when the image fails to load. |
| `Tag` | `string` | Which HTML tag to use for wrapping elements. Defaults to `div`. |
| `critical` | `bool` | Opt-out of lazy-loading behavior. Defaults to `false`. |

## Image processing arguments

Expand Down
14 changes: 14 additions & 0 deletions packages/gatsby-image/src/__tests__/__snapshots__/index.js.snap
Expand Up @@ -6,6 +6,13 @@ exports[`<Img /> should render fixed size images 1`] = `
class="fixedImage gatsby-image-wrapper"
style="position: relative; overflow: hidden; display: inline; width: 100px; height: 100px;"
>
<img
alt=""
class="placeholder"
src="string_of_base64"
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; opacity: 0; color: red;"
title="Title for the image"
/>
<div
style="width: 100px; opacity: 0; height: 100px;"
title="Title for the image"
Expand Down Expand Up @@ -43,6 +50,13 @@ exports[`<Img /> should render fluid images 1`] = `
<div
style="width: 100%; padding-bottom: 66.66666666666667%;"
/>
<img
alt=""
class="placeholder"
src="string_of_base64"
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; opacity: 0; color: red;"
title="Title for the image"
/>
<div
style="position: absolute; top: 0px; bottom: 0px; opacity: 0; right: 0px; left: 0px;"
title="Title for the image"
Expand Down
16 changes: 14 additions & 2 deletions packages/gatsby-image/src/__tests__/index.js
Expand Up @@ -11,6 +11,7 @@ const fixedShapeMock = {
src: `test_image.jpg`,
srcSet: `some srcSet`,
srcSetWebp: `some srcSetWebp`,
base64: `string_of_base64`,
}

const fluidShapeMock = {
Expand All @@ -19,6 +20,7 @@ const fluidShapeMock = {
srcSet: `some srcSet`,
srcSetWebp: `some srcSetWebp`,
sizes: `(max-width: 600px) 100vw, 600px`,
base64: `string_of_base64`,
}

const setup = (fluid = false, onLoad = () => {}, onError = () => {}) => {
Expand All @@ -33,6 +35,8 @@ const setup = (fluid = false, onLoad = () => {}, onError = () => {}) => {
{...!fluid && { fixed: fixedShapeMock }}
onLoad={onLoad}
onError={onError}
placeholderStyle={{ color: `red` }}
placeholderClassName={`placeholder`}
/>
)

Expand All @@ -51,16 +55,24 @@ describe(`<Img />`, () => {
})

it(`should have correct src, title and alt attributes`, () => {
const imageTag = setup().querySelector(`img`)
const imageTag = setup().querySelector(`picture img`)
expect(imageTag.getAttribute(`src`)).toEqual(`test_image.jpg`)
expect(imageTag.getAttribute(`title`)).toEqual(`Title for the image`)
expect(imageTag.getAttribute(`alt`)).toEqual(`Alt text for the image`)
})

it(`should have correct placeholder src, title, style and class attributes`, () => {
const placeholderImageTag = setup().querySelector(`img`)
expect(placeholderImageTag.getAttribute(`src`)).toEqual(`string_of_base64`)
expect(placeholderImageTag.getAttribute(`title`)).toEqual(`Title for the image`)
expect(placeholderImageTag.getAttribute(`style`)).toEqual(`position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; opacity: 0; color: red;`)
expect(placeholderImageTag.getAttribute(`class`)).toEqual(`placeholder`)
})

it(`should call onLoad and onError image events`, () => {
const onLoadMock = jest.fn()
const onErrorMock = jest.fn()
const imageTag = setup(true, onLoadMock, onErrorMock).querySelector(`img`)
const imageTag = setup(true, onLoadMock, onErrorMock).querySelector(`picture img`)
fireEvent.load(imageTag)
fireEvent.error(imageTag)

Expand Down
39 changes: 14 additions & 25 deletions packages/gatsby-image/src/index.js
Expand Up @@ -198,6 +198,7 @@ class Image extends React.Component {
style = {},
imgStyle = {},
placeholderStyle = {},
placeholderClassName,
fluid,
fixed,
backgroundColor,
Expand All @@ -220,6 +221,13 @@ class Image extends React.Component {
...imgStyle,
}

const placeholderImageProps = {
title,
alt: !this.state.isVisible ? alt : ``,
style: imagePlaceholderStyle,
className: placeholderClassName,
}

if (fluid) {
const image = fluid

Expand All @@ -244,22 +252,12 @@ class Image extends React.Component {

{/* Show the blurry base64 image. */}
{image.base64 && (
<Img
alt={!this.state.isVisible ? alt : ``}
title={title}
src={image.base64}
style={imagePlaceholderStyle}
/>
)}
<Img src={image.base64} {...placeholderImageProps} />
)}

{/* Show the traced SVG image. */}
{image.tracedSVG && (
<Img
alt={!this.state.isVisible ? alt : ``}
title={title}
src={image.tracedSVG}
style={imagePlaceholderStyle}
/>
<Img src={image.tracedSVG} {...placeholderImageProps} />
)}

{/* Show a solid background color. */}
Expand Down Expand Up @@ -341,22 +339,12 @@ class Image extends React.Component {
>
{/* Show the blurry base64 image. */}
{image.base64 && (
<Img
alt={!this.state.isVisible ? alt : ``}
title={title}
src={image.base64}
style={imagePlaceholderStyle}
/>
<Img src={image.base64} {...placeholderImageProps} />
)}

{/* Show the traced SVG image. */}
{image.tracedSVG && (
<Img
alt={!this.state.isVisible ? alt : ``}
title={title}
src={image.tracedSVG}
style={imagePlaceholderStyle}
/>
<Img src={image.tracedSVG} {...placeholderImageProps} />
)}

{/* Show a solid background color. */}
Expand Down Expand Up @@ -465,6 +453,7 @@ Image.propTypes = {
style: PropTypes.object,
imgStyle: PropTypes.object,
placeholderStyle: PropTypes.object,
placeholderClassName: PropTypes.string,
backgroundColor: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
onLoad: PropTypes.func,
onError: PropTypes.func,
Expand Down

0 comments on commit 6cb7762

Please sign in to comment.