You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Dialog.tsx 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import React, { useCallback } from 'react';
  2. import { useTranslation } from 'react-i18next';
  3. import { useDispatch } from 'react-redux';
  4. import { makeStyles } from 'tss-react/mui';
  5. import { hideDialog } from '../../../dialog/actions';
  6. import { IconCloseLarge } from '../../../icons/svg';
  7. import { withPixelLineHeight } from '../../../styles/functions.web';
  8. import BaseDialog, { IProps as IBaseDialogProps } from './BaseDialog';
  9. import Button from './Button';
  10. import ClickableIcon from './ClickableIcon';
  11. const useStyles = makeStyles()(theme => {
  12. return {
  13. header: {
  14. width: '100%',
  15. padding: '24px',
  16. boxSizing: 'border-box',
  17. display: 'flex',
  18. alignItems: 'flex-start',
  19. justifyContent: 'space-between'
  20. },
  21. closeIcon: {
  22. '&:focus': {
  23. boxShadow: 'none'
  24. }
  25. },
  26. title: {
  27. color: theme.palette.text01,
  28. ...withPixelLineHeight(theme.typography.heading5),
  29. margin: 0,
  30. padding: 0
  31. },
  32. content: {
  33. height: 'auto',
  34. overflowY: 'auto',
  35. width: '100%',
  36. boxSizing: 'border-box',
  37. padding: '0 24px',
  38. overflowX: 'hidden',
  39. minHeight: '40px',
  40. '@media (max-width: 448px)': {
  41. height: '100%'
  42. }
  43. },
  44. footer: {
  45. width: '100%',
  46. boxSizing: 'border-box',
  47. display: 'flex',
  48. alignItems: 'center',
  49. justifyContent: 'flex-end',
  50. padding: '24px',
  51. '& button:last-child': {
  52. marginLeft: '16px'
  53. }
  54. }
  55. };
  56. });
  57. interface IDialogProps extends IBaseDialogProps {
  58. back?: {
  59. hidden?: boolean;
  60. onClick?: () => void;
  61. translationKey?: string;
  62. };
  63. cancel?: {
  64. hidden?: boolean;
  65. translationKey?: string;
  66. };
  67. children?: React.ReactNode;
  68. disableAutoHideOnSubmit?: boolean;
  69. hideCloseButton?: boolean;
  70. ok?: {
  71. disabled?: boolean;
  72. hidden?: boolean;
  73. translationKey?: string;
  74. };
  75. onCancel?: () => void;
  76. onSubmit?: () => void;
  77. }
  78. const Dialog = ({
  79. back = { hidden: true },
  80. cancel = { translationKey: 'dialog.Cancel' },
  81. children,
  82. className,
  83. description,
  84. disableAutoHideOnSubmit = false,
  85. disableBackdropClose,
  86. hideCloseButton,
  87. disableEnter,
  88. ok = { translationKey: 'dialog.Ok' },
  89. onCancel,
  90. onSubmit,
  91. size,
  92. title,
  93. titleKey
  94. }: IDialogProps) => {
  95. const { classes } = useStyles();
  96. const { t } = useTranslation();
  97. const dispatch = useDispatch();
  98. const onClose = useCallback(() => {
  99. dispatch(hideDialog());
  100. onCancel?.();
  101. }, [ onCancel ]);
  102. const submit = useCallback(() => {
  103. !disableAutoHideOnSubmit && dispatch(hideDialog());
  104. onSubmit?.();
  105. }, [ onSubmit ]);
  106. return (
  107. <BaseDialog
  108. className = { className }
  109. description = { description }
  110. disableBackdropClose = { disableBackdropClose }
  111. disableEnter = { disableEnter }
  112. onClose = { onClose }
  113. size = { size }
  114. submit = { submit }
  115. title = { title }
  116. titleKey = { titleKey }>
  117. <div className = { classes.header }>
  118. <p
  119. className = { classes.title }
  120. id = 'dialog-title'>
  121. {title ?? t(titleKey ?? '')}
  122. </p>
  123. {!hideCloseButton && (
  124. <ClickableIcon
  125. accessibilityLabel = { t('dialog.close') }
  126. className = { classes.closeIcon }
  127. icon = { IconCloseLarge }
  128. id = 'modal-header-close-button'
  129. onClick = { onClose } />
  130. )}
  131. </div>
  132. <div
  133. className = { classes.content }
  134. data-autofocus-inside = 'true'>
  135. {children}
  136. </div>
  137. <div
  138. className = { classes.footer }
  139. data-autofocus-inside = 'true'>
  140. {!back.hidden && <Button
  141. accessibilityLabel = { t(back.translationKey ?? '') }
  142. labelKey = { back.translationKey }
  143. // eslint-disable-next-line react/jsx-handler-names
  144. onClick = { back.onClick }
  145. type = 'secondary' />}
  146. {!cancel.hidden && <Button
  147. accessibilityLabel = { t(cancel.translationKey ?? '') }
  148. labelKey = { cancel.translationKey }
  149. onClick = { onClose }
  150. type = 'tertiary' />}
  151. {!ok.hidden && <Button
  152. accessibilityLabel = { t(ok.translationKey ?? '') }
  153. disabled = { ok.disabled }
  154. id = 'modal-dialog-ok-button'
  155. labelKey = { ok.translationKey }
  156. onClick = { submit } />}
  157. </div>
  158. </BaseDialog>
  159. );
  160. };
  161. export default Dialog;