Skip to content

Instantly share code, notes, and snippets.

@methyl
Created March 14, 2022 19:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save methyl/57c8fbabfed8bca0136b2168aea1a14f to your computer and use it in GitHub Desktop.
Save methyl/57c8fbabfed8bca0136b2168aea1a14f to your computer and use it in GitHub Desktop.
Capture clicks in iframe but pass on :focus and :hover to the underlying element
const Demo = () => {
const handleTriggerRef = (el) => {
if (el == null) {
return
}
rect == null && setRect(el.getBoundingClientRect())
el.setAttribute('inert', '')
const anyDescendantMatches = (selectorText) =>
Array.from(el.querySelectorAll('*')).some((descendant: HTMLElement) =>
descendant.matches(selectorText),
)
Array.from(document.styleSheets).forEach((stylesheet) =>
Array.from(stylesheet.cssRules).forEach((rule: CSSStyleRule) => {
if (
rule.selectorText &&
rule.selectorText.includes(':hover') &&
anyDescendantMatches(rule.selectorText.replaceAll(':hover', ''))
) {
stylesheet.insertRule(
`.hddlr-trigger-hover ${rule.cssText.replaceAll(':hover', '')}`,
0,
)
}
if (
rule.selectorText &&
rule.selectorText.includes(':focus') &&
anyDescendantMatches(rule.selectorText.replaceAll(':focus', ''))
) {
stylesheet.insertRule(
`.hddlr-trigger-focus ${rule.cssText.replaceAll(':focus', '')}`,
0,
)
}
}),
)
}
const [isHovering, setIsHovering] = useState(false)
const handleMouseEnter = useCallback(() => setIsHovering(true), [setIsHovering])
const handleMouseLeave = useCallback(() => setIsHovering(false), [setIsHovering])
const [isFocused, setIsFocused] = useState(false)
const handleFocus = useCallback(() => setIsFocused(true), [setIsFocused])
const handleBlur = useCallback(() => setIsFocused(false), [setIsFocused])
useEffect(() => {
const handler = (msg) => {
if (
msg.origin === 'https://iframe-origin.example.com' &&
msg.data.type === 'focus'
) {
handleFocus()
}
if (
msg.origin === 'https://iframe-origin.example.com' &&
msg.data.type === 'blur'
) {
handleBlur()
}
}
window.addEventListener('message', handler)
return () => window.removeEventListener('message', handler)
}, [handleFocus, handleBlur])
return
<div
style={{ position: 'relative' }}
className={`${isHovering ? 'hddlr-trigger-hover' : ''} ${
isFocused ? 'hddlr-trigger-focus' : ''
}`.trim()}
>
<div
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onFocus={handleFocus}
onBlur={handleBlur}
style={{
position: 'absolute',
top: 0,
bottom: 0,
width: '100%',
height: '100%',
zIndex: 1,
outline: 'none',
}}
>
{/* Clicks are captured by this iframe */}
<iframe
style={{ width: '100%', height: '100%' }}
allow="camera;microphone"
>
</iframe>
</div>
<div ref={handleTriggerRef}>
{props.children}
</div>
</div>
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment