2

I have a component that blurs everything that is on the screen.

const SVGBlur = () => (
    <svg style={{position: 'absolute', top: '-99999px'}} xmlns="http://www.w3.org/2000/svg">
        <filter id="svgBlur" x="-5%" y="-5%" width="150%" height="150%">
            <feGaussianBlur in="SourceGraphic" stdDeviation={5}/>
        </filter>
    </svg>
)

const BlurOverlay = ({children}) => {
    const [domNode, setDomNode] = useState(null);

    useEffect(() => {
        const blurContainer = document.createElement('div')
        const childrenContainer = document.getElementById('root')
        const elementToApplyBlurTo = document.getElementById('blur-overlay')

        if (elementToApplyBlurTo && childrenContainer) {
            childrenContainer.appendChild(blurContainer)
            elementToApplyBlurTo.setAttribute('style', 'filter: url(#svgBlur); filter: blur(5px);')
            setDomNode(childrenContainer)
        }
        return () => {
            if (elementToApplyBlurTo && childrenContainer) {
                childrenContainer.removeChild(blurContainer)
                elementToApplyBlurTo.setAttribute('style', '')
            }
        }
    }, [])

    return domNode && ReactDOM.createPortal(
        <>
            {children}
            <SVGBlur />
        </>,
        domNode,
    )
}

export default BlurOverlay;

I want to be able to blurr everything and at the same time insert children that are on top of all the blurred stuff. Basically like a Modal on the backdrop. However, the children I am passing BlurOverlay are always blurred too, because they appear as children of root, but after the <div/> with id=blur-overlay;

This is the DOM before <BlurOverlay />

<div id='root'>
    <div className="App" id={'blur-overlay'}>
        ...
    </div>
</div>

And this is the order after creating the Portal

<div id='root'>
    <div className="App" id={'blur-overlay'}> <- BLUR STYLES APPLIED
        ...
    <div>THIS CONTAINS THE CHILDREN PASSED TO <BlurOverlay></div>
    <svg .../>
    </div>
</div>

In order for the children not to be blurred, they need to be here

<div id='root'>
    <div>THIS CONTAINS THE CHILDREN PASSED TO <BlurOverlay></div>
    <div className="App" id={'blur-overlay'}> <- BLUR STYLES APPLIED
        ...
    <svg .../>
    </div>
</div>

How to achieve that?

four-eyes
  • 10,740
  • 29
  • 111
  • 220

1 Answers1

0

how about use HTML <dialog> element directly?

yang zhou
  • 148
  • 6