From 254291218a1e4d806a404c3a6b3e5d63bb5b5a64 Mon Sep 17 00:00:00 2001 From: AndyEPhipps Date: Tue, 11 Oct 2022 18:58:06 +0100 Subject: [PATCH 1/6] Focal point props --- src/components/Atoms/Picture/Picture.js | 15 ++++-- .../SingleMessageDS/SingleMessageDs.js | 12 ++++- .../SingleMessageDS/SingleMessageDs.md | 50 +++++++++++++++++++ 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/components/Atoms/Picture/Picture.js b/src/components/Atoms/Picture/Picture.js index 4385d769e..238c77b67 100644 --- a/src/components/Atoms/Picture/Picture.js +++ b/src/components/Atoms/Picture/Picture.js @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import styled, { withTheme } from 'styled-components'; +import styled, { css, withTheme } from 'styled-components'; import PropTypes from 'prop-types'; import 'lazysizes'; @@ -25,6 +25,11 @@ const Image = styled.img` || (props.objectFit === 'cover' && 'cover') || (props.objectFit === 'contain' && 'contain')}; ${({ objectFit, objFitState }) => (objectFit !== 'none' && !objFitState) && 'visibility: hidden;'}; // Allows image to provide the container height, but make it invisible + + ${props => (props.objectFit === 'contain' && props.focalPointX && props.focalPointY) && css` + object-position: ${props.focalPointX} ${props.focalPointY}; + `} + `; /** Responsive Picture */ @@ -128,7 +133,9 @@ Picture.propTypes = { ]), width: PropTypes.string, height: PropTypes.string, - isBackgroundImage: PropTypes.bool + isBackgroundImage: PropTypes.bool, + focalPointX: PropTypes.string, + focalPointY: PropTypes.string }; Picture.defaultProps = { @@ -139,7 +146,9 @@ Picture.defaultProps = { width: '100%', height: 'auto', alt: '', - isBackgroundImage: false + isBackgroundImage: false, + focalPointX: '', + focalPointY: '' }; export default withTheme(Picture); diff --git a/src/components/Molecules/SingleMessageDS/SingleMessageDs.js b/src/components/Molecules/SingleMessageDS/SingleMessageDs.js index aadb8e773..f5fcefac6 100644 --- a/src/components/Molecules/SingleMessageDS/SingleMessageDs.js +++ b/src/components/Molecules/SingleMessageDS/SingleMessageDs.js @@ -27,6 +27,8 @@ const SingleMessageDs = ({ target, linkIcon, youTubeId, + focalPointX, + focalPointY, ...rest }) => { const [isOpen, setIsOpen] = useState(false); @@ -44,6 +46,8 @@ const SingleMessageDs = ({ objectFit="cover" width={width} height={height} + focalPointX={focalPointX} + focalPointY={focalPointY} /> ); @@ -187,7 +191,9 @@ SingleMessageDs.propTypes = { target: PropTypes.string, children: PropTypes.node.isRequired, linkIcon: PropTypes.node, - youTubeId: PropTypes.string + youTubeId: PropTypes.string, + focalPointX: PropTypes.string, + focalPointY: PropTypes.string }; SingleMessageDs.defaultProps = { @@ -203,7 +209,9 @@ SingleMessageDs.defaultProps = { width: '100%', height: '100%', linkIcon: null, - youTubeId: null + youTubeId: null, + focalPointX: '', + focalPointY: ',' }; export default SingleMessageDs; diff --git a/src/components/Molecules/SingleMessageDS/SingleMessageDs.md b/src/components/Molecules/SingleMessageDS/SingleMessageDs.md index 6d727e241..c720ced59 100644 --- a/src/components/Molecules/SingleMessageDS/SingleMessageDs.md +++ b/src/components/Molecules/SingleMessageDS/SingleMessageDs.md @@ -185,4 +185,54 @@ import Download from '../../Atoms/Icons/Download'; ; +``` + +## FocalPoint stuff + +```js +const defaultData = require('../../../styleguide/data/data').defaultData;import Text from '../../Atoms/Text/Text'; +import Link from '../../Atoms/Link/Link'; +import styled from 'styled-components'; +import spacing from '../../../theme/shared/spacing'; + +const Title = styled(Text)` + letter-spacing: 0.03em; + text-transform: uppercase; + margin: ${spacing('md')} 0; + @media ${({ theme }) => theme.breakpoint('small')} { + margin-bottom: ${spacing('m')}; + } +`; +
+ + + Heading Line 1 Heading Line 2 + + + Whatever you’ve got planned, the Sport Relief shop has everything you need + to get you looking your best while you’re raising some cash. Also + available in Sainsbury’s stores and online and in selected Argos stores. + + +
; ``` \ No newline at end of file From 29180f747ff618eb16dde27599b91f39c6e63e19 Mon Sep 17 00:00:00 2001 From: AndyEPhipps Date: Thu, 13 Oct 2022 09:28:29 +0100 Subject: [PATCH 2/6] Tweak percentage values to suit --- src/components/Atoms/Picture/Picture.js | 52 ++++++++----------- src/components/Atoms/Picture/Picture.style.js | 26 ++++++++++ .../SingleMessageDS/SingleMessageDs.js | 23 ++++---- .../SingleMessageDS/SingleMessageDs.md | 21 +++++--- .../SingleMessageDS/SingleMessageDs.style.js | 2 + src/styleguide/data/data.js | 11 +++- src/utils/focalPointCalc.js | 22 ++++++++ 7 files changed, 111 insertions(+), 46 deletions(-) create mode 100644 src/components/Atoms/Picture/Picture.style.js create mode 100644 src/utils/focalPointCalc.js diff --git a/src/components/Atoms/Picture/Picture.js b/src/components/Atoms/Picture/Picture.js index 238c77b67..7b5bdf03b 100644 --- a/src/components/Atoms/Picture/Picture.js +++ b/src/components/Atoms/Picture/Picture.js @@ -1,37 +1,14 @@ import React, { useEffect, useState } from 'react'; -import styled, { css, withTheme } from 'styled-components'; +import { withTheme } from 'styled-components'; import PropTypes from 'prop-types'; - +import focalPointCalc from '../../../utils/focalPointCalc'; import 'lazysizes'; import 'lazysizes/plugins/blur-up/ls.blur-up'; +import { Wrapper, Image } from './Picture.style'; // Transparent pixel png const IMAGE_FALLBACK = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; -const Wrapper = styled.div` - ${({ objFitState, nonObjFitImage }) => (!objFitState && nonObjFitImage) && `background-image: url(${nonObjFitImage}); background-size: cover; background-position: center;`}; - display: block; - width: ${props => (props.width ? props.width : '100%')}; - height: ${props => (props.height ? props.height : '100%')}; - position: relative; - ${({ isBackgroundImage }) => isBackgroundImage && 'position: absolute; bottom: 0px; left: 0px; right: 0px; height: 100%;'}; - `; - -const Image = styled.img` - width: ${props => (props.width ? props.width : '100%')}; - height: ${props => (props.height ? props.height : 'auto')}; - display: block; - object-fit: ${props => (props.objectFit === 'none' && 'none') - || (props.objectFit === 'cover' && 'cover') - || (props.objectFit === 'contain' && 'contain')}; - ${({ objectFit, objFitState }) => (objectFit !== 'none' && !objFitState) && 'visibility: hidden;'}; // Allows image to provide the container height, but make it invisible - - ${props => (props.objectFit === 'contain' && props.focalPointX && props.focalPointY) && css` - object-position: ${props.focalPointX} ${props.focalPointY}; - `} - -`; - /** Responsive Picture */ const Picture = ({ @@ -43,6 +20,7 @@ const Picture = ({ objectFit, imageLow, isBackgroundImage, + focalPoint, ...rest }) => { const document = typeof window !== 'undefined' ? window.document : null; @@ -63,6 +41,8 @@ const Picture = ({ nonObjFitImage = images.substring(0, images.indexOf('?')); } + const calculatedFocalPoints = focalPointCalc(focalPoint); + if (!images) { return ( ); @@ -114,6 +96,8 @@ const Picture = ({ data-lowsrc={imageLow} className="lazyload" objFitState={objFitState} + focalPointXPos={calculatedFocalPoints.x} + focalPointYPos={calculatedFocalPoints.y} /> ); @@ -134,8 +118,12 @@ Picture.propTypes = { width: PropTypes.string, height: PropTypes.string, isBackgroundImage: PropTypes.bool, - focalPointX: PropTypes.string, - focalPointY: PropTypes.string + focalPoint: PropTypes.shape({ + focalPointX: PropTypes.number, + focalPointY: PropTypes.number, + rawImageWidth: PropTypes.number, + rawImageHeight: PropTypes.number + }) }; Picture.defaultProps = { @@ -147,8 +135,12 @@ Picture.defaultProps = { height: 'auto', alt: '', isBackgroundImage: false, - focalPointX: '', - focalPointY: '' + focalPoint: { + focalPointX: null, + focalPointY: null, + rawImageWidth: null, + rawImageHeigh: null + } }; export default withTheme(Picture); diff --git a/src/components/Atoms/Picture/Picture.style.js b/src/components/Atoms/Picture/Picture.style.js new file mode 100644 index 000000000..8d08af8f5 --- /dev/null +++ b/src/components/Atoms/Picture/Picture.style.js @@ -0,0 +1,26 @@ +import styled, { css } from 'styled-components'; + +const Wrapper = styled.div` + ${({ objFitState, nonObjFitImage }) => (!objFitState && nonObjFitImage) && `background-image: url(${nonObjFitImage}); background-size: cover; background-position: center;`}; + display: block; + width: ${props => (props.width ? props.width : '100%')}; + height: ${props => (props.height ? props.height : '100%')}; + position: relative; + ${({ isBackgroundImage }) => isBackgroundImage && 'position: absolute; bottom: 0px; left: 0px; right: 0px; height: 100%;'}; + `; + +const Image = styled.img` + width: ${props => (props.width ? props.width : '100%')}; + height: ${props => (props.height ? props.height : 'auto')}; + display: block; + object-fit: ${props => (props.objectFit === 'none' && 'none') + || (props.objectFit === 'cover' && 'cover') + || (props.objectFit === 'contain' && 'contain')}; + ${({ objectFit, objFitState }) => (objectFit !== 'none' && !objFitState) && 'visibility: hidden;'}; // Allows image to provide the container height, but make it invisible + + ${props => (props.objectFit === 'cover' && props.focalPointXPos && props.focalPointYPos) && css` + object-position: ${props.focalPointXPos} ${props.focalPointYPos}; + `} +`; + +export { Wrapper, Image }; diff --git a/src/components/Molecules/SingleMessageDS/SingleMessageDs.js b/src/components/Molecules/SingleMessageDS/SingleMessageDs.js index f5fcefac6..2b1dc9fc2 100644 --- a/src/components/Molecules/SingleMessageDS/SingleMessageDs.js +++ b/src/components/Molecules/SingleMessageDS/SingleMessageDs.js @@ -27,13 +27,11 @@ const SingleMessageDs = ({ target, linkIcon, youTubeId, - focalPointX, - focalPointY, + focalPoint, ...rest }) => { const [isOpen, setIsOpen] = useState(false); - // const openModal = () => setIsOpen(true); const closeModal = () => setIsOpen(false); const Media = ( @@ -46,8 +44,7 @@ const SingleMessageDs = ({ objectFit="cover" width={width} height={height} - focalPointX={focalPointX} - focalPointY={focalPointY} + focalPoint={focalPoint} /> ); @@ -192,8 +189,12 @@ SingleMessageDs.propTypes = { children: PropTypes.node.isRequired, linkIcon: PropTypes.node, youTubeId: PropTypes.string, - focalPointX: PropTypes.string, - focalPointY: PropTypes.string + focalPoint: PropTypes.shape({ + focalPointX: PropTypes.number, + focalPointY: PropTypes.number, + rawImageWidth: PropTypes.number, + rawImageHeight: PropTypes.number + }) }; SingleMessageDs.defaultProps = { @@ -210,8 +211,12 @@ SingleMessageDs.defaultProps = { height: '100%', linkIcon: null, youTubeId: null, - focalPointX: '', - focalPointY: ',' + focalPoint: { + focalPointX: null, + focalPointY: null, + rawImageWidth: null, + rawImageHeigh: null + } }; export default SingleMessageDs; diff --git a/src/components/Molecules/SingleMessageDS/SingleMessageDs.md b/src/components/Molecules/SingleMessageDS/SingleMessageDs.md index c720ced59..b42d2a3f7 100644 --- a/src/components/Molecules/SingleMessageDS/SingleMessageDs.md +++ b/src/components/Molecules/SingleMessageDS/SingleMessageDs.md @@ -190,11 +190,22 @@ import Download from '../../Atoms/Icons/Download'; ## FocalPoint stuff ```js -const defaultData = require('../../../styleguide/data/data').defaultData;import Text from '../../Atoms/Text/Text'; +const focalPointImages = require('../../../styleguide/data/data').focalPointImages; +import Text from '../../Atoms/Text/Text'; import Link from '../../Atoms/Link/Link'; import styled from 'styled-components'; import spacing from '../../../theme/shared/spacing'; +// These will come directly via the CMS query in the proper CRcom +// context; I've just hardcoded the actual size values from the example +// image and focal point that focuses on the subject's face +const exampleFocalPoint = { + rawImageWidth: 2000, + rawImageHeight: 945, + focalPointX: 1450, // middle of dog and woman + focalPointY: 350 +}; + const Title = styled(Text)` letter-spacing: 0.03em; text-transform: uppercase; @@ -215,15 +226,13 @@ const Title = styled(Text)` link='/home' linkLabel='Check out' backgroundColor='white' - imageLow={defaultData.image} - images={defaultData.images} + imageLow={focalPointImages.image} + images={focalPointImages.images} imageAltText='Happy man going to work' subtitle="Subtitle" height='100%' youTubeId='faz0JeBB41M' - focalPointX='50%' - focalPointY='50%' - + focalPoint={exampleFocalPoint} > Heading Line 1 Heading Line 2 diff --git a/src/components/Molecules/SingleMessageDS/SingleMessageDs.style.js b/src/components/Molecules/SingleMessageDS/SingleMessageDs.style.js index 5a434658c..a84eb9996 100644 --- a/src/components/Molecules/SingleMessageDS/SingleMessageDs.style.js +++ b/src/components/Molecules/SingleMessageDS/SingleMessageDs.style.js @@ -141,6 +141,8 @@ const Copy = styled.div` flex-shrink: 0; flex-basis: calc(50% + 1.5rem); padding: ${spacing('l')}; + // DEBUG + opacity: 0; ${({ hasLink }) => hasLink && `padding-bottom: calc(${spacing('l')} + ${spacing('m')})`}; diff --git a/src/styleguide/data/data.js b/src/styleguide/data/data.js index 41bda798e..fa47e3344 100644 --- a/src/styleguide/data/data.js +++ b/src/styleguide/data/data.js @@ -26,4 +26,13 @@ const mobileImages = { '//https://images.ctfassets.net/zsfivwzfgl3t/54DHIEgtwbr9TDkf70lToB/ffe8d6a8e9bbc224343f475a5c55c832/-CROP-Promo-Des_2000x945-_Kate.jpg?w=200&h=150&q=50 200w,//images.ctfassets.net/zsfivwzfgl3t/54DHIEgtwbr9TDkf70lToB/ffe8d6a8e9bbc224343f475a5c55c832/-CROP-Promo-Des_2000x945-_Kate.jpg?w=400&h=300&q=50 400w,//images.ctfassets.net/zsfivwzfgl3t/54DHIEgtwbr9TDkf70lToB/ffe8d6a8e9bbc224343f475a5c55c832/-CROP-Promo-Des_2000x945-_Kate.jpg?w=800&h=600&q=50 800w,//images.ctfassets.net/zsfivwzfgl3t/54DHIEgtwbr9TDkf70lToB/ffe8d6a8e9bbc224343f475a5c55c832/-CROP-Promo-Des_2000x945-_Kate.jpg?w=1200&h=900&q=50 1200w,//images.ctfassets.net/zsfivwzfgl3t/54DHIEgtwbr9TDkf70lToB/ffe8d6a8e9bbc224343f475a5c55c832/-CROP-Promo-Des_2000x945-_Kate.jpg?w=1440&h=1080&q=50 1440w' }; -export { defaultData, mobileImages }; +const focalPointImages = { + imageLow: + 'http://images.ctfassets.net/zsfivwzfgl3t/54DHIEgtwbr9TDkf70lToB/ffe8d6a8e9bbc224343f475a5c55c832/-CROP-Promo-Des_2000x945-_Kate.jpg?w=100&h=50&q=100', + image: + 'https://images.ctfassets.net/zsfivwzfgl3t/54DHIEgtwbr9TDkf70lToB/ffe8d6a8e9bbc224343f475a5c55c832/-CROP-Promo-Des_2000x945-_Kate.jpg', + images: + '//https://images.ctfassets.net/zsfivwzfgl3t/54DHIEgtwbr9TDkf70lToB/ffe8d6a8e9bbc224343f475a5c55c832/-CROP-Promo-Des_2000x945-_Kate.jpg?w=200&h=150&q=50 200w,//images.ctfassets.net/zsfivwzfgl3t/54DHIEgtwbr9TDkf70lToB/ffe8d6a8e9bbc224343f475a5c55c832/-CROP-Promo-Des_2000x945-_Kate.jpg?w=400&h=300&q=50 400w,//images.ctfassets.net/zsfivwzfgl3t/54DHIEgtwbr9TDkf70lToB/ffe8d6a8e9bbc224343f475a5c55c832/-CROP-Promo-Des_2000x945-_Kate.jpg?w=800&h=600&q=50 800w,//images.ctfassets.net/zsfivwzfgl3t/54DHIEgtwbr9TDkf70lToB/ffe8d6a8e9bbc224343f475a5c55c832/-CROP-Promo-Des_2000x945-_Kate.jpg?w=1200&h=900&q=50 1200w,//images.ctfassets.net/zsfivwzfgl3t/54DHIEgtwbr9TDkf70lToB/ffe8d6a8e9bbc224343f475a5c55c832/-CROP-Promo-Des_2000x945-_Kate.jpg?w=1440&h=1080&q=50 1440w' +}; + +export { defaultData, mobileImages, focalPointImages }; diff --git a/src/utils/focalPointCalc.js b/src/utils/focalPointCalc.js new file mode 100644 index 000000000..5309dddbf --- /dev/null +++ b/src/utils/focalPointCalc.js @@ -0,0 +1,22 @@ +// A handy to make the percentage math nice and reusable +const focalPointCalc = focalPointData => { + // Calculate the focal point as a percentage of the image dimension + let x = Math.round((focalPointData.focalPointX / focalPointData.rawImageWidth) * 100); + let y = Math.round((focalPointData.focalPointY / focalPointData.rawImageHeight) * 100); + + // Some ugly maths to basically just sweetenen to percentage, resulting + // in a slightly higher value (* 1.1) around the 25% and 75% points + // to get the position close to what we actually want visually + x *= (0.1 / 25) * (25 - Math.abs((x % (2 * 25)) - 25)) + 1; + y *= (0.1 / 25) * (25 - Math.abs((y % (2 * 25)) - 25)) + 1; + + // Return this directly as a percentage to be used within CSS; + // hard pixel values won't ever work, given the object-fit: contains + // rule and fluid layout + return { + x: `${x}%`, + y: `${y}%` + }; +}; + +export default focalPointCalc; From 0528136787b69d7759090ba5dc6cdcc69e80a2cc Mon Sep 17 00:00:00 2001 From: AndyEPhipps <a.phipps@comicrelief.com> Date: Thu, 13 Oct 2022 10:03:03 +0100 Subject: [PATCH 3/6] Better comments --- src/utils/focalPointCalc.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/utils/focalPointCalc.js b/src/utils/focalPointCalc.js index 5309dddbf..3c6804a4f 100644 --- a/src/utils/focalPointCalc.js +++ b/src/utils/focalPointCalc.js @@ -1,18 +1,18 @@ -// A handy to make the percentage math nice and reusable +/* A handy to make the percentage math nice and reusable */ const focalPointCalc = focalPointData => { - // Calculate the focal point as a percentage of the image dimension + // Calculate the focal points as percentages of the image dimensions let x = Math.round((focalPointData.focalPointX / focalPointData.rawImageWidth) * 100); let y = Math.round((focalPointData.focalPointY / focalPointData.rawImageHeight) * 100); - // Some ugly maths to basically just sweetenen to percentage, resulting - // in a slightly higher value (* 1.1) around the 25% and 75% points - // to get the position close to what we actually want visually + // Some ugly maths to basically just sweetenen the percentage, resulting + // in a slightly higher value (up to * 1.1 around the 25% and 75% points) + // to get the position close to what we actually want visually with our + // fluid layout and 'cover' object-fit CSS rule x *= (0.1 / 25) * (25 - Math.abs((x % (2 * 25)) - 25)) + 1; y *= (0.1 / 25) * (25 - Math.abs((y % (2 * 25)) - 25)) + 1; // Return this directly as a percentage to be used within CSS; - // hard pixel values won't ever work, given the object-fit: contains - // rule and fluid layout + // hard pixel values won't ever work, given that fluid layout return { x: `${x}%`, y: `${y}%` From 70cec58071f62f91765e86cc199f0747c3871eda Mon Sep 17 00:00:00 2001 From: AndyEPhipps <a.phipps@comicrelief.com> Date: Thu, 13 Oct 2022 10:21:26 +0100 Subject: [PATCH 4/6] Update snaps --- src/components/Atoms/Picture/Picture.test.js | 21 ++++++++++++------- .../ArticleTeaser/ArticleTeaser.test.js | 16 +++++++------- .../Card/__snapshots__/Card.test.js.snap | 1 + .../CardDs/__snapshots__/CardDs.test.js.snap | 1 + .../Promo/__snapshots__/Promo.test.js.snap | 2 ++ .../__snapshots__/SingleMessage.test.js.snap | 5 +++++ .../SingleMessageDs.test.js.snap | 2 ++ 7 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/components/Atoms/Picture/Picture.test.js b/src/components/Atoms/Picture/Picture.test.js index 7a7ef0079..63f472a40 100644 --- a/src/components/Atoms/Picture/Picture.test.js +++ b/src/components/Atoms/Picture/Picture.test.js @@ -1,11 +1,15 @@ -import React from 'react'; -import 'jest-styled-components'; -import renderWithTheme from '../../../hoc/shallowWithTheme'; -import Picture from './Picture'; -import { defaultData } from '../../../styleguide/data/data'; -it('renders correctly', () => { +import React from "react"; +import "jest-styled-components"; +import renderWithTheme from "../../../hoc/shallowWithTheme"; +import Picture from "./Picture"; +import { defaultData } from "../../../styleguide/data/data"; +it("renders correctly", () => { const tree = renderWithTheme( - <Picture images={defaultData.images} image={defaultData.image} alt="Test images" /> + <Picture + images={defaultData.images} + image={defaultData.image} + alt="Test images" + /> ).toJSON(); expect(tree).toMatchInlineSnapshot(` @@ -44,7 +48,7 @@ it('renders correctly', () => { `); }); -it('renders correctly with custom props', () => { +it("renders correctly with custom props", () => { const tree = renderWithTheme( <Picture images={defaultData.images} @@ -69,6 +73,7 @@ it('renders correctly with custom props', () => { height: 100px; display: block; object-fit: cover; + object-position: NaN% NaN%; } <div diff --git a/src/components/Molecules/ArticleTeaser/ArticleTeaser.test.js b/src/components/Molecules/ArticleTeaser/ArticleTeaser.test.js index 47528f69b..e31da2e69 100644 --- a/src/components/Molecules/ArticleTeaser/ArticleTeaser.test.js +++ b/src/components/Molecules/ArticleTeaser/ArticleTeaser.test.js @@ -1,9 +1,9 @@ -import React from 'react'; -import 'jest-styled-components'; -import renderWithTheme from '../../../hoc/shallowWithTheme'; -import ArticleTeaser from './ArticleTeaser'; -import { defaultData } from '../../../styleguide/data/data'; -it('renders article teaser correctly', () => { +import React from "react"; +import "jest-styled-components"; +import renderWithTheme from "../../../hoc/shallowWithTheme"; +import ArticleTeaser from "./ArticleTeaser"; +import { defaultData } from "../../../styleguide/data/data"; +it("renders article teaser correctly", () => { const tree = renderWithTheme( <ArticleTeaser href="/test" @@ -53,6 +53,7 @@ it('renders article teaser correctly', () => { height: 100%; display: block; object-fit: cover; + object-position: NaN% NaN%; } .c1 { @@ -258,7 +259,7 @@ it('renders article teaser correctly', () => { `); }); -it('renders press realese correctly', () => { +it("renders press realese correctly", () => { const tree = renderWithTheme( <ArticleTeaser href="/test" @@ -305,6 +306,7 @@ it('renders press realese correctly', () => { height: 80px; display: block; object-fit: cover; + object-position: NaN% NaN%; } .c1 { diff --git a/src/components/Molecules/Card/__snapshots__/Card.test.js.snap b/src/components/Molecules/Card/__snapshots__/Card.test.js.snap index a43d1e642..e97070d1b 100644 --- a/src/components/Molecules/Card/__snapshots__/Card.test.js.snap +++ b/src/components/Molecules/Card/__snapshots__/Card.test.js.snap @@ -54,6 +54,7 @@ exports[`renders correctly with no body 1`] = ` height: 100%; display: block; object-fit: cover; + object-position: NaN% NaN%; } .c0 { diff --git a/src/components/Molecules/CardDs/__snapshots__/CardDs.test.js.snap b/src/components/Molecules/CardDs/__snapshots__/CardDs.test.js.snap index 7d0c2fb18..24cc4bc38 100644 --- a/src/components/Molecules/CardDs/__snapshots__/CardDs.test.js.snap +++ b/src/components/Molecules/CardDs/__snapshots__/CardDs.test.js.snap @@ -13,6 +13,7 @@ exports[`renders correctly 1`] = ` height: auto; display: block; object-fit: cover; + object-position: NaN% NaN%; } .c8 { diff --git a/src/components/Molecules/Promo/__snapshots__/Promo.test.js.snap b/src/components/Molecules/Promo/__snapshots__/Promo.test.js.snap index 0f12f43e0..1e94aab69 100644 --- a/src/components/Molecules/Promo/__snapshots__/Promo.test.js.snap +++ b/src/components/Molecules/Promo/__snapshots__/Promo.test.js.snap @@ -37,6 +37,7 @@ exports[`renders Promo correctly 1`] = ` height: 100%; display: block; object-fit: cover; + object-position: NaN% NaN%; } .c8 { @@ -278,6 +279,7 @@ exports[`renders Promo correctly end position 1`] = ` height: 100%; display: block; object-fit: cover; + object-position: NaN% NaN%; } .c8 { diff --git a/src/components/Molecules/SingleMessage/__snapshots__/SingleMessage.test.js.snap b/src/components/Molecules/SingleMessage/__snapshots__/SingleMessage.test.js.snap index 2135186af..cc8367312 100644 --- a/src/components/Molecules/SingleMessage/__snapshots__/SingleMessage.test.js.snap +++ b/src/components/Molecules/SingleMessage/__snapshots__/SingleMessage.test.js.snap @@ -22,6 +22,7 @@ exports[`renders Single Message with 100% vertical height image correctly 1`] = height: 100%; display: block; object-fit: cover; + object-position: NaN% NaN%; } .c0 { @@ -197,6 +198,7 @@ exports[`renders Single Message with Image correctly 1`] = ` height: 100%; display: block; object-fit: cover; + object-position: NaN% NaN%; } .c8 { @@ -411,6 +413,7 @@ exports[`renders Single Message with double image correctly 1`] = ` height: 100%; display: block; object-fit: cover; + object-position: NaN% NaN%; } .c0 { @@ -631,6 +634,7 @@ exports[`renders Single Message with full width correctly 1`] = ` height: 100%; display: block; object-fit: cover; + object-position: NaN% NaN%; } .c8 { @@ -859,6 +863,7 @@ exports[`renders Single Message with full width image and no text correctly 1`] height: 100%; display: block; object-fit: cover; + object-position: NaN% NaN%; } .c0 { diff --git a/src/components/Molecules/SingleMessageDS/__snapshots__/SingleMessageDs.test.js.snap b/src/components/Molecules/SingleMessageDS/__snapshots__/SingleMessageDs.test.js.snap index 202b8079c..2e59f296a 100644 --- a/src/components/Molecules/SingleMessageDS/__snapshots__/SingleMessageDs.test.js.snap +++ b/src/components/Molecules/SingleMessageDS/__snapshots__/SingleMessageDs.test.js.snap @@ -31,6 +31,7 @@ exports[`renders correctly 1`] = ` height: auto; display: block; object-fit: cover; + object-position: NaN% NaN%; } .c12 { @@ -214,6 +215,7 @@ exports[`renders correctly 1`] = ` -ms-flex-preferred-size: calc(50% + 1.5rem); flex-basis: calc(50% + 1.5rem); padding: 2rem; + opacity: 0; padding-bottom: calc(2rem + 1.5rem); margin: 2rem 0 1.5rem -1.5rem; } From a693c31fa0c6d861f9412b8b229fcacde7b8018b Mon Sep 17 00:00:00 2001 From: AndyEPhipps <a.phipps@comicrelief.com> Date: Thu, 13 Oct 2022 11:04:08 +0100 Subject: [PATCH 5/6] Remove debug style --- src/components/Molecules/SingleMessageDS/SingleMessageDs.md | 4 ++-- .../Molecules/SingleMessageDS/SingleMessageDs.style.js | 2 -- .../__snapshots__/SingleMessageDs.test.js.snap | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/Molecules/SingleMessageDS/SingleMessageDs.md b/src/components/Molecules/SingleMessageDS/SingleMessageDs.md index b42d2a3f7..b24cfdcf6 100644 --- a/src/components/Molecules/SingleMessageDS/SingleMessageDs.md +++ b/src/components/Molecules/SingleMessageDS/SingleMessageDs.md @@ -198,11 +198,11 @@ import spacing from '../../../theme/shared/spacing'; // These will come directly via the CMS query in the proper CRcom // context; I've just hardcoded the actual size values from the example -// image and focal point that focuses on the subject's face +// image and focal point that focuses on the subject. const exampleFocalPoint = { rawImageWidth: 2000, rawImageHeight: 945, - focalPointX: 1450, // middle of dog and woman + focalPointX: 1450, focalPointY: 350 }; diff --git a/src/components/Molecules/SingleMessageDS/SingleMessageDs.style.js b/src/components/Molecules/SingleMessageDS/SingleMessageDs.style.js index a84eb9996..5a434658c 100644 --- a/src/components/Molecules/SingleMessageDS/SingleMessageDs.style.js +++ b/src/components/Molecules/SingleMessageDS/SingleMessageDs.style.js @@ -141,8 +141,6 @@ const Copy = styled.div` flex-shrink: 0; flex-basis: calc(50% + 1.5rem); padding: ${spacing('l')}; - // DEBUG - opacity: 0; ${({ hasLink }) => hasLink && `padding-bottom: calc(${spacing('l')} + ${spacing('m')})`}; diff --git a/src/components/Molecules/SingleMessageDS/__snapshots__/SingleMessageDs.test.js.snap b/src/components/Molecules/SingleMessageDS/__snapshots__/SingleMessageDs.test.js.snap index 2e59f296a..e0bea3b90 100644 --- a/src/components/Molecules/SingleMessageDS/__snapshots__/SingleMessageDs.test.js.snap +++ b/src/components/Molecules/SingleMessageDS/__snapshots__/SingleMessageDs.test.js.snap @@ -215,7 +215,6 @@ exports[`renders correctly 1`] = ` -ms-flex-preferred-size: calc(50% + 1.5rem); flex-basis: calc(50% + 1.5rem); padding: 2rem; - opacity: 0; padding-bottom: calc(2rem + 1.5rem); margin: 2rem 0 1.5rem -1.5rem; } From ef7a2366235938ae49d65267f130e46b48111928 Mon Sep 17 00:00:00 2001 From: AndyEPhipps <a.phipps@comicrelief.com> Date: Thu, 13 Oct 2022 17:27:06 +0100 Subject: [PATCH 6/6] WIP --- .../SingleMessageDS/SingleMessageDs.md | 63 ++++++++++++++++++- src/styleguide/data/data.js | 13 +++- src/utils/focalPointCalc.js | 17 +++-- 3 files changed, 86 insertions(+), 7 deletions(-) diff --git a/src/components/Molecules/SingleMessageDS/SingleMessageDs.md b/src/components/Molecules/SingleMessageDS/SingleMessageDs.md index b24cfdcf6..bd979863a 100644 --- a/src/components/Molecules/SingleMessageDS/SingleMessageDs.md +++ b/src/components/Molecules/SingleMessageDS/SingleMessageDs.md @@ -187,7 +187,7 @@ import Download from '../../Atoms/Icons/Download'; </div>; ``` -## FocalPoint stuff +## FocalPoint example 1 ```js const focalPointImages = require('../../../styleguide/data/data').focalPointImages; @@ -228,7 +228,66 @@ const Title = styled(Text)` backgroundColor='white' imageLow={focalPointImages.image} images={focalPointImages.images} - imageAltText='Happy man going to work' + imageAltText='A woman and her hairy child' + subtitle="Subtitle" + height='100%' + youTubeId='faz0JeBB41M' + focalPoint={exampleFocalPoint} + > + <Title tag="h4" color="grey_dark" size="xl" family="Anton" weight="normal"> + Heading Line 1 Heading Line 2 + + + Whatever you’ve got planned, the Sport Relief shop has everything you need + to get you looking your best while you’re raising some cash. Also + available in Sainsbury’s stores and online and in selected Argos stores. + + +; +``` + +## FocalPoint example 2 + +```js +const focalPointImagesTwo = require('../../../styleguide/data/data').focalPointImagesTwo; +import Text from '../../Atoms/Text/Text'; +import Link from '../../Atoms/Link/Link'; +import styled from 'styled-components'; +import spacing from '../../../theme/shared/spacing'; + +// These will come directly via the CMS query in the proper CRcom +// context; I've just hardcoded the actual size values from the example +// image and focal point that focuses on the subject. +const exampleFocalPoint = { + rawImageWidth: 1872, + rawImageHeight: 686, + focalPointX: 440, // Tall skyscraper on the left + focalPointY: 240 +}; + +const Title = styled(Text)` + letter-spacing: 0.03em; + text-transform: uppercase; + margin: ${spacing('md')} 0; + @media ${({ theme }) => theme.breakpoint('small')} { + margin-bottom: ${spacing('m')}; + } +`; +
+ { // Calculate the focal points as percentages of the image dimensions - let x = Math.round((focalPointData.focalPointX / focalPointData.rawImageWidth) * 100); - let y = Math.round((focalPointData.focalPointY / focalPointData.rawImageHeight) * 100); + let x = (focalPointData.focalPointX / focalPointData.rawImageWidth) * 100; + let y = (focalPointData.focalPointY / focalPointData.rawImageHeight) * 100; // Some ugly maths to basically just sweetenen the percentage, resulting // in a slightly higher value (up to * 1.1 around the 25% and 75% points) // to get the position close to what we actually want visually with our // fluid layout and 'cover' object-fit CSS rule - x *= (0.1 / 25) * (25 - Math.abs((x % (2 * 25)) - 25)) + 1; - y *= (0.1 / 25) * (25 - Math.abs((y % (2 * 25)) - 25)) + 1; + + const maths = true; + + if (maths) { + x *= (0.1 / 25) * (25 - Math.abs((x % (2 * 25)) - 25)) + 1; + y *= (0.1 / 25) * (25 - Math.abs((y % (2 * 25)) - 25)) + 1; + } + + // Round-up for best browser compatibility + x = Math.round(x); + y = Math.round(y); // Return this directly as a percentage to be used within CSS; // hard pixel values won't ever work, given that fluid layout