Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

Drawer.tsx 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import React, { KeyboardEvent, ReactNode, useCallback } from 'react';
  2. import ReactFocusLock from 'react-focus-lock';
  3. import { makeStyles } from 'tss-react/mui';
  4. import { DRAWER_MAX_HEIGHT } from '../../constants';
  5. interface IProps {
  6. /**
  7. * The component(s) to be displayed within the drawer menu.
  8. */
  9. children: ReactNode;
  10. /**
  11. * Class name for custom styles.
  12. */
  13. className?: string;
  14. /**
  15. * The id of the dom element acting as the Drawer label.
  16. */
  17. headingId?: string;
  18. /**
  19. * Whether the drawer should be shown or not.
  20. */
  21. isOpen: boolean;
  22. /**
  23. * Function that hides the drawer.
  24. */
  25. onClose?: Function;
  26. }
  27. const useStyles = makeStyles()(theme => {
  28. return {
  29. drawer: {
  30. backgroundColor: theme.palette.ui01,
  31. maxHeight: `calc(${DRAWER_MAX_HEIGHT})`,
  32. borderRadius: '24px 24px 0 0'
  33. }
  34. };
  35. });
  36. /**
  37. * Component that displays the mobile friendly drawer on web.
  38. *
  39. * @returns {ReactElement}
  40. */
  41. function Drawer({
  42. children,
  43. className = '',
  44. headingId,
  45. isOpen,
  46. onClose
  47. }: IProps) {
  48. const { classes: styles } = useStyles();
  49. /**
  50. * Handles clicks within the menu, preventing the propagation of the click event.
  51. *
  52. * @param {Object} event - The click event.
  53. * @returns {void}
  54. */
  55. const handleInsideClick = useCallback(event => {
  56. event.stopPropagation();
  57. }, []);
  58. /**
  59. * Handles clicks outside of the menu, closing it, and also stopping further propagation.
  60. *
  61. * @param {Object} event - The click event.
  62. * @returns {void}
  63. */
  64. const handleOutsideClick = useCallback(event => {
  65. event.stopPropagation();
  66. onClose?.();
  67. }, [ onClose ]);
  68. /**
  69. * Handles pressing the escape key, closing the drawer.
  70. *
  71. * @param {KeyboardEvent<HTMLDivElement>} event - The keydown event.
  72. * @returns {void}
  73. */
  74. const handleEscKey = useCallback((event: KeyboardEvent<HTMLDivElement>) => {
  75. if (event.key === 'Escape') {
  76. event.preventDefault();
  77. event.stopPropagation();
  78. onClose?.();
  79. }
  80. }, [ onClose ]);
  81. return (
  82. isOpen ? (
  83. <div
  84. className = 'drawer-menu-container'
  85. onClick = { handleOutsideClick }
  86. onKeyDown = { handleEscKey }>
  87. <div
  88. className = { `drawer-menu ${styles.drawer} ${className}` }
  89. onClick = { handleInsideClick }>
  90. <ReactFocusLock
  91. lockProps = {{
  92. role: 'dialog',
  93. 'aria-modal': true,
  94. 'aria-labelledby': `#${headingId}`
  95. }}
  96. returnFocus = { true }>
  97. {children}
  98. </ReactFocusLock>
  99. </div>
  100. </div>
  101. ) : null
  102. );
  103. }
  104. export default Drawer;