Skip to content

Commit 6f46aac

Browse files
frinyvonnicksidharthachatterjee
authored andcommitted
feat(gatsby-image): Add durationFadeIn (#13566)
1 parent 369f54e commit 6f46aac

4 files changed

Lines changed: 67 additions & 12 deletions

File tree

packages/gatsby-image/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ You will need to add it in your graphql query as is shown in the following snipp
338338
| `fixed` | `object` | Data returned from the `fixed` query |
339339
| `fluid` | `object` | Data returned from the `fluid` query |
340340
| `fadeIn` | `bool` | Defaults to fading in the image on load |
341+
| `durationFadeIn` | `number` | fading duration is set up to 500ms by default |
341342
| `title` | `string` | Passed to the `img` element |
342343
| `alt` | `string` | Passed to the `img` element |
343344
| `crossOrigin` | `string` | Passed to the `img` element |

packages/gatsby-image/src/__tests__/__snapshots__/index.js.snap

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,61 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`<Image /> should have a transition-delay of 1sec 1`] = `
4+
<div>
5+
<div
6+
class="fixedImage gatsby-image-wrapper"
7+
style="position: relative; overflow: hidden; display: inline; width: 100px; height: 100px;"
8+
>
9+
<div
10+
style="background-color: lightgray; width: 100px; opacity: 1; height: 100px; transition-delay: 1000ms;"
11+
title="Title for the image"
12+
/>
13+
<img
14+
alt=""
15+
class="placeholder"
16+
src="string_of_base64"
17+
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 1; transition-delay: 1000ms; color: red;"
18+
title="Title for the image"
19+
/>
20+
<picture>
21+
<source
22+
srcset="some srcSetWebp"
23+
type="image/webp"
24+
/>
25+
<img
26+
alt="Alt text for the image"
27+
crossorigin="anonymous"
28+
height="100"
29+
itemprop="item-prop-for-the-image"
30+
src="test_image.jpg"
31+
srcset="some srcSet"
32+
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 0; transition: opacity 1000ms;"
33+
title="Title for the image"
34+
width="100"
35+
/>
36+
</picture>
37+
<noscript>
38+
&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;
39+
</noscript>
40+
</div>
41+
</div>
42+
`;
43+
344
exports[`<Image /> should render fixed size images 1`] = `
445
<div>
546
<div
647
class="fixedImage gatsby-image-wrapper"
748
style="position: relative; overflow: hidden; display: inline; width: 100px; height: 100px;"
849
>
950
<div
10-
style="background-color: lightgray; width: 100px; opacity: 1; height: 100px; transition-delay: 0.5s;"
51+
style="background-color: lightgray; width: 100px; opacity: 1; height: 100px; transition-delay: 500ms;"
1152
title="Title for the image"
1253
/>
1354
<img
1455
alt=""
1556
class="placeholder"
1657
src="string_of_base64"
17-
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;"
58+
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 1; transition-delay: 500ms; color: red;"
1859
title="Title for the image"
1960
/>
2061
<picture>
@@ -29,7 +70,7 @@ exports[`<Image /> should render fixed size images 1`] = `
2970
itemprop="item-prop-for-the-image"
3071
src="test_image.jpg"
3172
srcset="some srcSet"
32-
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 0; transition: opacity 0.5s;"
73+
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 0; transition: opacity 500ms;"
3374
title="Title for the image"
3475
width="100"
3576
/>
@@ -51,14 +92,14 @@ exports[`<Image /> should render fluid images 1`] = `
5192
style="width: 100%; padding-bottom: 66.66666666666667%;"
5293
/>
5394
<div
54-
style="background-color: lightgray; position: absolute; top: 0px; bottom: 0px; opacity: 1; right: 0px; left: 0px; transition-delay: 0.5s;"
95+
style="background-color: lightgray; position: absolute; top: 0px; bottom: 0px; opacity: 1; right: 0px; left: 0px; transition-delay: 500ms;"
5596
title="Title for the image"
5697
/>
5798
<img
5899
alt=""
59100
class="placeholder"
60101
src="string_of_base64"
61-
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;"
102+
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 1; transition-delay: 500ms; color: red;"
62103
title="Title for the image"
63104
/>
64105
<picture>
@@ -74,7 +115,7 @@ exports[`<Image /> should render fluid images 1`] = `
74115
sizes="(max-width: 600px) 100vw, 600px"
75116
src="test_image.jpg"
76117
srcset="some srcSet"
77-
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 0; transition: opacity 0.5s;"
118+
style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 0; transition: opacity 500ms;"
78119
title="Title for the image"
79120
/>
80121
</picture>

packages/gatsby-image/src/__tests__/index.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@ const fluidShapeMock = {
2323
base64: `string_of_base64`,
2424
}
2525

26-
const setup = (fluid = false, onLoad = () => {}, onError = () => {}) => {
26+
const setup = (
27+
fluid = false,
28+
props = {},
29+
onLoad = () => {},
30+
onError = () => {}
31+
) => {
2732
const { container } = render(
2833
<Image
2934
backgroundColor
@@ -39,6 +44,7 @@ const setup = (fluid = false, onLoad = () => {}, onError = () => {}) => {
3944
itemProp={`item-prop-for-the-image`}
4045
placeholderStyle={{ color: `red` }}
4146
placeholderClassName={`placeholder`}
47+
{...props}
4248
/>
4349
)
4450

@@ -73,15 +79,20 @@ describe(`<Image />`, () => {
7379
)
7480
// No Intersection Observer in JSDOM, so placeholder img will be visible (opacity 1) by default
7581
expect(placeholderImageTag.getAttribute(`style`)).toEqual(
76-
`position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 1; transition-delay: 0.5s; color: red;`
82+
`position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center; opacity: 1; transition-delay: 500ms; color: red;`
7783
)
7884
expect(placeholderImageTag.getAttribute(`class`)).toEqual(`placeholder`)
7985
})
8086

87+
it(`should have a transition-delay of 1sec`, () => {
88+
const component = setup(false, { durationFadeIn: `1000` })
89+
expect(component).toMatchSnapshot()
90+
})
91+
8192
it(`should call onLoad and onError image events`, () => {
8293
const onLoadMock = jest.fn()
8394
const onErrorMock = jest.fn()
84-
const imageTag = setup(true, onLoadMock, onErrorMock).querySelector(
95+
const imageTag = setup(true, {}, onLoadMock, onErrorMock).querySelector(
8596
`picture img`
8697
)
8798
fireEvent.load(imageTag)

packages/gatsby-image/src/index.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,25 +256,25 @@ class Image extends React.Component {
256256
fluid,
257257
fixed,
258258
backgroundColor,
259+
durationFadeIn,
259260
Tag,
260261
itemProp,
261262
} = convertProps(this.props)
262263

263264
const shouldReveal = this.state.imgLoaded || this.state.fadeIn === false
264265
const shouldFadeIn = this.state.fadeIn === true && !this.state.imgCached
265-
const durationFadeIn = `0.5s`
266266

267267
const imageStyle = {
268268
opacity: shouldReveal ? 1 : 0,
269-
transition: shouldFadeIn ? `opacity ${durationFadeIn}` : `none`,
269+
transition: shouldFadeIn ? `opacity ${durationFadeIn}ms` : `none`,
270270
...imgStyle,
271271
}
272272

273273
const bgColor =
274274
typeof backgroundColor === `boolean` ? `lightgray` : backgroundColor
275275

276276
const delayHideStyle = {
277-
transitionDelay: durationFadeIn,
277+
transitionDelay: `${durationFadeIn}ms`,
278278
}
279279

280280
const imagePlaceholderStyle = {
@@ -477,6 +477,7 @@ class Image extends React.Component {
477477
Image.defaultProps = {
478478
critical: false,
479479
fadeIn: true,
480+
durationFadeIn: 500,
480481
alt: ``,
481482
Tag: `div`,
482483
}
@@ -509,6 +510,7 @@ Image.propTypes = {
509510
fixed: fixedObject,
510511
fluid: fluidObject,
511512
fadeIn: PropTypes.bool,
513+
durationFadeIn: PropTypes.number,
512514
title: PropTypes.string,
513515
alt: PropTypes.string,
514516
className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), // Support Glamor's css prop.

0 commit comments

Comments
 (0)