Skip to content

Commit ac317af

Browse files
authored
Merge pull request #13579 from guardian/doml/card-gap-sizing-fix
Card gap sizing amendments
2 parents c2f1e13 + 81a25fb commit ac317af

File tree

4 files changed

+143
-62
lines changed

4 files changed

+143
-62
lines changed

dotcom-rendering/src/components/Card/Card.tsx

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ export const Card = ({
499499
<div
500500
css={css`
501501
margin-top: auto;
502+
display: flex;
502503
`}
503504
>
504505
{isVideoArticle && (
@@ -626,51 +627,61 @@ export const Card = ({
626627
}
627628
};
628629

629-
/** Determines the gap of between card components based on card properties */
630+
/**
631+
* Determines the gap of between card components based on card properties
632+
* Order matters here as the logic is based on the card properties
633+
*/
630634
const getGapSizes = (): GapSizes => {
631635
if (isOnwardContent) {
632636
return {
633637
row: 'none',
634638
column: 'none',
635639
};
636640
}
637-
if (isMediaCardOrNewsletter && !isFlexibleContainer) {
638-
return {
639-
row: 'tiny',
640-
column: 'tiny',
641-
};
642-
}
643-
if (!!isFlexSplash || (isFlexibleContainer && imageSize === 'jumbo')) {
641+
642+
if (isFlexSplash) {
644643
return {
645644
row: 'small',
646-
column: 'small',
645+
column: 'none',
647646
};
648647
}
648+
649+
if (!isBetaContainer) {
650+
/**
651+
* Media cards have 4px padding around the content so we have a
652+
* tiny (4px) gap to account for this and make it 8px total
653+
*/
654+
if (isMediaCardOrNewsletter) {
655+
return {
656+
row: 'tiny',
657+
column: 'tiny',
658+
};
659+
}
660+
661+
// Current cards have small padding for everything
662+
return { row: 'small', column: 'small' };
663+
}
664+
649665
if (isSmallCard) {
650666
return {
651667
row: 'medium',
652668
column: 'medium',
653669
};
654670
}
655-
if (isBetaContainer && media?.type === 'avatar') {
656-
return {
657-
row: 'small',
658-
column: 'small',
659-
};
660-
}
671+
661672
if (
662-
isFlexibleContainer &&
663-
(imagePositionOnDesktop === 'left' ||
664-
imagePositionOnDesktop === 'right')
673+
imagePositionOnDesktop === 'bottom' ||
674+
imagePositionOnMobile === 'bottom'
665675
) {
666676
return {
667-
row: 'large',
677+
row: 'tiny',
668678
column: 'large',
669679
};
670680
}
681+
671682
return {
672-
row: isBetaContainer ? 'tiny' : 'small',
673-
column: 'small',
683+
row: 'small',
684+
column: 'large',
674685
};
675686
};
676687

@@ -1052,13 +1063,19 @@ export const Card = ({
10521063
<ContentWrapper
10531064
imageType={media?.type}
10541065
imageSize={imageSize}
1066+
isBetaContainer={isBetaContainer}
10551067
imagePositionOnDesktop={imagePositionOnDesktop}
1068+
imagePositionOnMobile={imagePositionOnMobile}
10561069
padContent={determinePadContent(
10571070
isMediaCardOrNewsletter,
10581071
isBetaContainer,
10591072
isOnwardContent,
10601073
)}
1061-
isFlexibleContainer={isFlexibleContainer}
1074+
padRight={
1075+
!!isFlexSplash &&
1076+
image &&
1077+
imagePositionOnDesktop === 'right'
1078+
}
10621079
>
10631080
{/* This div is needed to keep the headline and trail text justified at the start */}
10641081
<div

dotcom-rendering/src/components/Card/components/CardLayout.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ const decidePosition = (
156156
`;
157157
};
158158

159-
/** Detemines the gap size between components in card layout */
159+
/** Determines the gap size between components in card layout */
160160
const decideGap = (gapSize: GapSize) => {
161161
switch (gapSize) {
162162
case 'none':
@@ -172,6 +172,14 @@ const decideGap = (gapSize: GapSize) => {
172172
}
173173
};
174174

175+
const decideColumnGap = (gapSize: GapSize) => css`
176+
column-gap: ${gapSize === 'large' ? '10px' : decideGap(gapSize)};
177+
178+
${from.tablet} {
179+
column-gap: ${decideGap(gapSize)};
180+
}
181+
`;
182+
175183
export const CardLayout = ({
176184
children,
177185
cardBackgroundColour,
@@ -196,11 +204,11 @@ export const CardLayout = ({
196204
isBetaContainer,
197205
imageType === 'avatar',
198206
),
207+
decideColumnGap(gapSizes.column),
199208
]}
200209
style={{
201210
backgroundColor: cardBackgroundColour,
202211
rowGap: decideGap(gapSizes.row),
203-
columnGap: decideGap(gapSizes.column),
204212
}}
205213
>
206214
{children}

dotcom-rendering/src/components/Card/components/ContentWrapper.tsx

Lines changed: 63 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { SerializedStyles } from '@emotion/react';
22
import { css } from '@emotion/react';
3-
import { between, from, space } from '@guardian/source/foundations';
3+
import { between, from, space, until } from '@guardian/source/foundations';
44
import type { CardImageType } from '../../../types/layout';
55
import type { ImagePositionType, ImageSizeType } from './ImageWrapper';
66

@@ -14,7 +14,6 @@ const sizingStyles = css`
1414
/**
1515
* This function works in partnership with its sibling in `ImageWrapper`. If you
1616
* change any values here be sure to update that file as well.
17-
*
1817
*/
1918
const flexBasisStyles = ({
2019
imageSize,
@@ -61,67 +60,99 @@ const flexBasisStyles = ({
6160
}
6261
};
6362

64-
const paddingStyles = (
63+
type ImageDirection = 'vertical' | 'horizontal' | 'none';
64+
65+
/**
66+
* There is no padding on the side of the image where the text is.
67+
*/
68+
const paddingBetaContainerStyles = (
69+
imagePositionMobile: ImagePositionType,
70+
imagePositionDesktop: ImagePositionType,
71+
padding: 1 | 2,
72+
) => css`
73+
${until.tablet} {
74+
padding-left: ${imagePositionMobile !== 'left' &&
75+
`${space[padding]}px`};
76+
padding-right: ${imagePositionMobile !== 'right' &&
77+
`${space[padding]}px`};
78+
padding-top: ${imagePositionMobile !== 'top' && `${space[padding]}px`};
79+
padding-bottom: ${imagePositionMobile !== 'bottom' &&
80+
`${space[padding]}px`};
81+
}
82+
${from.tablet} {
83+
padding-left: ${imagePositionDesktop !== 'left' &&
84+
`${space[padding]}px`};
85+
padding-right: ${imagePositionDesktop !== 'right' &&
86+
`${space[padding]}px`};
87+
padding-top: ${imagePositionDesktop !== 'top' && `${space[padding]}px`};
88+
padding-bottom: ${imagePositionDesktop !== 'bottom' &&
89+
`${space[padding]}px`};
90+
}
91+
`;
92+
93+
const padRightStyles = css`
94+
${from.tablet} {
95+
padding-right: ${space[5]}px;
96+
}
97+
`;
98+
99+
const getImageDirection = (
65100
imagePosition: ImagePositionType,
66-
isFlexibleContainer: boolean,
67-
paddingWidth: 1 | 2,
68-
) => {
69-
/**
70-
* If we're in a flexible container there is a 20px gap between the image
71-
* and content. We don't apply padding to the content on the same edge as
72-
* the image so the content is aligned with the grid.
73-
*/
74-
if (isFlexibleContainer && imagePosition === 'left') {
75-
return css`
76-
padding: ${space[paddingWidth]}px ${space[paddingWidth]}px
77-
${space[paddingWidth]}px 0;
78-
`;
101+
): ImageDirection => {
102+
if (imagePosition === 'top' || imagePosition === 'bottom') {
103+
return 'vertical';
79104
}
80105

81-
if (isFlexibleContainer && imagePosition === 'right') {
82-
return css`
83-
padding: ${space[paddingWidth]}px 0 ${space[paddingWidth]}px
84-
${space[paddingWidth]}px;
85-
`;
106+
if (imagePosition === 'left' || imagePosition === 'right') {
107+
return 'horizontal';
86108
}
87109

88-
return css`
89-
padding: ${space[paddingWidth]}px;
90-
`;
110+
return 'none';
91111
};
92112

93113
type Props = {
94114
children: React.ReactNode;
95115
imageType?: CardImageType;
96116
imageSize: ImageSizeType;
117+
isBetaContainer: boolean;
97118
imagePositionOnDesktop: ImagePositionType;
119+
imagePositionOnMobile: ImagePositionType;
98120
padContent?: 'small' | 'large';
99-
isFlexibleContainer?: boolean;
121+
padRight?: boolean;
100122
};
101123

102124
export const ContentWrapper = ({
103125
children,
104126
imageType,
105127
imageSize,
128+
isBetaContainer,
106129
imagePositionOnDesktop,
130+
imagePositionOnMobile,
107131
padContent,
108-
isFlexibleContainer = false,
132+
padRight = false,
109133
}: Props) => {
110-
const isHorizontalOnDesktop =
111-
imagePositionOnDesktop === 'left' || imagePositionOnDesktop === 'right';
134+
const imageDirectionDesktop = getImageDirection(imagePositionOnDesktop);
135+
const paddingSpace = padContent === 'small' ? 1 : 2;
112136

113137
return (
114138
<div
115139
css={[
116140
sizingStyles,
117-
isHorizontalOnDesktop &&
141+
imageDirectionDesktop === 'horizontal' &&
118142
flexBasisStyles({ imageSize, imageType }),
119143
padContent &&
120-
paddingStyles(
144+
!isBetaContainer &&
145+
css`
146+
padding: ${space[paddingSpace]}px;
147+
`,
148+
padContent &&
149+
isBetaContainer &&
150+
paddingBetaContainerStyles(
151+
imagePositionOnMobile,
121152
imagePositionOnDesktop,
122-
isFlexibleContainer,
123-
padContent === 'small' ? 1 : 2,
153+
paddingSpace,
124154
),
155+
padRight && padRightStyles,
125156
]}
126157
>
127158
{children}

dotcom-rendering/src/components/Card/components/ImageWrapper.tsx

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,27 @@ const imageOverlayContainerStyles = css`
5353
height: 100%;
5454
`;
5555

56+
/**
57+
* There is no padding on the side of the image where the text is.
58+
*/
59+
const imagePaddingStyles = (
60+
imagePositionOnDesktop: ImagePositionType,
61+
imagePositionOnMobile: ImagePositionType,
62+
) => css`
63+
${until.tablet} {
64+
padding-left: ${imagePositionOnMobile !== 'right' && `${space[2]}px`};
65+
padding-right: ${imagePositionOnMobile !== 'left' && `${space[2]}px`};
66+
padding-top: ${imagePositionOnMobile !== 'bottom' && `${space[2]}px`};
67+
padding-bottom: ${imagePositionOnMobile !== 'top' && `${space[2]}px`};
68+
}
69+
${from.tablet} {
70+
padding-left: ${imagePositionOnDesktop !== 'right' && `${space[2]}px`};
71+
padding-right: ${imagePositionOnDesktop !== 'left' && `${space[2]}px`};
72+
padding-top: ${imagePositionOnDesktop !== 'bottom' && `${space[2]}px`};
73+
padding-bottom: ${imagePositionOnDesktop !== 'top' && `${space[2]}px`};
74+
}
75+
`;
76+
5677
/**
5778
* This function works in partnership with its sibling in `ContentWrapper`. If you
5879
* change any values here be sure to update that file as well.
@@ -123,10 +144,6 @@ const fixImageWidth = ({
123144
`}
124145
`;
125146

126-
const imagePadding = css`
127-
padding: ${space[2]}px;
128-
`;
129-
130147
export const ImageWrapper = ({
131148
children,
132149
imageSize,
@@ -180,7 +197,11 @@ export const ImageWrapper = ({
180197
display: block;
181198
}
182199
`,
183-
padImage && imagePadding,
200+
padImage &&
201+
imagePaddingStyles(
202+
imagePositionOnDesktop,
203+
imagePositionOnMobile,
204+
),
184205
]}
185206
>
186207
<>
@@ -191,7 +212,11 @@ export const ImageWrapper = ({
191212
<div
192213
css={[
193214
imageOverlayContainerStyles,
194-
padImage && imagePadding,
215+
padImage &&
216+
imagePaddingStyles(
217+
imagePositionOnDesktop,
218+
imagePositionOnMobile,
219+
),
195220
]}
196221
>
197222
{/* This child div is needed as the hover background colour covers the padded

0 commit comments

Comments
 (0)