Skip to content
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 durationFadeIn #13566

Merged
merged 5 commits into from
Apr 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/gatsby-image/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ You will need to add it in your graphql query as is shown in the following snipp
| `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 |
| `durationFadeIn` | `number` | fading duration is set up to 500ms by default |
| `title` | `string` | Passed to the `img` element |
| `alt` | `string` | Passed to the `img` element |
| `crossOrigin` | `string` | Passed to the `img` element |
Expand Down
53 changes: 47 additions & 6 deletions packages/gatsby-image/src/__tests__/__snapshots__/index.js.snap
Original file line number Diff line number Diff line change
@@ -1,20 +1,61 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<Image /> should have a transition-delay of 1sec 1`] = `
<div>
<div
class="fixedImage gatsby-image-wrapper"
style="position: relative; overflow: hidden; display: inline; width: 100px; height: 100px;"
>
<div
style="background-color: lightgray; width: 100px; opacity: 1; height: 100px; transition-delay: 1000ms;"
title="Title for the image"
/>
<img
alt=""
class="placeholder"
src="string_of_base64"
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 1; transition-delay: 1000ms; color: red;"
title="Title for the image"
/>
<picture>
<source
srcset="some srcSetWebp"
type="image/webp"
/>
<img
alt="Alt text for the image"
crossorigin="anonymous"
height="100"
itemprop="item-prop-for-the-image"
src="test_image.jpg"
srcset="some srcSet"
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 0; transition: opacity 1000ms;"
title="Title for the image"
width="100"
/>
</picture>
<noscript>
&lt;picture&gt;&lt;source type='image/webp' srcset="some srcSetWebp" /&gt;&lt;img width="100" height="100" srcset="some srcSet" src="test_image.jpg" alt="Alt text for the image" title="Title for the image" style="position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center"/&gt;&lt;/picture&gt;
</noscript>
</div>
</div>
`;

exports[`<Image /> should render fixed size images 1`] = `
<div>
<div
class="fixedImage gatsby-image-wrapper"
style="position: relative; overflow: hidden; display: inline; width: 100px; height: 100px;"
>
<div
style="background-color: lightgray; width: 100px; opacity: 1; height: 100px; transition-delay: 0.5s;"
style="background-color: lightgray; width: 100px; opacity: 1; height: 100px; transition-delay: 500ms;"
title="Title for the image"
/>
<img
alt=""
class="placeholder"
src="string_of_base64"
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 1; transition-delay: 0.5s; color: red;"
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 1; transition-delay: 500ms; color: red;"
title="Title for the image"
/>
<picture>
Expand All @@ -29,7 +70,7 @@ exports[`<Image /> should render fixed size images 1`] = `
itemprop="item-prop-for-the-image"
src="test_image.jpg"
srcset="some srcSet"
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 0; transition: opacity 0.5s;"
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 0; transition: opacity 500ms;"
title="Title for the image"
width="100"
/>
Expand All @@ -51,14 +92,14 @@ exports[`<Image /> should render fluid images 1`] = `
style="width: 100%; padding-bottom: 66.66666666666667%;"
/>
<div
style="background-color: lightgray; position: absolute; top: 0px; bottom: 0px; opacity: 1; right: 0px; left: 0px; transition-delay: 0.5s;"
style="background-color: lightgray; position: absolute; top: 0px; bottom: 0px; opacity: 1; right: 0px; left: 0px; transition-delay: 500ms;"
title="Title for the image"
/>
<img
alt=""
class="placeholder"
src="string_of_base64"
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 1; transition-delay: 0.5s; color: red;"
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 1; transition-delay: 500ms; color: red;"
title="Title for the image"
/>
<picture>
Expand All @@ -74,7 +115,7 @@ exports[`<Image /> should render fluid images 1`] = `
sizes="(max-width: 600px) 100vw, 600px"
src="test_image.jpg"
srcset="some srcSet"
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 0; transition: opacity 0.5s;"
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 0; transition: opacity 500ms;"
title="Title for the image"
/>
</picture>
Expand Down
17 changes: 14 additions & 3 deletions packages/gatsby-image/src/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ const fluidShapeMock = {
base64: `string_of_base64`,
}

const setup = (fluid = false, onLoad = () => {}, onError = () => {}) => {
const setup = (
fluid = false,
props = {},
onLoad = () => {},
onError = () => {}
) => {
const { container } = render(
<Image
backgroundColor
Expand All @@ -39,6 +44,7 @@ const setup = (fluid = false, onLoad = () => {}, onError = () => {}) => {
itemProp={`item-prop-for-the-image`}
placeholderStyle={{ color: `red` }}
placeholderClassName={`placeholder`}
{...props}
/>
)

Expand Down Expand Up @@ -73,15 +79,20 @@ describe(`<Image />`, () => {
)
// No Intersection Observer in JSDOM, so placeholder img will be visible (opacity 1) by default
expect(placeholderImageTag.getAttribute(`style`)).toEqual(
`position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 1; transition-delay: 0.5s; color: red;`
`position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 1; transition-delay: 500ms; color: red;`
frinyvonnick marked this conversation as resolved.
Show resolved Hide resolved
)
expect(placeholderImageTag.getAttribute(`class`)).toEqual(`placeholder`)
})

it(`should have a transition-delay of 1sec`, () => {
const component = setup(false, { durationFadeIn: `1000` })
expect(component).toMatchSnapshot()
})

it(`should call onLoad and onError image events`, () => {
const onLoadMock = jest.fn()
const onErrorMock = jest.fn()
const imageTag = setup(true, onLoadMock, onErrorMock).querySelector(
const imageTag = setup(true, {}, onLoadMock, onErrorMock).querySelector(
`picture img`
)
fireEvent.load(imageTag)
Expand Down
8 changes: 5 additions & 3 deletions packages/gatsby-image/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,25 +256,25 @@ class Image extends React.Component {
fluid,
fixed,
backgroundColor,
durationFadeIn,
Tag,
itemProp,
} = convertProps(this.props)

const shouldReveal = this.state.imgLoaded || this.state.fadeIn === false
const shouldFadeIn = this.state.fadeIn === true && !this.state.imgCached
const durationFadeIn = `0.5s`

const imageStyle = {
opacity: shouldReveal ? 1 : 0,
transition: shouldFadeIn ? `opacity ${durationFadeIn}` : `none`,
transition: shouldFadeIn ? `opacity ${durationFadeIn}ms` : `none`,
...imgStyle,
}

const bgColor =
typeof backgroundColor === `boolean` ? `lightgray` : backgroundColor

const delayHideStyle = {
transitionDelay: durationFadeIn,
transitionDelay: `${durationFadeIn}ms`,
}

const imagePlaceholderStyle = {
Expand Down Expand Up @@ -477,6 +477,7 @@ class Image extends React.Component {
Image.defaultProps = {
critical: false,
fadeIn: true,
durationFadeIn: 500,
alt: ``,
Tag: `div`,
}
Expand Down Expand Up @@ -509,6 +510,7 @@ Image.propTypes = {
fixed: fixedObject,
fluid: fluidObject,
fadeIn: PropTypes.bool,
durationFadeIn: PropTypes.number,
frinyvonnick marked this conversation as resolved.
Show resolved Hide resolved
title: PropTypes.string,
alt: PropTypes.string,
className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), // Support Glamor's css prop.
Expand Down