Created
February 11, 2021 22:20
-
-
Save pucinsk/7b74c86098a8f35b2be9117ca9d5a244 to your computer and use it in GitHub Desktop.
React Material UI 'drawer-like' component which can be rendered from container.
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, { useMemo, forwardRef, useState, useEffect } from 'react' | |
import PropTypes from 'prop-types' | |
import { makeStyles, Paper, Slide, ClickAwayListener } from '@material-ui/core' | |
const useStyles = makeStyles(function (theme) { | |
return ( | |
{ | |
root: { | |
backgroundColor: theme.palette.background.paper, | |
flexGrow: 1, | |
display: 'flex', | |
} | |
} | |
) | |
}) | |
const AwesomeDrawer = function ({ direction, open, setOpen, ariaLabel, children }) { | |
const classes = useStyles() | |
const Slider = function (sliderProps, ref) { | |
return ( | |
<ClickAwayListener onClickAway={() => setOpen(false)}> | |
<Slide ref={ref} {...sliderProps} /> | |
</ClickAwayListener> | |
) | |
} | |
const AwesomeSlider = useMemo(function () { | |
return ( | |
forwardRef(Slider) | |
) | |
}) | |
useEffect(function() { | |
if (open) { | |
document.body.classList.add('overlay-visible') | |
document.documentElement.classList.add('overlay-visible') | |
} else { | |
document.body.classList.remove('overlay-visible') | |
document.documentElement.classList.remove('overlay-visible') | |
} | |
}, [open]) | |
return ( | |
<AwesomeSlider direction={direction} in={open} mountOnEnter unmountOnExit> | |
<Paper className={classes.root} id={ariaLabel}> | |
{children} | |
</Paper> | |
</AwesomeSlider> | |
) | |
} | |
AwesomeDrawer.propTypes = { | |
direction: PropTypes.oneOf(['left', 'right']), | |
open: PropTypes.bool, | |
ariaLabel: PropTypes.string.isRequired, | |
children: PropTypes.node, | |
} | |
AwesomeDrawer.defaultProps = { | |
direction: 'left', | |
open: false, | |
} | |
export const SliderProvider = (sliderTarget) => { | |
let open = false | |
const isOpen = function () { | |
return !!document.getElementById(sliderTarget) | |
} | |
const setOpen = function (newValue) { | |
open = newValue | |
notify() | |
} | |
let observers = [] | |
const subscribe = function (observer) { | |
observers.push(observer) | |
} | |
const unsubscribe = function (observer) { | |
observers = observers.filter(_observer => _observer !== observer) | |
} | |
const notify = function () { | |
observers.forEach(observer => observer(open)) | |
} | |
return ( | |
{ | |
setOpen, | |
isOpen, | |
subscribe, | |
unsubscribe, | |
} | |
) | |
} | |
export const useSlider = function (provider) { | |
const [isOpen, setIsOpen] = useState(provider.isOpen()) | |
useEffect(function () { | |
const listener = function (newIsOpen) { | |
setIsOpen(newIsOpen) | |
} | |
provider.subscribe(listener) | |
return function () { | |
provider.unsubscribe(listener) | |
} | |
}, []) | |
return [isOpen, setIsOpen] | |
} | |
export default AwesomeDrawer |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment