-
-
Save brandonkal/088da2bf362cf23df58cb9e1f9c263ab to your computer and use it in GitHub Desktop.
useFocusTrap bug
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 from 'react' | |
import { storiesOf } from '@storybook/react' | |
// import '../../global.css' | |
// Mock out Button: | |
// import Button from '../Button' | |
import styled from '@emotion/styled' | |
const Button = styled.button`` | |
import Drawer, { Directions } from './Drawer' | |
function Demo() { | |
const [isOpen, setOpen] = React.useState(false) | |
const [direction, setDirection] = React.useState<Directions>('e') | |
const toggleDirection = () => { | |
const directions: Directions[] = ['n', 's', 'e', 'w'] | |
let index = directions.indexOf(direction) | |
index += 1 | |
if (!directions[index]) index = 0 | |
setDirection(directions[index]) | |
} | |
const handleClick = () => { | |
return setOpen(!isOpen) | |
} | |
React.useEffect(() => { | |
function handleEsc(event: any) { | |
console.log('Checking for escape key in demo') | |
if (event.key === 'Escape') { | |
setOpen(!isOpen) | |
} | |
} | |
document.addEventListener('keydown', handleEsc) | |
return () => { | |
document.removeEventListener('keydown', handleEsc) | |
} | |
}, [isOpen]) | |
return ( | |
<> | |
<p>{isOpen ? 'Opened' : 'Closed'}</p> | |
<Button onClick={handleClick}>Open Drawer</Button> | |
<input /> | |
<br /> | |
<Button onClick={toggleDirection}>Toggle Direction</Button> | |
{direction.toUpperCase()} | |
<Drawer | |
isOpen={isOpen} | |
position={direction} | |
style={{ | |
width: '50vw', | |
}} | |
> | |
<> | |
<input id="first" /> | |
<input /> | |
<p style={{ padding: '3rem' }}> | |
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne | |
merninisti licere mihi ista probare, quae sunt a te dicta? Refert | |
tamen, quo modo. | |
</p> | |
</> | |
</Drawer> | |
</> | |
) | |
} | |
storiesOf('Drawer', module).add('Basic', () => <Demo />) |
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 from 'react' | |
import { animated, useSpring, SpringConfig } from 'react-spring' | |
import { Portal } from '../Portal' | |
import useFocusTrap from '@charlietango/use-focus-trap' | |
import { RemoveScroll } from 'react-remove-scroll' | |
import { css } from '@emotion/core' | |
export type Directions = 'n' | 's' | 'e' | 'w' | |
interface DrawerProps { | |
style?: any | |
/** Whether the sheet is visible */ | |
isOpen: boolean | |
/** A callback to handle closing the sheet */ | |
onRequestClose?: () => void | |
role?: string | |
children: React.ReactNode | |
/** | |
* The compass position of the sheet. | |
* 'w' is typically used for navigation, | |
* 'e' for additional information, | |
* 's' for responsive modal popovers. | |
*/ | |
position?: Directions | |
closeOnClick?: boolean | |
/** spring animation configuration */ | |
animationConfig?: SpringConfig | |
} | |
export const Drawer = ({ | |
isOpen, | |
children, | |
role = 'document', | |
closeOnClick = true, | |
animationConfig = { mass: 0.8, tension: 185, friction: 24 }, | |
position = 'e', | |
onRequestClose, | |
...props | |
}: DrawerProps) => { | |
const ref = useFocusTrap(isOpen) | |
const isNegative = position === 'w' || position === 'n' | |
const isSide = position === 'e' || position === 'w' | |
const opacity = useSpring({ | |
opacity: isOpen ? 1 : 0, | |
}) | |
// A spring which animates the sheet position | |
const { percent } = useSpring({ | |
percent: [isOpen ? 0 : isNegative ? -100 : 100], | |
config: animationConfig, | |
}) | |
return ( | |
<Portal> | |
<div | |
aria-hidden={!isOpen} | |
// onKeyDown={(e: React.KeyboardEvent) => { | |
// if (e.key === 'Escape') { | |
// e.stopPropagation() | |
// onRequestClose && onRequestClose() | |
// } | |
// }} | |
css={{ | |
bottom: 0, | |
left: 0, | |
overflow: 'auto', | |
width: '100vw', | |
height: '100vh', | |
pointerEvents: isOpen ? 'auto' : 'none', | |
zIndex: 999, | |
position: 'fixed', | |
content: "''", | |
right: 0, | |
top: 0, | |
WebkitTapHighlightColor: 'transparent', | |
}} | |
> | |
<animated.div | |
css={{ | |
touchAction: 'none', | |
position: 'absolute', | |
willChange: 'opacity', | |
top: 0, | |
left: 0, | |
pointerEvents: isOpen ? 'auto' : 'none', | |
right: 0, | |
bottom: 0, | |
background: 'rgba(33, 37, 41, 0.6) none repeat scroll 0% 0%', | |
}} | |
style={opacity} | |
/> | |
<animated.div | |
tabIndex={-1} | |
ref={ref} | |
className="Sheet" | |
onClick={e => { | |
e.stopPropagation() | |
}} | |
css={css` | |
will-change: transform; | |
outline: none; | |
z-index: 10; | |
opacity: 1; | |
/* max-width: 50vw; */ | |
position: fixed; | |
top: ${position !== 's' && 0}; | |
bottom: ${position !== 'n' && 0}; | |
left: ${position === 'w' && 0}; | |
right: ${position === 'e' && 0}; | |
height: ${isSide ? '100vh' : 'auto'}; | |
width: ${!isSide && '100%'}; | |
`} | |
style={{ | |
visibility: opacity.opacity.interpolate(o => | |
o === 0 ? 'hidden' : 'visible' | |
), | |
transform: percent.interpolate(percent => { | |
return isSide | |
? `translate3d(${percent}%, 0, 0)` | |
: `translate3d(0, ${percent}%, 0)` | |
}), | |
}} | |
// {...props} | |
> | |
{/* <RequestCloseContext.Provider value={onRequestClose}> */} | |
<RemoveScroll enabled={isOpen} forwardProps> | |
<div | |
className="Sheet__container" | |
css={{ | |
background: 'white none repeat scroll 0% 0%', | |
height: '100%', | |
}} | |
> | |
{children} | |
</div> | |
</RemoveScroll> | |
{/* </RequestCloseContext.Provider> */} | |
</animated.div> | |
</div> | |
</Portal> | |
) | |
} | |
export default Drawer |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment