diff --git a/packages/template-retail-react-app/app/components/header/index.jsx b/packages/template-retail-react-app/app/components/header/index.jsx index 1c7560a33d..6f447470a7 100644 --- a/packages/template-retail-react-app/app/components/header/index.jsx +++ b/packages/template-retail-react-app/app/components/header/index.jsx @@ -174,7 +174,11 @@ const Header = ({ {showLoading && } - + )} diff --git a/packages/template-retail-react-app/app/components/search/index.jsx b/packages/template-retail-react-app/app/components/search/index.jsx index 29d043737a..700db08b79 100644 --- a/packages/template-retail-react-app/app/components/search/index.jsx +++ b/packages/template-retail-react-app/app/components/search/index.jsx @@ -42,6 +42,7 @@ import { } from '@salesforce/retail-react-app/app/utils/url' import {getConfig} from '@salesforce/pwa-kit-runtime/utils/ssr-config' import {getCommerceAgentConfig} from '@salesforce/retail-react-app/app/utils/config-utils' +import {launchChat as launchChatFromUtils} from '@salesforce/retail-react-app/app/utils/shopper-agent-utils' import {useUsid} from '@salesforce/commerce-sdk-react' import {useLocation} from 'react-router-dom' import useRefreshToken from '@salesforce/retail-react-app/app/hooks/use-refresh-token' @@ -351,9 +352,11 @@ const Search = (props) => { } const onAskAssistantClick = useCallback(() => { - launchChat() + // When floating button is hidden (enableAgentFromFloatingButton false), show it first then launch + setPrechatFieldsForNewSession() + launchChatFromUtils() clearInput() - }, [launchChat, clearInput]) + }, [setPrechatFieldsForNewSession, clearInput]) const shouldOpenPopover = () => { // As per design we only want to show the popover if the input is focused and we have recent searches saved diff --git a/packages/template-retail-react-app/app/components/search/partials/ask-assistant-banner.jsx b/packages/template-retail-react-app/app/components/search/partials/ask-assistant-banner.jsx index e66dba3cf3..d8f85fb864 100644 --- a/packages/template-retail-react-app/app/components/search/partials/ask-assistant-banner.jsx +++ b/packages/template-retail-react-app/app/components/search/partials/ask-assistant-banner.jsx @@ -4,7 +4,7 @@ * 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 React, {useRef} from 'react' import PropTypes from 'prop-types' import {Box, Text} from '@salesforce/retail-react-app/app/components/shared/ui' import {useIntl} from 'react-intl' @@ -12,6 +12,7 @@ import {SparkleIcon, ChevronRightIcon} from '@salesforce/retail-react-app/app/co const AskAssistantBanner = ({onClick, styles}) => { const intl = useIntl() + const handledByTouchRef = useRef(false) const title = intl.formatMessage({ id: 'search.suggestions.askAssistant.title', defaultMessage: 'Ask Shopping Agent' @@ -27,13 +28,36 @@ const AskAssistantBanner = ({onClick, styles}) => { onClick?.() } + const handleTouchStart = (e) => { + // Prevent the search input from blurring when the user touches the banner. + // Otherwise onBlur closes the overlay before touchEnd/click fires, so the tap never runs. + e.preventDefault() + } + + const handleTouchEnd = () => { + handledByTouchRef.current = true + onClick?.() + setTimeout(() => { + handledByTouchRef.current = false + }, 400) + } + + const handleClick = (e) => { + if (handledByTouchRef.current) { + return + } + handleInteraction(e) + } + return ( diff --git a/packages/template-retail-react-app/app/theme/components/project/header.js b/packages/template-retail-react-app/app/theme/components/project/header.js index 6dbc2e19ff..61ed3fe9a0 100644 --- a/packages/template-retail-react-app/app/theme/components/project/header.js +++ b/packages/template-retail-react-app/app/theme/components/project/header.js @@ -24,7 +24,6 @@ export default { searchContainer: { order: [2, 2, 2, 'inherit'], width: ['full', 'full', 'full', 60], - marginRight: [0, 0, 0, 4], marginBottom: [1, 1, 2, 0] }, bodyContainer: { @@ -35,13 +34,9 @@ export default { height: [6, 6, 6, 8] }, icons: { - marginBottom: [1, 1, 2, 0] - }, - accountIcon: { height: 11, minWidth: 'auto', - cursor: 'pointer', - alignSelf: ['self-start', 'self-start', 'self-start', 'auto'], + marginBottom: [1, 1, 2, 0], _focus: { boxShadow: 'outline' }, @@ -49,23 +44,21 @@ export default { outline: 0 } }, + agentIcon: { + alignSelf: ['self-start', 'self-start', 'self-start', 'auto'] + }, + accountIcon: { + cursor: 'pointer', + alignSelf: ['self-start', 'self-start', 'self-start', 'auto'] + }, arrowDown: { - height: 11, - minWidth: 'auto', marginRight: 0, alignSelf: ['self-start', 'self-start', 'self-start', 'auto'], cursor: 'pointer', - _focus: { - boxShadow: 'outline' - }, - _focusVisible: { - outline: 0 - }, display: ['none', 'none', 'none', 'block'] }, wishlistIcon: { - // More breathing room between the account and wishlist icons - marginLeft: 2 + alignSelf: ['self-start', 'self-start', 'self-start', 'auto'] }, signout: { width: '100%', @@ -86,5 +79,15 @@ export default { marginRight: 2 } }, - parts: ['container', 'content', 'searchContainer', 'bodyContainer', 'logo', 'icons', 'signout'] + parts: [ + 'container', + 'content', + 'searchContainer', + 'bodyContainer', + 'logo', + 'icons', + 'agentIcon', + 'wishlistIcon', + 'signout' + ] }