FeatureHighlight.jsx (2851B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 import React, { useState, useCallback, useRef, useEffect } from "react"; 6 import { actionCreators as ac } from "common/Actions.mjs"; 7 8 export function FeatureHighlight({ 9 message, 10 icon, 11 toggle, 12 arrowPosition = "", 13 position = "top-left", 14 verticalPosition = "", 15 title, 16 ariaLabel, 17 feature = "FEATURE_HIGHLIGHT_DEFAULT", 18 dispatch = () => {}, 19 windowObj = global, 20 openedOverride = false, 21 showButtonIcon = true, 22 dismissCallback = () => {}, 23 outsideClickCallback = () => {}, 24 modalClassName = "", 25 }) { 26 const [opened, setOpened] = useState(openedOverride); 27 const ref = useRef(null); 28 29 useEffect(() => { 30 const handleOutsideClick = e => { 31 if (!ref?.current?.contains(e.target)) { 32 setOpened(false); 33 outsideClickCallback(); 34 } 35 }; 36 37 const handleKeyDown = e => { 38 if (e.key === "Escape") { 39 outsideClickCallback(); 40 } 41 }; 42 43 windowObj.document.addEventListener("click", handleOutsideClick); 44 windowObj.document.addEventListener("keydown", handleKeyDown); 45 return () => { 46 windowObj.document.removeEventListener("click", handleOutsideClick); 47 windowObj.document.removeEventListener("keydown", handleKeyDown); 48 }; 49 }, [windowObj, outsideClickCallback]); 50 51 const onToggleClick = useCallback(() => { 52 if (!opened) { 53 dispatch( 54 ac.DiscoveryStreamUserEvent({ 55 event: "CLICK", 56 source: "FEATURE_HIGHLIGHT", 57 value: { 58 feature, 59 }, 60 }) 61 ); 62 } 63 setOpened(!opened); 64 }, [dispatch, feature, opened]); 65 66 const onDismissClick = useCallback(() => { 67 setOpened(false); 68 dismissCallback(); 69 }, [dismissCallback]); 70 71 const hideButtonClass = showButtonIcon ? `` : `isHidden`; 72 const openedClassname = opened ? `opened` : `closed`; 73 return ( 74 <div ref={ref} className={`feature-highlight ${verticalPosition}`}> 75 <button 76 title={title} 77 aria-haspopup="true" 78 aria-label={ariaLabel} 79 className={`toggle-button ${hideButtonClass}`} 80 onClick={onToggleClick} 81 > 82 {toggle} 83 </button> 84 <div 85 className={`feature-highlight-modal ${position} ${arrowPosition} ${modalClassName} ${openedClassname}`} 86 > 87 <div className="message-icon">{icon}</div> 88 <p className="content-wrapper">{message}</p> 89 <moz-button 90 type="icon ghost" 91 size="small" 92 data-l10n-id="feature-highlight-dismiss-button" 93 iconsrc="chrome://global/skin/icons/close.svg" 94 onClick={onDismissClick} 95 onKeyDown={onDismissClick} 96 /> 97 </div> 98 </div> 99 ); 100 }