Skip to content

Commit

Permalink
[Shopper Experience] ImageWithText component (#991)
Browse files Browse the repository at this point in the history
* init `ImageWithText` component

* Add more ImageWithText props

* Remove HTML paragraph tag from text

* Sanitize HTML

* Add `dompurify` to template-retail-react-app

* Replace `dompurify` with `sanitize-html` ready for ssr

* Revert "Replace `dompurify` with `sanitize-html` ready for ssr"

This reverts commit 231183a.

* bump bundle size

* Add styles and basic test

* Adjust text styles

* Update packages/template-retail-react-app/app/components/experience/image-with-text/index.jsx

Co-authored-by: Ben Chypak <[email protected]>

* PR Feedback

* Use Chakra UI components over native HTML elements

* Update CHANGELOG.md

* Remove DOMPurify

* Remove example page

---------

Co-authored-by: Ben Chypak <[email protected]>
  • Loading branch information
adamraya and bendvc authored Feb 24, 2023
1 parent cfa5811 commit 572407b
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 3 deletions.
3 changes: 3 additions & 0 deletions packages/template-retail-react-app/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
## v2.7.0-dev (Jan 25, 2023)
- Add Page Designer ImageTile component [#967](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/967)
- Add Page Designer ImageWithText component [#991](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/991)
- Add Page Designer carousel component [#977](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/977)
- Add Page Designer layout components [#993](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/993)

## v2.6.0 (Jan 25, 2023)
- Mega menu fixes [#875](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/875) and [#910](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/910)
- Cache SLAS callback using request processor [#884](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/884)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/
import React from 'react'
import PropTypes from 'prop-types'
import {Image} from '@chakra-ui/react'
import {Box, Image} from '@chakra-ui/react'

/**
* Simple ImageTile component that can be used inside any Layout component.
Expand All @@ -15,7 +15,7 @@ import {Image} from '@chakra-ui/react'
*/
const ImageTile = ({image}) => {
return (
<div className={'image-tile'}>
<Box className={'image-tile'}>
<figure className={'image-tile-figure'}>
<picture>
<source srcSet={image?.src?.tablet} media="(min-width: 48em)" />
Expand All @@ -30,7 +30,7 @@ const ImageTile = ({image}) => {
/>
</picture>
</figure>
</div>
</Box>
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* Copyright (c) 2023, Salesforce, Inc.
* All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import React from 'react'
import PropTypes from 'prop-types'
import {Box, Image, Link, Text} from '@chakra-ui/react'

/**
* Image with text component
*
* @param {object} props
* @param {string} - props.ITCLink - Image Link.
* @param {string} - props.ITCText - Text Below Image.
* @param {image} - props.image - Image.
* @param {string} - props.heading - Text Overlay.
* @param {string} - props.alt - The image alt text shown by the component.
* @returns {React.ReactElement} - ImageWithText component.
*/
const ImageWithText = ({ITCLink, ITCText, image, heading, alt}) => {
const hasCaption = ITCText || heading

return (
<Box className={'image-with-text'}>
<Box
as="figure"
className={'image-with-text-figure'}
position={'relative'}
margin={0}
width={'100%'}
>
<picture>
<source srcSet={image?.src?.tablet} media="(min-width: 48em)" />
<source srcSet={image?.src?.desktop} media="(min-width: 64em)" />
<Link to={ITCLink}>
<Image
className={'image-with-text-image'}
data-testid={'image-with-text-image'}
src={image?.src?.mobile ? image?.src?.mobile : image?.url}
ignoreFallback={true}
alt={alt}
title={alt}
filter={'brightness(40%)'}
/>
</Link>
</picture>
{hasCaption && (
<Text as="figcaption">
{heading && (
<Box
className={'image-with-text-heading-container'}
position={'absolute'}
top={'50%'}
width={'100%'}
>
<Text
as="span"
className={'image-with-text-heading-text'}
color={'white'}
>
{/* The `dangerouslySetInnerHTML` is safe to use in this context. */}
{/* The HTML in the response from Page Designer API is already sanitized. */}
<Box
dangerouslySetInnerHTML={{
__html: heading
}}
sx={{
p: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}
}}
/>
</Text>
</Box>
)}
{ITCText && (
<Box>
<Text as="span" className={'image-with-text-text-underneath'}>
{/* The `dangerouslySetInnerHTML` is safe to use in this context. */}
{/* The HTML in the response from Page Designer API is already sanitized. */}
<Box
dangerouslySetInnerHTML={{
__html: ITCText
}}
sx={{
p: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}
}}
/>
</Text>
</Box>
)}
</Text>
)}
</Box>
</Box>
)
}

ImageWithText.propTypes = {
ITCLink: PropTypes.string,
ITCText: PropTypes.string,
image: PropTypes.shape({
_type: PropTypes.string,
focalPoint: PropTypes.shape({
_type: PropTypes.string,
x: PropTypes.number,
y: PropTypes.number
}),
metaData: PropTypes.shape({
_type: PropTypes.string,
height: PropTypes.number,
width: PropTypes.number
}),
url: PropTypes.string,
src: PropTypes.string || PropTypes.object
}).isRequired,
heading: PropTypes.string,
alt: PropTypes.string
}

export default ImageWithText
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2023, Salesforce, Inc.
* All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import React from 'react'
import ImageWithText from './index'
import {renderWithProviders} from '../../../utils/test-utils'

const SAMPLE_DATA = {
ITCLink: 'https://salesforce.com',
ITCText:
'<p><em>Text</em> <strong>Below</strong> <u>Image</u> <s>test</s> Image With Text Component <a href="https://zzrf-001.dx.commercecloud.salesforce.com/s/RefArchGlobal/homepage-example.html?lang=en_US" target="_self" data-link-type="page" data-link-label="homepage-example" data-content-page-id="homepage-example">Home-page example link</a><img src="https://zzrf-001.dx.commercecloud.salesforce.com/on/demandware.static/-/Library-Sites-RefArchSharedLibrary/default/dw89c1031d/images/myaccount_addresses.png" alt="alt tag myaccount_addresses image"></p>',
image: {
_type: 'Image',
focalPoint: {
_type: 'Imagefocalpoint',
x: 0.5,
y: 0.5
},
metaData: {
_type: 'Imagemetadata',
height: 1280,
width: 1920
},
url: 'https://zzrf-001.dx.commercecloud.salesforce.com/on/demandware.static/-/Library-Sites-RefArchSharedLibrary/default/dw34c389b5/images/SearchBanner/search.jpg'
},
heading:
'<p><em>Text</em> <strong>Overlay</strong> <s>test</s> <u>Image</u> With Text <a href="https://zzrf-001.dx.commercecloud.salesforce.com/s/RefArchGlobal/mens/?lang=en_US" target="_self" data-link-type="category" data-link-label="Mens" data-category-id="mens" data-category-catalog-id="storefront-catalog-m-en">Component Link</a><img src="https://zzrf-001.dx.commercecloud.salesforce.com/on/demandware.static/-/Library-Sites-RefArchSharedLibrary/default/dw2d9142bf/images/myaccount_registry.png" alt="alt text myaccount_registry image"></p>',
alt: 'Alt Text test Image With Text Component'
}

test('Page renders correct component', () => {
const {getByText} = renderWithProviders(<ImageWithText {...SAMPLE_DATA} />)

expect(getByText(/image with text component/i)).toBeInTheDocument()
})

0 comments on commit 572407b

Please sign in to comment.