Created
May 26, 2019 18:36
-
-
Save reneviering/96d89716c445d641ccf6ca8217b42787 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useEffect, useRef } from 'react'; | |
import { useBooleanState } from './useBooleanState'; | |
import { PopoverTrigger } from './PopoverTrigger'; | |
import { PopoverContent } from './PopoverContent'; | |
import { PopoverContext } from './PopoverContext'; | |
const ESC_KEY = 27; | |
const Popover = ({ children }) => { | |
const [isOpen, closePopover, togglePopover] = useBooleanState(false); | |
const containerRef = useRef(null); | |
useEffect(() => { | |
const handleKeydown = event => { | |
if (event.keyCode === ESC_KEY) { | |
closePopover(); | |
} | |
}; | |
const handleClick = event => { | |
const didClickHappenInsidePopover = | |
containerRef && containerRef.current.contains(event.target); | |
if (!didClickHappenInsidePopover) { | |
closePopover(); | |
} | |
}; | |
document.addEventListener('keydown', handleKeydown); | |
document.addEventListener('click', handleClick); | |
return () => { | |
document.removeEventListener('keydown', handleKeydown); | |
document.removeEventListener('click', handleClick); | |
}; | |
}, [closePopover]); | |
return ( | |
<PopoverContext.Provider value={{ isOpen, closePopover, togglePopover }}> | |
<div ref={containerRef}>{children}</div> | |
</PopoverContext.Provider> | |
); | |
}; | |
const PopoverExample = () => { | |
return ( | |
<Popover> | |
<PopoverTrigger> | |
<button>Filter</button> | |
</PopoverTrigger> | |
<PopoverContent> | |
<div> | |
<button>asdflkjasdlfkj</button> | |
</div> | |
</PopoverContent> | |
</Popover> | |
); | |
}; | |
export { PopoverExample as Popover }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useContext } from 'react'; | |
import { PopoverContext } from '../PopoverContext'; | |
export const PopoverContent = ({ children }) => { | |
const popoverContext = useContext(PopoverContext); | |
if (!popoverContext) { | |
throw new Error('Do not use PopoverContent without Popover Provider'); | |
} | |
const { isOpen } = popoverContext; | |
if (!isOpen) return null; | |
return <div>{children}</div>; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useContext } from 'react'; | |
import { PopoverContext } from '../PopoverContext'; | |
export const PopoverTrigger = ({ children }) => { | |
const popoverContext = useContext(PopoverContext); | |
if (!popoverContext) { | |
throw new Error('Do not use PopoverContent without Popover Provider'); | |
} | |
const { togglePopover } = popoverContext; | |
return <div onClick={togglePopover}>{children}</div>; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState } from 'react'; | |
/* Just a little hooks helper for boolean state */ | |
export const useBooleanState = defaultValue => { | |
const [state, setState] = useState(defaultValue); | |
const toggleState = () => { | |
const newState = !state; | |
setState(newState); | |
}; | |
const deactivate = newState => setState(false); | |
return [state, deactivate, toggleState]; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment