Modal

import { Modal } from '@megafon/ui-core';
Примеры и код
Свойства и методы
Код DemoModalWrapper
export const DemoModalWrapper: React.FC<IDemoModalWrapperProps> = ({ children }) => {
const [isOpened, setIsOpened] = React.useState<boolean>(false);
const [isShowBackButton, setIsShowBackButton] = React.useState<boolean>(false);
const [isChangeMobileView, setIsChangeMobileView] = React.useState<boolean>(false);
const [isChangeProps, setIsChangeProps] = React.useState<boolean>(false);
const handleOpen = (): void => {
setIsOpened(true);
};
const handleCLose = (): void => {
setIsOpened(false);
setIsShowBackButton(false);
setIsChangeMobileView(false);
setIsChangeProps(false);
};
const handleChangeShowBackButton =
(value: boolean): (() => void) =>
(): void => {
setIsShowBackButton(value);
};
const handleChangeMobileView = (): void => {
setIsChangeMobileView(true);
};
const handleChangeProps = (): void => {
setIsChangeProps(true);
};
const renderStaticFooter: JSX.Element = (
<div style={{ paddingTop: '24px', textAlign: 'center' }}>
<Button onClick={handleCLose}>Закрыть</Button>
</div>
);
const renderStickyFooter: JSX.Element = (
<div style={{ padding: '32px 0', textAlign: 'center' }}>
<Button onClick={handleCLose}>Закрыть</Button>
</div>
);
const renderActiveButtonFooter: JSX.Element = (
<div style={{ display: 'flex', justifyContent: 'center', padding: '32px 0', textAlign: 'center' }}>
{!isShowBackButton && (
<div style={{ marginRight: '16px' }}>
<Button onClick={handleChangeShowBackButton(true)}>Далее</Button>
</div>
)}
<Button type="outline" onClick={handleCLose}>
Закрыть
</Button>
</div>
);
const renderChangeMobileViewButtonFooter: JSX.Element = (
<div style={{ display: 'flex', justifyContent: 'center', paddingTop: '24px', textAlign: 'center' }}>
{!isChangeMobileView && (
<div style={{ marginRight: '16px' }}>
<Button onClick={handleChangeMobileView}>Далее</Button>
</div>
)}
<Button type="outline" onClick={handleCLose}>
Закрыть
</Button>
</div>
);
const renderChangePropsButtonFooter: JSX.Element = (
<div style={{ display: 'flex', justifyContent: 'center', paddingTop: '24px', textAlign: 'center' }}>
<div style={{ marginRight: '16px' }}>
<Button onClick={handleChangeProps}>Далее</Button>
</div>
<Button type="outline" onClick={handleCLose}>
Закрыть
</Button>
</div>
);
return (
<div>
{children({
isOpened,
isShowBackButton,
isChangeMobileView,
isChangeProps,
staticFooter: renderStaticFooter,
stickyFooter: renderStickyFooter,
activeButtonFooter: renderActiveButtonFooter,
changeMobileViewButtonFooter: renderChangeMobileViewButtonFooter,
changePropsButtonFooter: renderChangePropsButtonFooter,
onClose: handleCLose,
onOpen: handleOpen,
onChangeShowBackButton: handleChangeShowBackButton,
})}
</div>
);
};

Базовое использование

Без заголовка

<DemoModalWrapper>
  {({ isOpened, onClose, onOpen }) =>
      <>
          <span>
              <Button onClick={onOpen}>Open</Button>
          </span>
          <Modal isOpened={isOpened} onClose={onClose}>
              <DemoModalContentMedium />
          </Modal>
      </>
  }
</DemoModalWrapper>

С заголовком

<DemoModalWrapper>
  {({ isOpened, onClose, onOpen }) =>
      <>
          <span>
              <Button onClick={onOpen}>Open</Button>
          </span>
          <Modal headerProps={{ headerTitle: 'Услуги связи' }} isOpened={isOpened} onClose={onClose}>
              <DemoModalContentMedium />
          </Modal>
      </>
  }
</DemoModalWrapper>

С длинным контентом

<DemoModalWrapper>
  {({ isOpened, onClose, onOpen }) =>
      <>
          <span>
              <Button onClick={onOpen}>Open</Button>
          </span>
          <Modal headerProps={{ headerTitle: 'Услуги связи' }} isOpened={isOpened} onClose={onClose}>
              <DemoModalContentLong />
          </Modal>
      </>
  }
</DemoModalWrapper>

Настройки шапки

С кнопкой назад и дополнительным контентом

<DemoModalWrapper>
  {({ isOpened, onClose, onOpen }) =>
      <>
          <span>
              <Button onClick={onOpen}>Open</Button>
          </span>
          <Modal
              headerProps={{
                  headerTitle: 'Услуги связи',
                  showBackButton: true,
                  headerAdditionalContent: 'Дополнительный контент в шапке попапа',
              }}
              isOpened={isOpened}
              onClose={onClose}
          >
              <DemoModalContentMedium />
          </Modal>
      </>
  }
</DemoModalWrapper>

С незафиксированной шапкой

<DemoModalWrapper>
  {({ isOpened, onClose, onOpen }) =>
      <>
          <span>
              <Button onClick={onOpen}>Open</Button>
          </span>
          <Modal
              headerProps={{ headerTitle: 'Услуги связи', isStickyHeader: false }}
              isOpened={isOpened}
              onClose={onClose}
          >
              <DemoModalContentLong />
          </Modal>
      </>
  }
</DemoModalWrapper>

Настройки футера

Отображение футера

<DemoModalWrapper>
  {({ isOpened, staticFooter, onClose, onOpen }) =>
      <>
          <span>
              <Button onClick={onOpen}>Open</Button>
          </span>
          <Modal
              headerProps={{ headerTitle: 'Услуги связи' }}
              footerProps={{ footer: staticFooter }}
              isOpened={isOpened}
              onClose={onClose}
          >
              <DemoModalContentMedium />
          </Modal>
      </>
  }
</DemoModalWrapper>

Зафиксированный футер с тенью

<DemoModalWrapper>
  {({ isOpened, stickyFooter, onClose, onOpen }) =>
      <>
          <span>
              <Button onClick={onOpen}>Open</Button>
          </span>
          <Modal
              headerProps={{ headerTitle: 'Услуги связи' }}
              footerProps={{
                  footer: stickyFooter,
                  isStickyFooter: true,
                  hasFooterShadow: true,
              }}
              isOpened={isOpened}
              onClose={onClose}
          >
              <DemoModalContentLong />
          </Modal>
      </>
  }
</DemoModalWrapper>

Другие настройки

Вид шторки на мобилках

<DemoModalWrapper>
  {({ isOpened, staticFooter, onClose, onOpen }) =>
      <>
          <span>
              <Button onClick={onOpen}>Open</Button>
          </span>
          <Modal
              headerProps={{ headerTitle: 'Услуги связи' }}
              footerProps={{ footer: staticFooter }}
              mobileView={MODAL_MOBILE_VIEWS_ENUM.BOTTOM}
              isOpened={isOpened}
              onClose={onClose}
          >
              <DemoModalContentShort />
          </Modal>
      </>
  }
</DemoModalWrapper>

Без кастомного скролла с кнопками вне основной шапки и подложкой

<DemoModalWrapper>
  {({ isOpened, onClose, onOpen }) =>
      <>
          <span>
              <Button onClick={onOpen}>Open</Button>
          </span>
          <Modal
              headerProps={{ isOutSideHeaderButtons: true, hasHeaderButtonsShadow: true }}
              isEnabledNativeScroll
              isOpened={isOpened}
              onClose={onClose}
          >
              <p style={{ padding: '60px 40px 40px' }}>
                  <DemoModalContentLong />
              </p>
          </Modal>
      </>
  }
</DemoModalWrapper>

Динамическое изменение высоты попапа при изменении контента внутри

<DemoModalWrapper>
  {({ isOpened, isShowBackButton, activeButtonFooter, onClose, onOpen, onChangeShowBackButton }) =>
      <>
          <span>
              <Button onClick={onOpen}>Open</Button>
          </span>
          <Modal
              headerProps={{
                  headerTitle: 'Услуги связи',
                  showBackButton: isShowBackButton,
                  onBackButtonClick: onChangeShowBackButton(false),
              }}
              footerProps={{
                  footer: activeButtonFooter,
                  isStickyFooter: true,
              }}
              isOpened={isOpened}
              onClose={onClose}
          >
              {isShowBackButton ? <DemoModalContentLong /> : <DemoModalContentMedium />}
          </Modal>
      </>
  }
</DemoModalWrapper>

Пересчет максимальной высоты скролла при изменении вида на мобилках

<DemoModalWrapper>
  {({ isOpened, isChangeMobileView, changeMobileViewButtonFooter, onClose, onOpen }) =>
      <>
          <span>
              <Button onClick={onOpen}>Open</Button>
          </span>
          <Modal
              headerProps={{
                  headerTitle: 'Услуги связи',
              }}
              footerProps={{
                  footer: changeMobileViewButtonFooter,
              }}
              mobileView={isChangeMobileView ? MODAL_MOBILE_VIEWS_ENUM.FULL_SCREEN : MODAL_MOBILE_VIEWS_ENUM.BOTTOM}
              isOpened={isOpened}
              onClose={onClose}
          >
              {<DemoModalContentShort />}
          </Modal>
      </>
  }
</DemoModalWrapper>

Пересчет максимальной высоты скролла при изменении шапки и футера

<DemoModalWrapper>
  {({ isOpened, isChangeProps, staticFooter, changePropsButtonFooter, onClose, onOpen }) =>
      <>
          <span>
              <Button onClick={onOpen}>Open</Button>
          </span>
          <Modal
              headerProps={{
                  headerTitle: 'Услуги связи',
                  headerAdditionalContent: isChangeProps ? 'Дополнительный контент в шапке' : '',
              }}
              footerProps={{
                  footer: isChangeProps ? staticFooter : changePropsButtonFooter
              }}
              isRecalculateHeight
              isOpened={isOpened}
              onClose={onClose}
          >
              {<DemoModalContentShort />}
          </Modal>
      </>
  }
</DemoModalWrapper>
Prop nameTypeDefaultDescription
classNamestring | undefinedДополнительные классы для корневого элемента
classesModalClassesType | undefinedДополнительные классы для внутренних элементов
dataAttrsModalDataAttrsType | undefinedДополнительные data-атрибуты к внутренним элементам
isOpened*booleanСостояние открытости
scrollBarParamsOmit<IScrollBarProps, "maxHeight"> | undefinedНастройки для кастомного компонента скролла
headerPropsModalHeaderPropsType | undefinedНастройки для шапки модального окна
footerPropsModalFooterPropsType | undefinedНастройки для футера модального окна
mobileViewMODAL_MOBILE_VIEWS_ENUM | undefinedMODAL_MOBILE_VIEWS_ENUM.FULL_SCREENВид модального окна на разрешении 767-
isEnabledNativeScrollboolean | undefinedВключить дефолтный скролл (отключает кастомный компонент скролла)
isSwipeDisabledboolean | undefinedОтключить закрытие шторки свайпом
isDisabledBackgroundClickboolean | undefinedОтключить закрытие модального окна при клике на фон
isReturnFocusAfterCloseboolean | undefinedtrueВосстанавливает фокус на элементе, который был сфокусирован до открытия модального окна
isRecalculateHeightboolean | undefinedПересчитывать максимальную высоту скролла
hideAriaAppboolean | undefinedfalseДолжен ли root-элемент приложения быть скрыт
contentLabelstring | undefinedУстанавливает aria-label
onClose(() => void) | undefinedОбработчик закрытия модального окна
onAfterModalOpen(() => void) | undefinedОбработчик после открытия модального окна
getModalContentRef((node: HTMLDivElement) => void) | undefinedRef обработчик для Content
getModalOverlayRef((node: HTMLDivElement) => void) | undefinedRef обработчик для Overlay
export type ModalClassesType = {
bodyOpen?: string;
modalContent?: string;
overlay?: string;
background?: string;
containerWrap?: string;
containerInner?: string;
containerBody?: string;
header?: string;
headerBackButton?: string;
headerCloseButton?: string;
titleArea?: string;
title?: string;
children?: string;
childrenContent?: string;
footer?: string;
};
export type ModalDataAttrsType = {
background?: Record<string, string>;
headerBackButton?: Record<string, string>;
headerCloseButton?: Record<string, string>;
containerWrap?: Record<string, string>;
containerInner?: Record<string, string>;
containerBody?: Record<string, string>;
};
export type ModalHeaderPropsType = {
/** Заголовок */
headerTitle?: string | JSX.Element | null;
/** Отобразить стрелку назад */
showBackButton?: boolean;
/** Скрыть крестик */
hideCloseButton?: boolean;
/** Отобразить дополнительный контент в шапке */
headerAdditionalContent?: JSX.Element | JSX.Element[] | string | null;
/** Отобразить тень у шапки */
hasHeaderShadow?: boolean;
/** Отобразить кнопки с подложкой */
hasHeaderButtonsShadow?: boolean;
/** Закрепленная шапка */
isStickyHeader?: boolean;
/** Кнопки находятся вне основной шапке */
isOutSideHeaderButtons?: boolean;
/** Обработчик для стрелки назад */
onBackButtonClick?: () => void;
};
export type ModalFooterPropsType = {
/** Футер */
footer?: JSX.Element | JSX.Element[] | string | null;
/** Закрепить футер */
isStickyFooter?: boolean;
/** Отобразить тень у футера */
hasFooterShadow?: boolean;
};