AdBannerContextMenu.jsx (4514B)
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 3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 4 5 import React, { useState } from "react"; 6 import { actionCreators as ac } from "common/Actions.mjs"; 7 import { LinkMenu } from "../../LinkMenu/LinkMenu"; 8 9 /** 10 * A context menu for IAB banners (e.g. billboard, leaderboard). 11 * 12 * Note: MREC ad formats and sponsored stories share the context menu with 13 * other cards: make sure you also look at DSLinkMenu component 14 * to keep any updates to ad-related context menu items in sync. 15 * 16 * @param dispatch 17 * @param spoc 18 * @param position 19 * @param type 20 * @param showAdReporting 21 * @returns {Element} 22 * @class 23 */ 24 export function AdBannerContextMenu({ 25 dispatch, 26 spoc, 27 position, 28 type, 29 showAdReporting, 30 toggleActive = () => {}, 31 }) { 32 const ADBANNER_CONTEXT_MENU_OPTIONS = [ 33 "BlockAdUrl", 34 ...(showAdReporting ? ["ReportAd"] : []), 35 "ManageSponsoredContent", 36 "OurSponsorsAndYourPrivacy", 37 ]; 38 39 const [showContextMenu, setShowContextMenu] = useState(false); 40 const [contextMenuClassNames, setContextMenuClassNames] = 41 useState("ads-context-menu"); 42 43 // The keyboard access parameter is passed down to LinkMenu component 44 // that uses it to focus on the first context menu option for accessibility. 45 const [isKeyboardAccess, setIsKeyboardAccess] = useState(false); 46 47 /** 48 * Toggles the style fix for context menu hover/active styles. 49 * This allows us to have unobtrusive, transparent button background by default, 50 * yet flip it over to semi-transparent grey when the menu is visible. 51 * 52 * @param contextMenuOpen 53 */ 54 const toggleContextMenuStyleSwitch = contextMenuOpen => { 55 if (contextMenuOpen) { 56 setContextMenuClassNames("ads-context-menu context-menu-open"); 57 } else { 58 setContextMenuClassNames("ads-context-menu"); 59 } 60 }; 61 62 /** 63 * Toggles the context menu to open or close. Sets state depending on whether 64 * the context menu is accessed by mouse or keyboard. 65 * 66 * @param isKeyBoard 67 */ 68 const toggleContextMenu = isKeyBoard => { 69 toggleContextMenuStyleSwitch(!showContextMenu); 70 toggleActive(!showContextMenu); 71 setShowContextMenu(!showContextMenu); 72 setIsKeyboardAccess(isKeyBoard); 73 }; 74 75 const onClick = e => { 76 e.preventDefault(); 77 toggleContextMenu(false); 78 }; 79 80 const onKeyDown = e => { 81 if (e.key === "Enter" || e.key === " ") { 82 e.preventDefault(); 83 toggleContextMenu(true); 84 } 85 }; 86 87 const onUpdate = () => { 88 toggleContextMenuStyleSwitch(!showContextMenu); 89 toggleActive(!showContextMenu); 90 setShowContextMenu(!showContextMenu); 91 }; 92 93 return ( 94 <div className="ads-context-menu-wrapper"> 95 <div className={contextMenuClassNames}> 96 <moz-button 97 type="icon" 98 size="default" 99 data-l10n-id="newtab-menu-content-tooltip" 100 data-l10n-args={JSON.stringify({ 101 title: spoc.title || spoc.sponsor || spoc.alt_text, 102 })} 103 iconsrc="chrome://global/skin/icons/more.svg" 104 onClick={onClick} 105 onKeyDown={onKeyDown} 106 /> 107 {showContextMenu && ( 108 <LinkMenu 109 onUpdate={onUpdate} 110 dispatch={dispatch} 111 keyboardAccess={isKeyboardAccess} 112 options={ADBANNER_CONTEXT_MENU_OPTIONS} 113 shouldSendImpressionStats={true} 114 userEvent={ac.DiscoveryStreamUserEvent} 115 site={{ 116 // Props we want to pass on for new ad types that come from Unified Ads API 117 block_key: spoc.block_key, 118 fetchTimestamp: spoc.fetchTimestamp, 119 flight_id: spoc.flight_id, 120 format: spoc.format, 121 id: spoc.id, 122 guid: spoc.guid, 123 card_type: "spoc", 124 // required to record telemetry for an action, see handleBlockUrl in TelemetryFeed.sys.mjs 125 is_pocket_card: true, 126 position, 127 sponsor: spoc.sponsor, 128 title: spoc.title, 129 url: spoc.url || spoc.shim.url, 130 personalization_models: spoc.personalization_models, 131 priority: spoc.priority, 132 score: spoc.score, 133 alt_text: spoc.alt_text, 134 shim: spoc.shim, 135 }} 136 index={position} 137 source={type.toUpperCase()} 138 /> 139 )} 140 </div> 141 </div> 142 ); 143 }