@comicrelief/component-library 8.51.4 → 8.51.5
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.
- package/dist/components/Molecules/CTA/CTAMultiCard/CTAMultiCard.js +11 -6
- package/dist/components/Molecules/CTA/CTAMultiCard/CTAMultiCard.md +4 -4
- package/dist/components/Molecules/CTA/CTAMultiCard/CTAMultiCard.style.js +41 -22
- package/dist/components/Molecules/CTA/CTAMultiCard/CTAMultiCard.test.js +0 -1
- package/dist/components/Molecules/CTA/CTAMultiCard/__snapshots__/CTAMultiCard.test.js.snap +996 -2653
- package/dist/components/Molecules/CTA/CTASingleCard/CTASingleCard.js +9 -4
- package/dist/components/Molecules/CTA/CTASingleCard/CTASingleCard.md +10 -10
- package/dist/components/Molecules/CTA/CTASingleCard/CTASingleCard.style.js +16 -6
- package/dist/components/Molecules/CTA/CTASingleCard/CTASingleCard.test.js +2 -0
- package/dist/components/Molecules/CTA/CTASingleCard/__snapshots__/CTASingleCard.test.js.snap +245 -233
- package/dist/components/Molecules/CTA/shared/CTACard.js +11 -8
- package/dist/components/Molecules/CTA/shared/CTACard.style.js +101 -73
- package/package.json +1 -1
- package/src/components/Molecules/CTA/CTAMultiCard/CTAMultiCard.js +48 -41
- package/src/components/Molecules/CTA/CTAMultiCard/CTAMultiCard.md +4 -4
- package/src/components/Molecules/CTA/CTAMultiCard/CTAMultiCard.style.js +34 -9
- package/src/components/Molecules/CTA/CTAMultiCard/CTAMultiCard.test.js +0 -1
- package/src/components/Molecules/CTA/CTAMultiCard/__snapshots__/CTAMultiCard.test.js.snap +996 -2653
- package/src/components/Molecules/CTA/CTASingleCard/CTASingleCard.js +22 -10
- package/src/components/Molecules/CTA/CTASingleCard/CTASingleCard.md +10 -10
- package/src/components/Molecules/CTA/CTASingleCard/CTASingleCard.style.js +7 -9
- package/src/components/Molecules/CTA/CTASingleCard/CTASingleCard.test.js +2 -0
- package/src/components/Molecules/CTA/CTASingleCard/__snapshots__/CTASingleCard.test.js.snap +245 -233
- package/src/components/Molecules/CTA/shared/CTACard.js +14 -7
- package/src/components/Molecules/CTA/shared/CTACard.style.js +80 -43
- package/dist/components/Molecules/OLD_CTAMultiCard/CTAMultiCard.js +0 -58
- package/dist/components/Molecules/OLD_CTAMultiCard/CTAMultiCard.style.js +0 -157
- package/dist/components/Molecules/OLD_CTAMultiCard/CTAMultiCard.test.js +0 -70
- package/dist/components/Molecules/OLD_CTAMultiCard/SingleCard.js +0 -56
- package/dist/components/Molecules/OLD_CTAMultiCard/_ArrowIcon.js +0 -29
- package/dist/components/Molecules/OLD_CTAMultiCard/__snapshots__/CTAMultiCard.test.js.snap +0 -2296
- package/dist/components/Molecules/OLD_CTAMultiCard/example_data.json +0 -107
- package/src/components/Molecules/OLD_CTAMultiCard/CTAMultiCard.js +0 -100
- package/src/components/Molecules/OLD_CTAMultiCard/CTAMultiCard.style.js +0 -259
- package/src/components/Molecules/OLD_CTAMultiCard/CTAMultiCard.test.js +0 -86
- package/src/components/Molecules/OLD_CTAMultiCard/SingleCard.js +0 -100
- package/src/components/Molecules/OLD_CTAMultiCard/_ArrowIcon.js +0 -22
- package/src/components/Molecules/OLD_CTAMultiCard/__snapshots__/CTAMultiCard.test.js.snap +0 -2296
- package/src/components/Molecules/OLD_CTAMultiCard/example_data.json +0 -107
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"__typename": "ContentfulParagraphCardsDs",
|
|
3
|
-
"title": "test cards 6",
|
|
4
|
-
"backgroundColour": "Transparent",
|
|
5
|
-
"layout": "3 columns",
|
|
6
|
-
"columnsOnMd": false,
|
|
7
|
-
"paddingOptions": "Both Off",
|
|
8
|
-
"carouselOfCards": false,
|
|
9
|
-
"cards": [
|
|
10
|
-
{
|
|
11
|
-
"id": "fd8ef3fc-7d0d-531b-b2d2-9ac5f40d3d14",
|
|
12
|
-
"title": "Full Card Oooh Chilly",
|
|
13
|
-
"backgroundColour": "White",
|
|
14
|
-
"link": "/test",
|
|
15
|
-
"linkLabel": "test go",
|
|
16
|
-
"image": {
|
|
17
|
-
"description": "",
|
|
18
|
-
"gatsbyImageData": {
|
|
19
|
-
"images": {
|
|
20
|
-
"sources": [
|
|
21
|
-
{
|
|
22
|
-
"srcSet": "https://images.ctfassets.net/zsfivwzfgl3t/4VsIykPLHDNkNCT9djGrX/c8f1e4cb5c6bda5a7b77f18501e9304d/challenge-1.jpg?w=678&h=501&q=80&fm=webp 678w",
|
|
23
|
-
"sizes": "100vw",
|
|
24
|
-
"type": "image/webp"
|
|
25
|
-
}
|
|
26
|
-
],
|
|
27
|
-
"fallback": {
|
|
28
|
-
"src": "https://images.ctfassets.net/zsfivwzfgl3t/4VsIykPLHDNkNCT9djGrX/c8f1e4cb5c6bda5a7b77f18501e9304d/challenge-1.jpg?w=678&h=501&fl=progressive&q=80&fm=jpg",
|
|
29
|
-
"srcSet": "https://images.ctfassets.net/zsfivwzfgl3t/4VsIykPLHDNkNCT9djGrX/c8f1e4cb5c6bda5a7b77f18501e9304d/challenge-1.jpg?w=678&h=501&fl=progressive&q=80&fm=jpg 678w",
|
|
30
|
-
"sizes": "100vw"
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
"layout": "fullWidth",
|
|
34
|
-
"width": 1,
|
|
35
|
-
"height": 0.7389380530973452,
|
|
36
|
-
"placeholder": {
|
|
37
|
-
"fallback": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAPABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAcIBAb/xAAjEAACAgIBBAIDAAAAAAAAAAABAgMEABEGBRIhMQdBE1Fh/8QAFQEBAQAAAAAAAAAAAAAAAAAAAgT/xAAaEQADAQADAAAAAAAAAAAAAAAAAQIDERIT/9oADAMBAAIRAxEAPwBzRcrjVY+0tonyT41nG8y+SLFTkgpQTVFpoqiRZGHc2/egf4RrMM12OHpNi3LsrAjO2vsKCcQtvkbTW570sMUt6xphJKnd+Ma9A78ZRWcS+SWNLpNMqAdQidVaSxErEA6ZgCNj9YZNPTOTpJW7+ovdlnLHyjgAD6GGPug+bP/Z"
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"id": "fd8ef3fc-7d0d-531b-b2d2-9ac5f40d3d14-2",
|
|
44
|
-
"title": "Full Card Oooh Chilly",
|
|
45
|
-
"backgroundColour": "White",
|
|
46
|
-
"link": "/test",
|
|
47
|
-
"linkLabel": "test go",
|
|
48
|
-
"image": {
|
|
49
|
-
"description": "",
|
|
50
|
-
"gatsbyImageData": {
|
|
51
|
-
"images": {
|
|
52
|
-
"sources": [
|
|
53
|
-
{
|
|
54
|
-
"srcSet": "https://images.ctfassets.net/zsfivwzfgl3t/4VsIykPLHDNkNCT9djGrX/c8f1e4cb5c6bda5a7b77f18501e9304d/challenge-1.jpg?w=678&h=501&q=80&fm=webp 678w",
|
|
55
|
-
"sizes": "100vw",
|
|
56
|
-
"type": "image/webp"
|
|
57
|
-
}
|
|
58
|
-
],
|
|
59
|
-
"fallback": {
|
|
60
|
-
"src": "https://images.ctfassets.net/zsfivwzfgl3t/4VsIykPLHDNkNCT9djGrX/c8f1e4cb5c6bda5a7b77f18501e9304d/challenge-1.jpg?w=678&h=501&fl=progressive&q=80&fm=jpg",
|
|
61
|
-
"srcSet": "https://images.ctfassets.net/zsfivwzfgl3t/4VsIykPLHDNkNCT9djGrX/c8f1e4cb5c6bda5a7b77f18501e9304d/challenge-1.jpg?w=678&h=501&fl=progressive&q=80&fm=jpg 678w",
|
|
62
|
-
"sizes": "100vw"
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
"layout": "fullWidth",
|
|
66
|
-
"width": 1,
|
|
67
|
-
"height": 0.7389380530973452,
|
|
68
|
-
"placeholder": {
|
|
69
|
-
"fallback": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAPABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAcIBAb/xAAjEAACAgIBBAIDAAAAAAAAAAABAgMEABEGBRIhMQdBE1Fh/8QAFQEBAQAAAAAAAAAAAAAAAAAAAgT/xAAaEQADAQADAAAAAAAAAAAAAAAAAQIDERIT/9oADAMBAAIRAxEAPwBzRcrjVY+0tonyT41nG8y+SLFTkgpQTVFpoqiRZGHc2/egf4RrMM12OHpNi3LsrAjO2vsKCcQtvkbTW570sMUt6xphJKnd+Ma9A78ZRWcS+SWNLpNMqAdQidVaSxErEA6ZgCNj9YZNPTOTpJW7+ovdlnLHyjgAD6GGPug+bP/Z"
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
"id": "fd8ef3fc-7d0d-531b-b2d2-9ac5f40d3d14-3",
|
|
76
|
-
"title": "Full Card Oooh Chilly",
|
|
77
|
-
"backgroundColour": "White",
|
|
78
|
-
"link": "/test",
|
|
79
|
-
"linkLabel": "test go",
|
|
80
|
-
"image": {
|
|
81
|
-
"description": "",
|
|
82
|
-
"gatsbyImageData": {
|
|
83
|
-
"images": {
|
|
84
|
-
"sources": [
|
|
85
|
-
{
|
|
86
|
-
"srcSet": "https://images.ctfassets.net/zsfivwzfgl3t/4VsIykPLHDNkNCT9djGrX/c8f1e4cb5c6bda5a7b77f18501e9304d/challenge-1.jpg?w=678&h=501&q=80&fm=webp 678w",
|
|
87
|
-
"sizes": "100vw",
|
|
88
|
-
"type": "image/webp"
|
|
89
|
-
}
|
|
90
|
-
],
|
|
91
|
-
"fallback": {
|
|
92
|
-
"src": "https://images.ctfassets.net/zsfivwzfgl3t/4VsIykPLHDNkNCT9djGrX/c8f1e4cb5c6bda5a7b77f18501e9304d/challenge-1.jpg?w=678&h=501&fl=progressive&q=80&fm=jpg",
|
|
93
|
-
"srcSet": "https://images.ctfassets.net/zsfivwzfgl3t/4VsIykPLHDNkNCT9djGrX/c8f1e4cb5c6bda5a7b77f18501e9304d/challenge-1.jpg?w=678&h=501&fl=progressive&q=80&fm=jpg 678w",
|
|
94
|
-
"sizes": "100vw"
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
|
-
"layout": "fullWidth",
|
|
98
|
-
"width": 1,
|
|
99
|
-
"height": 0.7389380530973452,
|
|
100
|
-
"placeholder": {
|
|
101
|
-
"fallback": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAPABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAcIBAb/xAAjEAACAgIBBAIDAAAAAAAAAAABAgMEABEGBRIhMQdBE1Fh/8QAFQEBAQAAAAAAAAAAAAAAAAAAAgT/xAAaEQADAQADAAAAAAAAAAAAAAAAAQIDERIT/9oADAMBAAIRAxEAPwBzRcrjVY+0tonyT41nG8y+SLFTkgpQTVFpoqiRZGHc2/egf4RrMM12OHpNi3LsrAjO2vsKCcQtvkbTW570sMUt6xphJKnd+Ma9A78ZRWcS+SWNLpNMqAdQidVaSxErEA6ZgCNj9YZNPTOTpJW7+ovdlnLHyjgAD6GGPug+bP/Z"
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
]
|
|
107
|
-
}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { snakeCase } from 'lodash';
|
|
4
|
-
import SingleCard from './SingleCard';
|
|
5
|
-
import {
|
|
6
|
-
CardsContainer
|
|
7
|
-
} from './CTAMultiCard.style';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* CTAMultiCard Component
|
|
11
|
-
*
|
|
12
|
-
* This component is a successor to the CardsDs component.
|
|
13
|
-
* Previously, the comicrelief-contentful frontend would map
|
|
14
|
-
* through data and create multiple CardsDs instances.
|
|
15
|
-
* Now CTAMultiCard handles the mapping internally, accepting
|
|
16
|
-
* a data object and rendering all cards.
|
|
17
|
-
*
|
|
18
|
-
* Note: The component expects pre-rendered content in the `body`
|
|
19
|
-
* field of each card. The frontend should handle rich text rendering
|
|
20
|
-
* before passing data to this component.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
const CTAMultiCard = ({ data }) => {
|
|
24
|
-
const {
|
|
25
|
-
cards,
|
|
26
|
-
backgroundColour: bgCards,
|
|
27
|
-
layout,
|
|
28
|
-
carouselOfCards,
|
|
29
|
-
paddingAbove,
|
|
30
|
-
paddingBelow
|
|
31
|
-
} = data;
|
|
32
|
-
|
|
33
|
-
if (!cards || !Array.isArray(cards) || cards.length === 0) {
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Convert layout string to number (e.g., "3 columns"
|
|
38
|
-
// (that's how it comes through from Contentful) -> 3)
|
|
39
|
-
const columns = layout && layout.includes('3') ? 3 : 2;
|
|
40
|
-
|
|
41
|
-
const cardsBackground = snakeCase(bgCards || 'white');
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<CardsContainer
|
|
45
|
-
backgroundColor={cardsBackground}
|
|
46
|
-
columns={columns}
|
|
47
|
-
isCarousel={carouselOfCards}
|
|
48
|
-
paddingAbove={paddingAbove}
|
|
49
|
-
paddingBelow={paddingBelow}
|
|
50
|
-
>
|
|
51
|
-
{cards.map(card => (
|
|
52
|
-
<SingleCard
|
|
53
|
-
key={card.id}
|
|
54
|
-
card={card}
|
|
55
|
-
isCarousel={carouselOfCards}
|
|
56
|
-
/>
|
|
57
|
-
))}
|
|
58
|
-
</CardsContainer>
|
|
59
|
-
);
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
CTAMultiCard.propTypes = {
|
|
63
|
-
data: PropTypes.shape({
|
|
64
|
-
cards: PropTypes.arrayOf(
|
|
65
|
-
PropTypes.shape({
|
|
66
|
-
id: PropTypes.string.isRequired,
|
|
67
|
-
body: PropTypes.node,
|
|
68
|
-
image: PropTypes.shape({
|
|
69
|
-
description: PropTypes.string,
|
|
70
|
-
gatsbyImageData: PropTypes.shape({
|
|
71
|
-
placeholder: PropTypes.shape({
|
|
72
|
-
fallback: PropTypes.string
|
|
73
|
-
}),
|
|
74
|
-
images: PropTypes.shape({
|
|
75
|
-
fallback: PropTypes.shape({
|
|
76
|
-
src: PropTypes.string,
|
|
77
|
-
srcSet: PropTypes.string
|
|
78
|
-
}),
|
|
79
|
-
sources: PropTypes.arrayOf(
|
|
80
|
-
PropTypes.shape({
|
|
81
|
-
srcSet: PropTypes.string
|
|
82
|
-
})
|
|
83
|
-
)
|
|
84
|
-
})
|
|
85
|
-
})
|
|
86
|
-
}),
|
|
87
|
-
backgroundColour: PropTypes.string,
|
|
88
|
-
link: PropTypes.string,
|
|
89
|
-
linkLabel: PropTypes.string
|
|
90
|
-
})
|
|
91
|
-
).isRequired,
|
|
92
|
-
backgroundColour: PropTypes.string,
|
|
93
|
-
layout: PropTypes.string,
|
|
94
|
-
carouselOfCards: PropTypes.bool,
|
|
95
|
-
paddingAbove: PropTypes.string,
|
|
96
|
-
paddingBelow: PropTypes.string
|
|
97
|
-
}).isRequired
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
export default CTAMultiCard;
|
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
import styled, { css } from 'styled-components';
|
|
2
|
-
import { bounceUpAnimation, springScaleAnimation } from '../../../theme/shared/animations';
|
|
3
|
-
import { breakpointValues } from '../../../theme/shared/allBreakpoints';
|
|
4
|
-
import fontHelper from '../../../theme/crTheme/fontHelper';
|
|
5
|
-
|
|
6
|
-
const CardsContainer = styled.div`
|
|
7
|
-
padding-top: ${({ paddingAbove }) => paddingAbove};
|
|
8
|
-
padding-bottom: ${({ paddingBelow }) => paddingBelow};
|
|
9
|
-
display: flex;
|
|
10
|
-
flex-direction: column;
|
|
11
|
-
width: 100%;
|
|
12
|
-
background: ${({ theme, backgroundColor }) => theme.color(backgroundColor)};
|
|
13
|
-
gap: 1rem;
|
|
14
|
-
|
|
15
|
-
// Mobile stack mode - vertical layout (only on mobile, below M breakpoint)
|
|
16
|
-
${({ isCarousel }) => !isCarousel && css`
|
|
17
|
-
@media (max-width: ${breakpointValues.M - 1}px) {
|
|
18
|
-
flex-direction: column;
|
|
19
|
-
background: transparent;
|
|
20
|
-
}
|
|
21
|
-
`}
|
|
22
|
-
|
|
23
|
-
// Non-mobile layout (M and above) - consistent across carousel/non-carousel, as above M we only do stacked mode.
|
|
24
|
-
@media ${({ theme }) => theme.allBreakpoints('M')} {
|
|
25
|
-
flex-direction: row;
|
|
26
|
-
flex-wrap: wrap;
|
|
27
|
-
justify-content: center;
|
|
28
|
-
align-items: stretch;
|
|
29
|
-
width: fit-content;
|
|
30
|
-
max-width: 100%;
|
|
31
|
-
margin: 0 auto;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Carousel mode - horizontal scroll container (M and below)
|
|
35
|
-
${({ isCarousel }) => isCarousel && css`
|
|
36
|
-
@media (max-width: ${breakpointValues.L - 1}px) {
|
|
37
|
-
flex-direction: row;
|
|
38
|
-
flex-wrap: nowrap;
|
|
39
|
-
justify-content: flex-start;
|
|
40
|
-
width: 100%;
|
|
41
|
-
margin: 0;
|
|
42
|
-
max-width: 100%;
|
|
43
|
-
overflow-x: visible;
|
|
44
|
-
overflow-y: scroll;
|
|
45
|
-
-webkit-overflow-scrolling: touch;
|
|
46
|
-
scroll-snap-type: x mandatory;
|
|
47
|
-
padding: 0.75rem 1rem;
|
|
48
|
-
|
|
49
|
-
scrollbar-width: none;
|
|
50
|
-
-ms-overflow-style: none;
|
|
51
|
-
&::-webkit-scrollbar {
|
|
52
|
-
display: none;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
`}
|
|
56
|
-
|
|
57
|
-
// Desktop grid layout for XL breakpoint - 3 columns
|
|
58
|
-
@media ${({ theme }) => theme.allBreakpoints('XL')} {
|
|
59
|
-
${({ columns }) => columns === 3 && css`
|
|
60
|
-
display: grid;
|
|
61
|
-
justify-content: center;
|
|
62
|
-
align-items: stretch;
|
|
63
|
-
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
64
|
-
width: 100%;
|
|
65
|
-
margin: 0 auto;
|
|
66
|
-
max-width: 100%;
|
|
67
|
-
|
|
68
|
-
/*
|
|
69
|
-
Above 1724px (3 * 564px which is the card max-width + 2 * 1rem), this is to stop the visible "gaps" growing
|
|
70
|
-
between the cards on really wide screens (so the only space between cards is the gap (1rem)).
|
|
71
|
-
*/
|
|
72
|
-
@media (min-width: 1724px) {
|
|
73
|
-
grid-template-columns: repeat(3, 564px);
|
|
74
|
-
width: fit-content;
|
|
75
|
-
}
|
|
76
|
-
`}
|
|
77
|
-
}
|
|
78
|
-
`;
|
|
79
|
-
|
|
80
|
-
const ImageWrapper = styled.div`
|
|
81
|
-
width: 100%;
|
|
82
|
-
overflow: hidden;
|
|
83
|
-
flex-shrink: 0;
|
|
84
|
-
background: transparent;
|
|
85
|
-
|
|
86
|
-
img {
|
|
87
|
-
width: 100%;
|
|
88
|
-
height: auto;
|
|
89
|
-
object-fit: cover;
|
|
90
|
-
display: block;
|
|
91
|
-
|
|
92
|
-
// Desktop-only image zoom animation on card hover
|
|
93
|
-
@media ${({ theme }) => theme.allBreakpoints('M')} {
|
|
94
|
-
${springScaleAnimation(true)}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
`;
|
|
98
|
-
|
|
99
|
-
const CTAText = styled.span`
|
|
100
|
-
${({ theme }) => fontHelper(theme, 'span')}
|
|
101
|
-
color: ${({ theme }) => theme.color('grey')};
|
|
102
|
-
font-weight: bold;
|
|
103
|
-
text-decoration: none;
|
|
104
|
-
position: relative;
|
|
105
|
-
display: inline-block;
|
|
106
|
-
`;
|
|
107
|
-
|
|
108
|
-
const CTATextUnderline = styled.img`
|
|
109
|
-
height: 4px;
|
|
110
|
-
width: 100%;
|
|
111
|
-
position: absolute;
|
|
112
|
-
left: 0;
|
|
113
|
-
bottom: -5px;
|
|
114
|
-
transition: opacity 0.15s 0.1s;
|
|
115
|
-
opacity: 0;
|
|
116
|
-
pointer-events: none;
|
|
117
|
-
`;
|
|
118
|
-
|
|
119
|
-
const ArrowIconWrapper = styled.div`
|
|
120
|
-
width: 32px;
|
|
121
|
-
height: 32px;
|
|
122
|
-
border-radius: 50%;
|
|
123
|
-
background: ${({ theme }) => theme.color('grey')};
|
|
124
|
-
display: flex;
|
|
125
|
-
align-items: center;
|
|
126
|
-
justify-content: center;
|
|
127
|
-
flex-shrink: 0;
|
|
128
|
-
`;
|
|
129
|
-
|
|
130
|
-
// Card wrapper link - makes entire card clickable
|
|
131
|
-
const CardLink = styled.a`
|
|
132
|
-
display: flex;
|
|
133
|
-
position: relative;
|
|
134
|
-
flex-direction: column;
|
|
135
|
-
width: 100%;
|
|
136
|
-
flex: 1 1 auto;
|
|
137
|
-
background: transparent;
|
|
138
|
-
border-radius: 1rem;
|
|
139
|
-
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.15);
|
|
140
|
-
text-decoration: none;
|
|
141
|
-
overflow: hidden;
|
|
142
|
-
cursor: pointer;
|
|
143
|
-
|
|
144
|
-
img {
|
|
145
|
-
// Zoom the image in slightly by default so the 'bounce' animation doesn't cause issues
|
|
146
|
-
transform: scale(1.02);
|
|
147
|
-
transition: transform ${0.4}s cubic-bezier(0.68, ${-1.15}, 0.265, ${2.35});
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Desktop-only hover effects
|
|
151
|
-
@media ${({ theme }) => theme.allBreakpoints('M')} {
|
|
152
|
-
${bounceUpAnimation(true, 0.02, 1)};
|
|
153
|
-
|
|
154
|
-
&:hover {
|
|
155
|
-
box-shadow: 0 0 1.5rem rgba(0, 0, 0, 0.25);
|
|
156
|
-
|
|
157
|
-
${ImageWrapper} img {
|
|
158
|
-
transform: scale(1.1);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
${CTAText} {
|
|
162
|
-
color: ${({ theme }) => theme.color('red')};
|
|
163
|
-
text-decoration: none;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
${CTATextUnderline} {
|
|
167
|
-
opacity: 1;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
${ArrowIconWrapper} {
|
|
171
|
-
background: ${({ theme }) => theme.color('red')};
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
`;
|
|
176
|
-
|
|
177
|
-
const CardWrapper = styled.div`
|
|
178
|
-
width: 100%;
|
|
179
|
-
flex-shrink: 0;
|
|
180
|
-
display: flex;
|
|
181
|
-
flex-direction: column;
|
|
182
|
-
align-self: stretch;
|
|
183
|
-
|
|
184
|
-
// Carousel mode - cards at normal width in horizontal scroll (Medium and below)
|
|
185
|
-
${({ isCarousel }) => isCarousel && css`
|
|
186
|
-
@media (max-width: ${breakpointValues.L - 1}px) {
|
|
187
|
-
scroll-snap-align: start;
|
|
188
|
-
flex: 0 0 calc(100% - 1.5rem);
|
|
189
|
-
min-width: calc(100% - 1.5rem);
|
|
190
|
-
max-width: calc(100% - 1.5rem);
|
|
191
|
-
flex-shrink: 0;
|
|
192
|
-
}
|
|
193
|
-
`}
|
|
194
|
-
|
|
195
|
-
// Mobile stack mode - cards at normal width in vertical stack (only on mobile, below M breakpoint)
|
|
196
|
-
${({ isCarousel }) => !isCarousel && css`
|
|
197
|
-
@media (max-width: ${breakpointValues.M - 1}px) {
|
|
198
|
-
width: 100%;
|
|
199
|
-
}
|
|
200
|
-
`}
|
|
201
|
-
|
|
202
|
-
// Desktop M breakpoint - 2 columns layout
|
|
203
|
-
// - when isCarousel is true we only switch to "desktop" layout at L and above
|
|
204
|
-
@media ${({ theme, isCarousel }) => theme.allBreakpoints(isCarousel ? 'L' : 'M')} {
|
|
205
|
-
flex-basis: calc(50% - 1rem);
|
|
206
|
-
max-width: 564px;
|
|
207
|
-
height: 100%;
|
|
208
|
-
align-self: stretch;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Desktop XL breakpoint - 3 columns layout
|
|
212
|
-
@media ${({ theme }) => theme.allBreakpoints('XL')} {
|
|
213
|
-
flex-basis: unset;
|
|
214
|
-
max-width: 564px;
|
|
215
|
-
height: 100%;
|
|
216
|
-
align-self: stretch;
|
|
217
|
-
}
|
|
218
|
-
`;
|
|
219
|
-
|
|
220
|
-
const CopyAndLinkSection = styled.div`
|
|
221
|
-
width: 100%;
|
|
222
|
-
background: ${({ theme, backgroundColor }) => theme.color(backgroundColor)};
|
|
223
|
-
display: flex;
|
|
224
|
-
flex-direction: column;
|
|
225
|
-
padding: 2rem;
|
|
226
|
-
flex: 1;
|
|
227
|
-
min-height: 0;
|
|
228
|
-
border-radius: 0 0 1rem 1rem;
|
|
229
|
-
`;
|
|
230
|
-
|
|
231
|
-
const Copy = styled.div`
|
|
232
|
-
flex: 1;
|
|
233
|
-
display: flex;
|
|
234
|
-
flex-direction: column;
|
|
235
|
-
min-height: 0;
|
|
236
|
-
`;
|
|
237
|
-
|
|
238
|
-
const CTA = styled.div`
|
|
239
|
-
width: 100%;
|
|
240
|
-
display: flex;
|
|
241
|
-
flex-direction: row;
|
|
242
|
-
align-items: center;
|
|
243
|
-
justify-content: space-between;
|
|
244
|
-
margin-top: auto;
|
|
245
|
-
padding-top: 1rem;
|
|
246
|
-
`;
|
|
247
|
-
|
|
248
|
-
export {
|
|
249
|
-
CardLink,
|
|
250
|
-
ImageWrapper,
|
|
251
|
-
CopyAndLinkSection,
|
|
252
|
-
Copy,
|
|
253
|
-
CTA,
|
|
254
|
-
CTAText,
|
|
255
|
-
CTATextUnderline,
|
|
256
|
-
ArrowIconWrapper,
|
|
257
|
-
CardsContainer,
|
|
258
|
-
CardWrapper
|
|
259
|
-
};
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import 'jest-styled-components';
|
|
3
|
-
import renderWithTheme from '../../../../tests/hoc/shallowWithTheme';
|
|
4
|
-
import CTAMultiCard from './CTAMultiCard';
|
|
5
|
-
import exampleData from './example_data.json';
|
|
6
|
-
import Text from '../../Atoms/Text/Text';
|
|
7
|
-
|
|
8
|
-
// Map example data cards to include pre-rendered body content
|
|
9
|
-
const cardsWithRenderedBody = exampleData.cards.map(card => ({
|
|
10
|
-
...card,
|
|
11
|
-
body: (
|
|
12
|
-
<Text tag="p">
|
|
13
|
-
<strong>Load</strong> of text here
|
|
14
|
-
</Text>
|
|
15
|
-
)
|
|
16
|
-
}));
|
|
17
|
-
|
|
18
|
-
const mockData = {
|
|
19
|
-
...exampleData,
|
|
20
|
-
cards: [
|
|
21
|
-
...cardsWithRenderedBody,
|
|
22
|
-
// Add a card without image for testing edge cases. This should not ever really happen in real life, but just in case...
|
|
23
|
-
{
|
|
24
|
-
id: '6bc887c7-f939-5654-a0c5-1b2caf91de6c',
|
|
25
|
-
title: 'Card no pic',
|
|
26
|
-
backgroundColour: 'Blue Light',
|
|
27
|
-
link: '/test-no-image',
|
|
28
|
-
linkLabel: 'View card',
|
|
29
|
-
body: (
|
|
30
|
-
<Text tag="p">
|
|
31
|
-
Load of text here
|
|
32
|
-
</Text>
|
|
33
|
-
),
|
|
34
|
-
image: null
|
|
35
|
-
}
|
|
36
|
-
]
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
it('renders correctly with data prop', () => {
|
|
40
|
-
const tree = renderWithTheme(
|
|
41
|
-
<CTAMultiCard data={mockData} />
|
|
42
|
-
).toJSON();
|
|
43
|
-
|
|
44
|
-
expect(tree).toMatchSnapshot();
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('renders carousel mode correctly', () => {
|
|
48
|
-
const carouselData = {
|
|
49
|
-
...mockData,
|
|
50
|
-
carouselOfCards: true
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const tree = renderWithTheme(
|
|
54
|
-
<CTAMultiCard data={carouselData} />
|
|
55
|
-
).toJSON();
|
|
56
|
-
|
|
57
|
-
expect(tree).toMatchSnapshot();
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('renders 2 columns layout correctly', () => {
|
|
61
|
-
const twoColumnData = {
|
|
62
|
-
...mockData,
|
|
63
|
-
layout: '2 columns'
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const tree = renderWithTheme(
|
|
67
|
-
<CTAMultiCard data={twoColumnData} />
|
|
68
|
-
).toJSON();
|
|
69
|
-
|
|
70
|
-
expect(tree).toMatchSnapshot();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('handles data structure correctly', () => {
|
|
74
|
-
const testData = {
|
|
75
|
-
cards: mockData.cards,
|
|
76
|
-
backgroundColour: 'White',
|
|
77
|
-
layout: '3 columns',
|
|
78
|
-
carouselOfCards: false
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const tree = renderWithTheme(
|
|
82
|
-
<CTAMultiCard data={testData} />
|
|
83
|
-
).toJSON();
|
|
84
|
-
|
|
85
|
-
expect(tree).toMatchSnapshot();
|
|
86
|
-
});
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import Picture from '../../Atoms/Picture/Picture';
|
|
4
|
-
import ArrowIcon from './_ArrowIcon';
|
|
5
|
-
import altCtaUnderline from '../../../theme/shared/assets/alt_cta_underline.svg';
|
|
6
|
-
import {
|
|
7
|
-
CardLink,
|
|
8
|
-
ImageWrapper,
|
|
9
|
-
CopyAndLinkSection,
|
|
10
|
-
Copy,
|
|
11
|
-
CTA,
|
|
12
|
-
CTAText,
|
|
13
|
-
CTATextUnderline,
|
|
14
|
-
ArrowIconWrapper,
|
|
15
|
-
CardWrapper
|
|
16
|
-
} from './CTAMultiCard.style';
|
|
17
|
-
|
|
18
|
-
const SingleCard = ({
|
|
19
|
-
card,
|
|
20
|
-
isCarousel
|
|
21
|
-
}) => {
|
|
22
|
-
const {
|
|
23
|
-
id,
|
|
24
|
-
body,
|
|
25
|
-
link,
|
|
26
|
-
linkLabel,
|
|
27
|
-
fallback,
|
|
28
|
-
imageLow,
|
|
29
|
-
images,
|
|
30
|
-
bgColour,
|
|
31
|
-
description,
|
|
32
|
-
target,
|
|
33
|
-
external
|
|
34
|
-
} = card;
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<CardWrapper key={id} isCarousel={isCarousel}>
|
|
38
|
-
<CardLink
|
|
39
|
-
href={link}
|
|
40
|
-
target={target}
|
|
41
|
-
rel={external}
|
|
42
|
-
isCarousel={isCarousel}
|
|
43
|
-
backgroundColor={bgColour}
|
|
44
|
-
>
|
|
45
|
-
{imageLow && (
|
|
46
|
-
<ImageWrapper>
|
|
47
|
-
<Picture
|
|
48
|
-
alt={description}
|
|
49
|
-
imageLow={imageLow}
|
|
50
|
-
images={images}
|
|
51
|
-
image={fallback}
|
|
52
|
-
objectFit="cover"
|
|
53
|
-
width="100%"
|
|
54
|
-
height="100%"
|
|
55
|
-
/>
|
|
56
|
-
</ImageWrapper>
|
|
57
|
-
)}
|
|
58
|
-
<CopyAndLinkSection backgroundColor={bgColour}>
|
|
59
|
-
<Copy>
|
|
60
|
-
{body}
|
|
61
|
-
</Copy>
|
|
62
|
-
{linkLabel && (
|
|
63
|
-
<CTA>
|
|
64
|
-
<CTAText>
|
|
65
|
-
{linkLabel}
|
|
66
|
-
<CTATextUnderline
|
|
67
|
-
src={altCtaUnderline}
|
|
68
|
-
alt=""
|
|
69
|
-
aria-hidden="true"
|
|
70
|
-
/>
|
|
71
|
-
</CTAText>
|
|
72
|
-
<ArrowIconWrapper>
|
|
73
|
-
<ArrowIcon />
|
|
74
|
-
</ArrowIconWrapper>
|
|
75
|
-
</CTA>
|
|
76
|
-
)}
|
|
77
|
-
</CopyAndLinkSection>
|
|
78
|
-
</CardLink>
|
|
79
|
-
</CardWrapper>
|
|
80
|
-
);
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
SingleCard.propTypes = {
|
|
84
|
-
card: PropTypes.shape({
|
|
85
|
-
id: PropTypes.string.isRequired,
|
|
86
|
-
body: PropTypes.node,
|
|
87
|
-
link: PropTypes.string.isRequired,
|
|
88
|
-
linkLabel: PropTypes.string,
|
|
89
|
-
fallback: PropTypes.string,
|
|
90
|
-
imageLow: PropTypes.string,
|
|
91
|
-
images: PropTypes.string,
|
|
92
|
-
bgColour: PropTypes.string.isRequired,
|
|
93
|
-
description: PropTypes.string,
|
|
94
|
-
target: PropTypes.string.isRequired,
|
|
95
|
-
external: PropTypes.string
|
|
96
|
-
}).isRequired,
|
|
97
|
-
isCarousel: PropTypes.bool
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
export default SingleCard;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import styled from 'styled-components';
|
|
3
|
-
|
|
4
|
-
const StyledArrowIcon = styled.svg`
|
|
5
|
-
display: inline-block;
|
|
6
|
-
color: ${({ theme }) => theme.color('white')};
|
|
7
|
-
fill: currentColor;
|
|
8
|
-
`;
|
|
9
|
-
|
|
10
|
-
const ArrowIcon = () => (
|
|
11
|
-
<StyledArrowIcon
|
|
12
|
-
width="15"
|
|
13
|
-
height="13"
|
|
14
|
-
viewBox="0 0 15 13"
|
|
15
|
-
fill="none"
|
|
16
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
17
|
-
>
|
|
18
|
-
<path d="M9.58496 0.349976C9.1395 -0.116662 8.40641 -0.116634 7.96094 0.349976C7.52803 0.803486 7.5281 1.53021 7.96094 1.98376L11.1582 5.33337H1.13672C0.48748 5.33337 0 5.87822 0 6.50037C2.15408e-05 7.1225 0.487494 7.66736 1.13672 7.66736H11.1582L7.96094 11.017C7.52806 11.4705 7.52899 12.1972 7.96191 12.6508C8.18163 12.8803 8.47556 13.0004 8.77344 13.0004C9.07114 13.0002 9.36533 12.8808 9.58496 12.6508L14.6758 7.31677L14.6748 7.3158L14.6875 7.3031L14.6865 7.30212C14.6954 7.29215 14.7044 7.28482 14.71 7.27771C14.7117 7.27545 14.7133 7.27285 14.7148 7.27087C14.7485 7.23203 14.7824 7.18925 14.8135 7.14099L14.8154 7.13806C14.8354 7.10658 14.8493 7.07842 14.8564 7.06384L14.8652 7.04626L14.8662 7.04431L14.8672 7.04333C14.8672 7.04333 14.868 7.04057 14.8691 7.03845C14.8709 7.03512 14.8758 7.02671 14.8799 7.01892L14.8802 7.01839C14.8888 7.002 14.9034 6.97423 14.917 6.93982V6.93787C14.9303 6.90375 14.9391 6.87285 14.9443 6.85388C14.9469 6.84458 14.9498 6.83567 14.9512 6.83044C14.9527 6.82454 14.9535 6.8228 14.9541 6.82068C14.9541 6.82068 14.9542 6.81753 14.9551 6.81482L14.958 6.80603L14.9586 6.80422C14.9631 6.78961 14.9718 6.76119 14.9785 6.72693V6.72498C15.0066 6.57705 15.0066 6.4246 14.9785 6.27673V6.27478L14.958 6.19568L14.9551 6.18591L14.9531 6.18005L14.9512 6.17224C14.9497 6.1664 14.9481 6.15677 14.9453 6.14685C14.9398 6.12695 14.9307 6.09654 14.917 6.06189C14.9032 6.02688 14.8885 5.99813 14.8799 5.98181C14.8758 5.97402 14.8709 5.96562 14.8691 5.96228L14.8564 5.93689C14.849 5.92177 14.8351 5.89372 14.8154 5.86267L14.8145 5.86072L14.7529 5.7738C14.7316 5.74659 14.7094 5.72129 14.6875 5.69763C14.6837 5.69341 14.6802 5.68854 14.6758 5.68396L9.58496 0.349976Z" fill="currentColor" />
|
|
19
|
-
</StyledArrowIcon>
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
export default ArrowIcon;
|