diff --git a/app/soapbox/features/ads/components/ad.tsx b/app/soapbox/features/ads/components/ad.tsx index fd7209eed..1556d56e5 100644 --- a/app/soapbox/features/ads/components/ad.tsx +++ b/app/soapbox/features/ads/components/ad.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { FormattedMessage } from 'react-intl'; import { Stack, HStack, Card, Avatar, Text, Icon } from 'soapbox/components/ui'; @@ -19,8 +19,30 @@ interface IAd { const Ad: React.FC = ({ card, impression }) => { const instance = useAppSelector(state => state.instance); + const infobox = useRef(null); const [showInfo, setShowInfo] = useState(false); + /** Toggle the info box on click. */ + const handleInfoButtonClick: React.MouseEventHandler = () => { + setShowInfo(!showInfo); + }; + + /** Hide the info box when clicked outside. */ + const handleClickOutside = (event: MouseEvent) => { + if (event.target && infobox.current && !infobox.current.contains(event.target as any)) { + setShowInfo(false); + } + }; + + // Hide the info box when clicked outside. + // https://stackoverflow.com/a/42234988 + useEffect(() => { + document.addEventListener('mousedown', handleClickOutside); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, [infobox]); + // Fetch the impression URL (if any) upon displaying the ad. // It's common for ad providers to provide this. useEffect(() => { @@ -29,11 +51,6 @@ const Ad: React.FC = ({ card, impression }) => { } }, [impression]); - /** Toggle the info box on click. */ - const handleInfoButtonClick: React.MouseEventHandler = () => { - setShowInfo(!showInfo); - }; - return (
@@ -76,7 +93,7 @@ const Ad: React.FC = ({ card, impression }) => { {showInfo && ( -
+