@comicrelief/component-library 8.53.2 → 8.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/components/Atoms/Picture/Picture.js +1 -0
  2. package/dist/components/Molecules/SingleMessage/SingleMessage.js +12 -3
  3. package/dist/components/Molecules/SingleMessage/SingleMessage.md +5 -32
  4. package/dist/components/Molecules/SingleMessage/SingleMessage.style.js +38 -39
  5. package/dist/components/Molecules/SingleMessage/__snapshots__/SingleMessage.test.js.snap +27 -43
  6. package/dist/components/Organisms/DynamicGallery/DynamicGallery.js +43 -24
  7. package/dist/components/Organisms/DynamicGallery/DynamicGallery.md +1 -1
  8. package/dist/components/Organisms/DynamicGallery/DynamicGallery.style.js +29 -16
  9. package/dist/components/Organisms/DynamicGallery/_DynamicGalleryColumn.js +8 -3
  10. package/dist/components/Organisms/DynamicGallery/_Lightbox.js +45 -24
  11. package/dist/components/Organisms/DynamicGallery/_Lightbox.style.js +7 -11
  12. package/dist/components/Organisms/DynamicGallery/__snapshots__/DynamicGallery.test.js.snap +254 -216
  13. package/package.json +1 -1
  14. package/playwright/components/organisms/dynamicGallery.spec.js +222 -1
  15. package/src/components/Atoms/Picture/Picture.js +1 -0
  16. package/src/components/Molecules/SingleMessage/SingleMessage.js +14 -3
  17. package/src/components/Molecules/SingleMessage/SingleMessage.md +5 -32
  18. package/src/components/Molecules/SingleMessage/SingleMessage.style.js +11 -12
  19. package/src/components/Molecules/SingleMessage/__snapshots__/SingleMessage.test.js.snap +27 -43
  20. package/src/components/Organisms/DynamicGallery/DynamicGallery.js +48 -25
  21. package/src/components/Organisms/DynamicGallery/DynamicGallery.md +1 -1
  22. package/src/components/Organisms/DynamicGallery/DynamicGallery.style.js +23 -1
  23. package/src/components/Organisms/DynamicGallery/_DynamicGalleryColumn.js +8 -3
  24. package/src/components/Organisms/DynamicGallery/_Lightbox.js +36 -19
  25. package/src/components/Organisms/DynamicGallery/_Lightbox.style.js +16 -29
  26. package/src/components/Organisms/DynamicGallery/__snapshots__/DynamicGallery.test.js.snap +254 -216
@@ -117,6 +117,7 @@ const Picture = _ref11 => {
117
117
  nonObjFitImage: nonObjFitImage,
118
118
  objFitState: objFitState
119
119
  }, rest), /*#__PURE__*/_react.default.createElement(Image, {
120
+ key: image,
120
121
  alt: alt,
121
122
  height: height,
122
123
  width: width,
@@ -30,12 +30,18 @@ const SingleMessage = _ref => {
30
30
  vhFull = false,
31
31
  videoID = null,
32
32
  landscapeVideo = false,
33
- paddingOption = null
33
+ paddingTop = '2rem',
34
+ paddingBottom = '2rem'
34
35
  } = _ref;
35
36
  const hasImage = imageSet || false;
36
37
  const doubleImage = (imageSet || image) && (imageSet2 || image2);
37
38
  const hasVideo = Boolean(videoID !== null && videoID !== '');
38
39
 
40
+ // While the Content Team don't use image or video Single Msgs any more, this just keeps
41
+ // things looking nice in the CL; only using the new props where they want 'em:
42
+ const thisPaddingTop = hasImage || hasVideo ? '0rem' : paddingTop;
43
+ const thisPaddingBottom = hasImage || hasVideo ? '0rem' : paddingBottom;
44
+
39
45
  // States to track video status
40
46
  const [isInitialised, setIsInitialised] = (0, _react.useState)(false);
41
47
  const [isPlaying, setIsPlaying] = (0, _react.useState)(false);
@@ -125,7 +131,9 @@ const SingleMessage = _ref => {
125
131
  hasVideo: hasVideo,
126
132
  landscapeVideo: landscapeVideo,
127
133
  fullImage: fullImage,
128
- ref: thisRef
134
+ ref: thisRef,
135
+ paddingTop: thisPaddingTop,
136
+ paddingBottom: thisPaddingBottom
129
137
  }, imageSet || imageSet2 ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_SingleMessage.Media, {
130
138
  doubleImage: doubleImage,
131
139
  isPlaying: isPlaying,
@@ -172,7 +180,8 @@ const SingleMessage = _ref => {
172
180
  copyFirst: copyFirst,
173
181
  hasVideo: hasVideo,
174
182
  vhFull: vhFull,
175
- paddingOption: paddingOption
183
+ paddingTop: paddingTop,
184
+ paddingBottom: paddingBottom
176
185
  }, children) : null))
177
186
  );
178
187
  };
@@ -71,7 +71,7 @@ import Link from '../../Atoms/Link/Link';
71
71
  />;
72
72
  ```
73
73
 
74
- Single Message with no Image
74
+ Single Message with no Image (default padding)
75
75
 
76
76
  ```js
77
77
  import Text from '../../Atoms/Text/Text';
@@ -84,12 +84,12 @@ import Text from '../../Atoms/Text/Text';
84
84
  </SingleMessage>;
85
85
  ```
86
86
 
87
- Single Message with no Image - padding unmodified
87
+ Single Message with no Image (no padding)
88
88
 
89
89
  ```js
90
90
  import Text from '../../Atoms/Text/Text';
91
91
 
92
- <SingleMessage backgroundColor="purple_dark" copyFirst={false} paddingOption="both_on">
92
+ <SingleMessage backgroundColor="purple_dark" copyFirst={false} paddingTop="0rem" paddingBottom="0rem">
93
93
  <Text tag="p" color="white" size="xxl">
94
94
  “The creativity that goes into helping people have a better life is
95
95
  extraordinary.”
@@ -97,39 +97,12 @@ import Text from '../../Atoms/Text/Text';
97
97
  </SingleMessage>;
98
98
  ```
99
99
 
100
- Single Message with no Image - no bottom padding
100
+ Single Message with no Image (big padding)
101
101
 
102
102
  ```js
103
103
  import Text from '../../Atoms/Text/Text';
104
104
 
105
- <SingleMessage backgroundColor="purple_dark" copyFirst={false} paddingOption="lower_off">
106
- <Text tag="p" color="white" size="xxl">
107
- “The creativity that goes into helping people have a better life is
108
- extraordinary.”
109
- </Text>
110
- </SingleMessage>;
111
- ```
112
-
113
-
114
- Single Message with no Image - no top padding
115
-
116
- ```js
117
- import Text from '../../Atoms/Text/Text';
118
-
119
- <SingleMessage backgroundColor="purple_dark" copyFirst={false} paddingOption="upper_off">
120
- <Text tag="p" color="white" size="xxl">
121
- “The creativity that goes into helping people have a better life is
122
- extraordinary.”
123
- </Text>
124
- </SingleMessage>;
125
- ```
126
-
127
- Single Message with no Image - no top and bottom padding
128
-
129
- ```js
130
- import Text from '../../Atoms/Text/Text';
131
-
132
- <SingleMessage backgroundColor="purple_dark" copyFirst={false} paddingOption="both_off">
105
+ <SingleMessage backgroundColor="purple_dark" copyFirst={false} paddingTop="4rem" paddingBottom="4rem">
133
106
  <Text tag="p" color="white" size="xxl">
134
107
  “The creativity that goes into helping people have a better life is
135
108
  extraordinary.”
@@ -13,11 +13,10 @@ var _zIndex = _interopRequireDefault(require("../../../theme/shared/zIndex"));
13
13
  var _videoPlayIcon = _interopRequireDefault(require("./assets/video--play-icon.svg"));
14
14
  var _videoPlayIcon__hover = _interopRequireDefault(require("./assets/video--play-icon__hover.svg"));
15
15
  var _loader = _interopRequireDefault(require("./assets/loader.svg"));
16
- var _utils = _interopRequireDefault(require("../../../utils/_utils"));
17
16
  const Container = exports.Container = _styledComponents.default.div.withConfig({
18
17
  displayName: "SingleMessagestyle__Container",
19
18
  componentId: "sc-86zg20-0"
20
- })(["display:flex;position:relative;flex-direction:column;overflow:hidden;background:", ";@media ", "{flex-direction:", ";", ";}iframe{height:100%;width:100%;position:absolute;top:0;", ";", ";}"], _ref => {
19
+ })(["display:flex;position:relative;flex-direction:column;overflow:hidden;background:", ";padding-top:", ";padding-bottom:", ";iframe{height:100%;width:100%;position:absolute;top:0;", ";", ";}@media ", "{flex-direction:", ";", ";}"], _ref => {
21
20
  let {
22
21
  theme,
23
22
  backgroundColor
@@ -25,84 +24,84 @@ const Container = exports.Container = _styledComponents.default.div.withConfig({
25
24
  return theme.color(backgroundColor);
26
25
  }, _ref2 => {
27
26
  let {
28
- theme
27
+ paddingTop
29
28
  } = _ref2;
30
- return theme.allBreakpoints('M');
29
+ return paddingTop;
31
30
  }, _ref3 => {
32
31
  let {
33
- copyFirst
32
+ paddingBottom
34
33
  } = _ref3;
35
- return copyFirst === true ? 'row-reverse' : 'row';
34
+ return paddingBottom;
36
35
  }, _ref4 => {
37
36
  let {
38
- landscapeVideo,
39
- hasVideo,
40
- fullImage
37
+ copyFirst
41
38
  } = _ref4;
42
- return landscapeVideo && hasVideo && !fullImage ? 'min-height: 0;' : null;
39
+ return copyFirst === true ? 'left: auto; right: 0;' : 'left: 0; right: auto;';
43
40
  }, _ref5 => {
44
41
  let {
45
- copyFirst
42
+ isPlaying
46
43
  } = _ref5;
47
- return copyFirst === true ? 'left: auto; right: 0;' : 'left: 0; right: auto;';
44
+ return isPlaying ? (0, _zIndex.default)('high') : (0, _zIndex.default)('base');
48
45
  }, _ref6 => {
49
46
  let {
50
- isPlaying
47
+ theme
51
48
  } = _ref6;
52
- return isPlaying ? (0, _zIndex.default)('high') : (0, _zIndex.default)('base');
49
+ return theme.allBreakpoints('M');
50
+ }, _ref7 => {
51
+ let {
52
+ copyFirst
53
+ } = _ref7;
54
+ return copyFirst === true ? 'row-reverse' : 'row';
55
+ }, _ref8 => {
56
+ let {
57
+ landscapeVideo,
58
+ hasVideo,
59
+ fullImage
60
+ } = _ref8;
61
+ return landscapeVideo && hasVideo && !fullImage ? 'min-height: 0;' : null;
53
62
  });
54
63
  const Copy = exports.Copy = _styledComponents.default.div.withConfig({
55
64
  displayName: "SingleMessagestyle__Copy",
56
65
  componentId: "sc-86zg20-1"
57
- })(["width:100%;", ";", ";padding:", ";@media ", "{", ";", ";flex-direction:column;justify-content:center;padding:", ";}", ";", ";@media ", "{", ";}"], (0, _zIndex.default)('low'), _ref7 => {
66
+ })(["width:100%;", ";", ";padding:0 ", ";@media ", "{", ";", ";flex-direction:column;justify-content:center;padding:0 ", ";}", ";", ";"], (0, _zIndex.default)('low'), _ref9 => {
58
67
  let {
59
68
  hasVideo,
60
69
  fullImage
61
- } = _ref7;
70
+ } = _ref9;
62
71
  return hasVideo === true && fullImage === true ? 'display: none;' : null;
63
- }, (0, _spacing.default)('l'), _ref8 => {
72
+ }, (0, _spacing.default)('l'), _ref10 => {
64
73
  let {
65
74
  theme
66
- } = _ref8;
75
+ } = _ref10;
67
76
  return theme.allBreakpoints('M');
68
- }, _ref9 => {
77
+ }, _ref11 => {
69
78
  let {
70
79
  vhFull,
71
80
  fullImage
72
- } = _ref9;
81
+ } = _ref11;
73
82
  return vhFull || fullImage ? 'min-height: calc(100vh - 5.625rem); flex-direction: column; justify-content: center;' : 'height: auto;';
74
- }, _ref10 => {
83
+ }, _ref12 => {
75
84
  let {
76
85
  hasVideo,
77
86
  fullImage
78
- } = _ref10;
79
- return hasVideo === true && fullImage === true ? 'display: none;' : 'display: flex;';
80
- }, (0, _spacing.default)('xl'), props => props.fullImage && (0, _styledComponents.css)(["@media ", "{position:absolute;width:100%;right:0;top:50%;transform:translateY(-50%);", " width:50%;}"], _ref11 => {
81
- let {
82
- theme
83
- } = _ref11;
84
- return theme.allBreakpoints('M');
85
- }, props.copyFirst ? (0, _styledComponents.css)(["left:0;"]) : null), props => props.hasImage ? (0, _styledComponents.css)(["@media ", "{width:50%;}"], _ref12 => {
86
- let {
87
- theme
88
87
  } = _ref12;
89
- return theme.allBreakpoints('M');
90
- }) : (0, _styledComponents.css)(["@media ", "{width:100%;max-width ", ";padding:", ";}margin:auto;padding:", ";"], _ref13 => {
88
+ return hasVideo === true && fullImage === true ? 'display: none;' : 'display: flex;';
89
+ }, (0, _spacing.default)('xl'), props => props.fullImage && (0, _styledComponents.css)(["@media ", "{position:absolute;width:100%;right:0;top:50%;transform:translateY(-50%);", " width:50%;}"], _ref13 => {
91
90
  let {
92
91
  theme
93
92
  } = _ref13;
94
93
  return theme.allBreakpoints('M');
95
- }, _containers.default.small, (0, _spacing.default)('xl'), (0, _spacing.default)('md')), _ref14 => {
94
+ }, props.copyFirst ? (0, _styledComponents.css)(["left:0;"]) : null), props => props.hasImage ? (0, _styledComponents.css)(["@media ", "{width:50%;}"], _ref14 => {
96
95
  let {
97
96
  theme
98
97
  } = _ref14;
99
- return theme.allBreakpoints('L');
100
- }, _ref15 => {
98
+ return theme.allBreakpoints('M');
99
+ }) : (0, _styledComponents.css)(["@media ", "{width:100%;max-width ", ";padding:0 ", ";}margin:auto;padding:", ";"], _ref15 => {
101
100
  let {
102
- paddingOption
101
+ theme
103
102
  } = _ref15;
104
- return (0, _utils.default)(paddingOption);
105
- });
103
+ return theme.allBreakpoints('M');
104
+ }, _containers.default.small, (0, _spacing.default)('xl'), (0, _spacing.default)('md')));
106
105
  const Media = exports.Media = _styledComponents.default.div.withConfig({
107
106
  displayName: "SingleMessagestyle__Media",
108
107
  componentId: "sc-86zg20-2"
@@ -49,6 +49,8 @@ exports[`renders Single Message with 100% vertical height image correctly 1`] =
49
49
  flex-direction: column;
50
50
  overflow: hidden;
51
51
  background: #6F3AAB;
52
+ padding-top: 0rem;
53
+ padding-bottom: 0rem;
52
54
  }
53
55
 
54
56
  .c0 iframe {
@@ -64,7 +66,7 @@ exports[`renders Single Message with 100% vertical height image correctly 1`] =
64
66
  .c5 {
65
67
  width: 100%;
66
68
  z-index: 1;
67
- padding: 2rem;
69
+ padding: 0 2rem;
68
70
  }
69
71
 
70
72
  .c1 {
@@ -122,7 +124,7 @@ exports[`renders Single Message with 100% vertical height image correctly 1`] =
122
124
  -webkit-justify-content: center;
123
125
  -ms-flex-pack: center;
124
126
  justify-content: center;
125
- padding: 4rem;
127
+ padding: 0 4rem;
126
128
  }
127
129
  }
128
130
 
@@ -132,10 +134,6 @@ exports[`renders Single Message with 100% vertical height image correctly 1`] =
132
134
  }
133
135
  }
134
136
 
135
- @media (min-width:1024px) {
136
-
137
- }
138
-
139
137
  @media (min-width:740px) {
140
138
  .c1 {
141
139
  height: auto;
@@ -319,6 +317,8 @@ exports[`renders Single Message with Image correctly 1`] = `
319
317
  flex-direction: column;
320
318
  overflow: hidden;
321
319
  background: #6F3AAB;
320
+ padding-top: 0rem;
321
+ padding-bottom: 0rem;
322
322
  }
323
323
 
324
324
  .c0 iframe {
@@ -334,7 +334,7 @@ exports[`renders Single Message with Image correctly 1`] = `
334
334
  .c5 {
335
335
  width: 100%;
336
336
  z-index: 1;
337
- padding: 2rem;
337
+ padding: 0 2rem;
338
338
  }
339
339
 
340
340
  .c1 {
@@ -425,7 +425,7 @@ exports[`renders Single Message with Image correctly 1`] = `
425
425
  -webkit-justify-content: center;
426
426
  -ms-flex-pack: center;
427
427
  justify-content: center;
428
- padding: 4rem;
428
+ padding: 0 4rem;
429
429
  }
430
430
  }
431
431
 
@@ -435,10 +435,6 @@ exports[`renders Single Message with Image correctly 1`] = `
435
435
  }
436
436
  }
437
437
 
438
- @media (min-width:1024px) {
439
-
440
- }
441
-
442
438
  @media (min-width:740px) {
443
439
  .c1 {
444
440
  height: auto;
@@ -561,6 +557,8 @@ exports[`renders Single Message with double image correctly 1`] = `
561
557
  flex-direction: column;
562
558
  overflow: hidden;
563
559
  background: #FFE400;
560
+ padding-top: 0rem;
561
+ padding-bottom: 0rem;
564
562
  }
565
563
 
566
564
  .c0 iframe {
@@ -576,7 +574,7 @@ exports[`renders Single Message with double image correctly 1`] = `
576
574
  .c5 {
577
575
  width: 100%;
578
576
  z-index: 1;
579
- padding: 2rem;
577
+ padding: 0 2rem;
580
578
  }
581
579
 
582
580
  .c1 {
@@ -639,7 +637,7 @@ exports[`renders Single Message with double image correctly 1`] = `
639
637
  -webkit-justify-content: center;
640
638
  -ms-flex-pack: center;
641
639
  justify-content: center;
642
- padding: 4rem;
640
+ padding: 0 4rem;
643
641
  }
644
642
  }
645
643
 
@@ -649,10 +647,6 @@ exports[`renders Single Message with double image correctly 1`] = `
649
647
  }
650
648
  }
651
649
 
652
- @media (min-width:1024px) {
653
-
654
- }
655
-
656
650
  @media (min-width:740px) {
657
651
 
658
652
  }
@@ -661,10 +655,6 @@ exports[`renders Single Message with double image correctly 1`] = `
661
655
 
662
656
  }
663
657
 
664
- @media (min-width:1024px) {
665
-
666
- }
667
-
668
658
  @media (min-width:740px) {
669
659
  .c1 {
670
660
  height: auto;
@@ -880,6 +870,8 @@ exports[`renders Single Message with full width correctly 1`] = `
880
870
  flex-direction: column;
881
871
  overflow: hidden;
882
872
  background: #6F3AAB;
873
+ padding-top: 0rem;
874
+ padding-bottom: 0rem;
883
875
  }
884
876
 
885
877
  .c0 iframe {
@@ -895,7 +887,7 @@ exports[`renders Single Message with full width correctly 1`] = `
895
887
  .c5 {
896
888
  width: 100%;
897
889
  z-index: 1;
898
- padding: 2rem;
890
+ padding: 0 2rem;
899
891
  }
900
892
 
901
893
  .c1 {
@@ -993,7 +985,7 @@ exports[`renders Single Message with full width correctly 1`] = `
993
985
  -webkit-justify-content: center;
994
986
  -ms-flex-pack: center;
995
987
  justify-content: center;
996
- padding: 4rem;
988
+ padding: 0 4rem;
997
989
  }
998
990
  }
999
991
 
@@ -1016,10 +1008,6 @@ exports[`renders Single Message with full width correctly 1`] = `
1016
1008
  }
1017
1009
  }
1018
1010
 
1019
- @media (min-width:1024px) {
1020
-
1021
- }
1022
-
1023
1011
  @media (min-width:740px) {
1024
1012
  .c1 {
1025
1013
  height: auto;
@@ -1122,6 +1110,8 @@ exports[`renders Single Message with full width image and no text correctly 1`]
1122
1110
  flex-direction: column;
1123
1111
  overflow: hidden;
1124
1112
  background: #6F3AAB;
1113
+ padding-top: 0rem;
1114
+ padding-bottom: 0rem;
1125
1115
  }
1126
1116
 
1127
1117
  .c0 iframe {
@@ -1182,10 +1172,6 @@ exports[`renders Single Message with full width image and no text correctly 1`]
1182
1172
 
1183
1173
  }
1184
1174
 
1185
- @media (min-width:1024px) {
1186
-
1187
- }
1188
-
1189
1175
  @media (min-width:740px) {
1190
1176
  .c1 {
1191
1177
  height: auto;
@@ -1274,6 +1260,8 @@ exports[`renders Single Message with no Image correctly 1`] = `
1274
1260
  flex-direction: column;
1275
1261
  overflow: hidden;
1276
1262
  background: #6F3AAB;
1263
+ padding-top: 2rem;
1264
+ padding-bottom: 2rem;
1277
1265
  }
1278
1266
 
1279
1267
  .c0 iframe {
@@ -1289,7 +1277,7 @@ exports[`renders Single Message with no Image correctly 1`] = `
1289
1277
  .c1 {
1290
1278
  width: 100%;
1291
1279
  z-index: 1;
1292
- padding: 2rem;
1280
+ padding: 0 2rem;
1293
1281
  margin: auto;
1294
1282
  padding: 1rem;
1295
1283
  }
@@ -1332,6 +1320,10 @@ exports[`renders Single Message with no Image correctly 1`] = `
1332
1320
  }
1333
1321
  }
1334
1322
 
1323
+ @media (min-width:740px) {
1324
+
1325
+ }
1326
+
1335
1327
  @media (min-width:740px) {
1336
1328
  .c1 {
1337
1329
  height: auto;
@@ -1346,7 +1338,7 @@ exports[`renders Single Message with no Image correctly 1`] = `
1346
1338
  -webkit-justify-content: center;
1347
1339
  -ms-flex-pack: center;
1348
1340
  justify-content: center;
1349
- padding: 4rem;
1341
+ padding: 0 4rem;
1350
1342
  }
1351
1343
  }
1352
1344
 
@@ -1354,14 +1346,10 @@ exports[`renders Single Message with no Image correctly 1`] = `
1354
1346
  .c1 {
1355
1347
  width: 100%;
1356
1348
  max-width: 880px;
1357
- padding: 4rem;
1349
+ padding: 0 4rem;
1358
1350
  }
1359
1351
  }
1360
1352
 
1361
- @media (min-width:1024px) {
1362
-
1363
- }
1364
-
1365
1353
  @media (min-width:740px) {
1366
1354
 
1367
1355
  }
@@ -1370,10 +1358,6 @@ exports[`renders Single Message with no Image correctly 1`] = `
1370
1358
 
1371
1359
  }
1372
1360
 
1373
- @media (min-width:1024px) {
1374
-
1375
- }
1376
-
1377
1361
  @media (min-width:740px) {
1378
1362
 
1379
1363
  }
@@ -61,7 +61,7 @@ const DynamicGallery = _ref => {
61
61
  return (0, _floor2.default)(top, -2) + Math.floor(left) / 1000;
62
62
  }, 'asc');
63
63
  sortedNodes.forEach((galleryNode, index) => {
64
- galleryNode.setAttribute('data-order', String(index));
64
+ galleryNode.setAttribute('data-tab-order', String(index));
65
65
  });
66
66
  }
67
67
  // create a throttled version of the updateTabOrder function
@@ -105,16 +105,30 @@ const DynamicGallery = _ref => {
105
105
  const [selectedNode, setSelectedNode] = (0, _react.useState)(null);
106
106
  const [focusedNode, setFocusedNode] = (0, _react.useState)(null);
107
107
 
108
- // handle next/previous node events from the lightbox
108
+ // handle next/previous node events from the lightbox;
109
+ // slightly complicated because we need to use the data-tab-order attribute
110
+ // to navigate between nodes rather than the node index;
111
+ // this reflects the tab ordering in the DOM, rather than the order of the nodes in the array,
112
+ // because the dynamic image heights can confuse the normal order
109
113
  function handleNextNode(node) {
110
114
  const nodeIndex = nodes.indexOf(node);
111
- const nextNodeIndex = (nodeIndex + 1) % imageCount;
112
- setSelectedNode(nodes[nextNodeIndex]);
115
+ const nodeEl = containerRef.current.querySelector(`[data-node-index="${nodeIndex}"]`);
116
+ const tabOrder = nodeEl.getAttribute('data-tab-order');
117
+ const nextTabOrder = (+tabOrder + 1) % imageCount;
118
+ const nextNodeEl = containerRef.current.querySelector(`[data-tab-order="${nextTabOrder}"]`);
119
+ const nextNodeIndex = nextNodeEl.getAttribute('data-node-index');
120
+ const nextNode = nodes[nextNodeIndex];
121
+ setSelectedNode(nextNode);
113
122
  }
114
123
  function handlePreviousNode(node) {
115
124
  const nodeIndex = nodes.indexOf(node);
116
- const previousNodeIndex = (nodeIndex - 1 + imageCount) % imageCount;
117
- setSelectedNode(nodes[previousNodeIndex]);
125
+ const nodeEl = containerRef.current.querySelector(`[data-node-index="${nodeIndex}"]`);
126
+ const tabOrder = nodeEl.getAttribute('data-tab-order');
127
+ const previousTabOrder = (+tabOrder - 1 + imageCount) % imageCount;
128
+ const previousNodeEl = containerRef.current.querySelector(`[data-tab-order="${previousTabOrder}"]`);
129
+ const previousNodeIndex = previousNodeEl.getAttribute('data-node-index');
130
+ const previousNode = nodes[previousNodeIndex];
131
+ setSelectedNode(previousNode);
118
132
  }
119
133
 
120
134
  // handle keydown events,
@@ -146,7 +160,7 @@ const DynamicGallery = _ref => {
146
160
  // - columns + custom tabbing > what we're doing here
147
161
  case 'Tab':
148
162
  {
149
- const nodeIndex = +event.target.dataset.order;
163
+ const nodeIndex = +event.target.dataset.tabOrder;
150
164
  if (Number.isNaN(nodeIndex)) return;
151
165
  const galleryContainer = event.target.closest('.gallery-container');
152
166
  if (!galleryContainer) return;
@@ -156,7 +170,7 @@ const DynamicGallery = _ref => {
156
170
  newNodeIndex = nodeIndex - 1;
157
171
  if (newNodeIndex < 0) return;
158
172
  event.preventDefault();
159
- galleryContainer.querySelector(`[data-order="${newNodeIndex}"]`).focus();
173
+ galleryContainer.querySelector(`[data-tab-order="${newNodeIndex}"]`).focus();
160
174
  } else {
161
175
  // tab: move to the next image
162
176
  newNodeIndex = nodeIndex + 1;
@@ -171,7 +185,7 @@ const DynamicGallery = _ref => {
171
185
  return;
172
186
  }
173
187
  event.preventDefault();
174
- galleryContainer.querySelector(`[data-order="${newNodeIndex}"]`).focus();
188
+ galleryContainer.querySelector(`[data-tab-order="${newNodeIndex}"]`).focus();
175
189
  }
176
190
  break;
177
191
  }
@@ -200,24 +214,29 @@ const DynamicGallery = _ref => {
200
214
  }, /*#__PURE__*/_react.default.createElement(_DynamicGallery.ImageGrid, {
201
215
  className: "gallery-grid",
202
216
  onKeyDown: event => handleKeyDown(event)
203
- }, hasNodes && Array(columnCount).fill(null).map((column, columnIndex) => /*#__PURE__*/_react.default.createElement(_DynamicGalleryColumn.default
204
- // disabling the lint rule here
205
- // as we're chunking an array and have no unique keys
206
- // eslint-disable-next-line react/no-array-index-key
207
- , {
208
- key: columnIndex,
209
- columnIndex: columnIndex,
210
- columnCount: columnCount,
211
- nodes: nodes.slice(0, imageCount),
212
- imageRatio: imageRatio,
213
- updateTabOrder: throttledUpdateTabOrder.current,
214
- focusOutlineColour: textColour
215
- })), /*#__PURE__*/_react.default.createElement(_DynamicGallery.EmptyMessage, {
217
+ }, hasNodes && Array(columnCount).fill(null).map((column, columnIndex) => {
218
+ // eslint prefers template literals for strings, but they break the compiler
219
+ // eslint-disable-next-line prefer-template
220
+ const key = String(columnIndex) + ':' + nodes.length;
221
+ return /*#__PURE__*/_react.default.createElement(_DynamicGalleryColumn.default
222
+ // disabling the lint rule here
223
+ // as we're chunking an array and have no unique keys
224
+ // eslint-disable-next-line react/no-array-index-key
225
+ , {
226
+ key: key,
227
+ columnIndex: columnIndex,
228
+ columnCount: columnCount,
229
+ nodes: nodes.slice(0, imageCount),
230
+ imageRatio: imageRatio,
231
+ updateTabOrder: throttledUpdateTabOrder.current,
232
+ focusOutlineColour: textColour
233
+ });
234
+ }), /*#__PURE__*/_react.default.createElement(_DynamicGallery.EmptyMessage, {
216
235
  isEmpty: !hasNodes
217
- }, "No images to display")), /*#__PURE__*/_react.default.createElement(_Lightbox.default, null), /*#__PURE__*/_react.default.createElement("div", {
236
+ }, "No images to display")), /*#__PURE__*/_react.default.createElement(_Lightbox.default, null), /*#__PURE__*/_react.default.createElement(_DynamicGallery.FocusTrap, {
218
237
  className: "gallery-focus-trap",
219
238
  tabIndex: 0
220
- })), imageCount < nodes.length && /*#__PURE__*/_react.default.createElement(_Button.default, {
239
+ }, /*#__PURE__*/_react.default.createElement("span", null, "End of gallery"))), imageCount < nodes.length && /*#__PURE__*/_react.default.createElement(_Button.default, {
221
240
  onClick: () => handleLoadMore()
222
241
  }, "Show more"));
223
242
  };
@@ -18,7 +18,7 @@ import createMockGalleryNodes from './_utils';
18
18
  ```js
19
19
  const defaultData = require('../../../styleguide/data/data').defaultData;
20
20
  import createMockGalleryNodes from './_utils';
21
- <DynamicGallery gridWidth={4} nodes={createMockGalleryNodes(4)} loadingBehaviour="all" imageRatio="4:3" pageBackgroundColour="blue" textColour="white" paddingTop="6rem" paddingBottom="6rem" useLightbox={false} />;
21
+ <DynamicGallery gridWidth={4} nodes={createMockGalleryNodes(30)} loadingBehaviour="all" imageRatio="4:3" pageBackgroundColour="blue" textColour="white" paddingTop="6rem" paddingBottom="6rem" useLightbox={false} />;
22
22
  ```
23
23
 
24
24
  ### Gallery with max 5 columns