SidePanel.js 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import React from "react";
  2. import styled from "styled-components";
  3. import { useTranslation } from "react-i18next";
  4. const StyledSidePanel = styled.div`
  5. position: fixed;
  6. z-index: 10;
  7. ${({ position }) => (position === "right" ? "right: 0;" : "left: 0;")}
  8. top: 4em;
  9. bottom: 0em;
  10. background-color: var(--color-blueGrey);
  11. box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
  12. width: 25%;
  13. min-width: 280px;
  14. overflow-y: scroll;
  15. & .close {
  16. position: absolute;
  17. top: 5px;
  18. right: 10px;
  19. }
  20. transform: translateX(100%);
  21. transition: all 500ms cubic-bezier(0.4, 0, 0.2, 1);
  22. padding: 1em;
  23. ${({ open, position }) => {
  24. let start = -100;
  25. let end = 0;
  26. if (position === "right") {
  27. start = 100;
  28. }
  29. return open
  30. ? `transform: translateX(${end}%);`
  31. : `transform: translateX(${start}%);`;
  32. }}
  33. ${({ open }) => (open ? "opacity: 1;" : "opacity: 0.2;")}
  34. `;
  35. const SidePanel = ({ children, position, onClose = () => {} }) => {
  36. const { t } = useTranslation();
  37. const [open, setOpen] = React.useState(false);
  38. React.useEffect(() => {
  39. setOpen(true);
  40. }, []);
  41. const onCloseHandler = React.useCallback(() => {
  42. setOpen(false);
  43. }, []);
  44. const onAnimationEnd = React.useCallback(() => {
  45. if (!open) {
  46. onClose();
  47. }
  48. }, [onClose, open]);
  49. return (
  50. <StyledSidePanel
  51. position={position}
  52. open={open}
  53. onTransitionEnd={onAnimationEnd}
  54. >
  55. <button className="button clear icon-only close" onClick={onCloseHandler}>
  56. <img
  57. src="https://icongr.am/feather/x.svg?size=30&color=ffffff"
  58. alt={t("Close")}
  59. />
  60. </button>
  61. {children}
  62. </StyledSidePanel>
  63. );
  64. };
  65. export default SidePanel;