Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Shopper Experience] ImageWithText component #991

Merged
merged 20 commits into from
Feb 24, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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({
bendvc marked this conversation as resolved.
Show resolved Hide resolved
_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()
})
58 changes: 58 additions & 0 deletions packages/template-retail-react-app/app/pages/experience/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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 {Box, Container} from '@chakra-ui/react'
import ImageWithText from '../../components/experience/image-with-text'

const 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'
}

// TODO: Example Page designer Test page. Remove before merging.
const Experience = () => {
return (
<Box bg="gray.50" py={[8, 16]}>
<Container
paddingTop={16}
width={['100%', '907px']}
bg="white"
paddingBottom={14}
marginTop={8}
marginBottom={8}
borderRadius="base"
>
<ImageWithText {...data} />
</Container>
</Box>
)
}

Experience.getTemplateName = () => 'experience'

Experience.propTypes = {}

export default Experience
7 changes: 7 additions & 0 deletions packages/template-retail-react-app/app/routes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ const LoginRedirect = loadable(() => import('./pages/login-redirect'), {fallback
const ProductDetail = loadable(() => import('./pages/product-detail'), {fallback})
const ProductList = loadable(() => import('./pages/product-list'), {fallback})
const Wishlist = loadable(() => import('./pages/account/wishlist'), {fallback})
// TODO: Example Page designer Test page. Remove before merging.
const Experience = loadable(() => import('./pages/experience'), {fallback})
const PageNotFound = loadable(() => import('./pages/page-not-found'))

const routes = [
Expand Down Expand Up @@ -98,6 +100,11 @@ const routes = [
path: '/account/wishlist',
component: Wishlist
},
// TODO: Example Page designer Test page. Remove before merging.
{
path: '/experience',
component: Experience
},
{
path: '*',
component: PageNotFound
Expand Down