signal-desktop/ts/components/Modal.tsx

79 lines
1.9 KiB
TypeScript
Raw Normal View History

// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useState, ReactElement, ReactNode } from 'react';
import classNames from 'classnames';
import { noop } from 'lodash';
import { LocalizerType } from '../types/Util';
import { ModalHost } from './ModalHost';
import { Theme } from '../util/theme';
type PropsType = {
children: ReactNode;
hasXButton?: boolean;
i18n: LocalizerType;
2021-04-21 16:31:12 +00:00
moduleClassName?: string;
onClose?: () => void;
title?: ReactNode;
theme?: Theme;
};
export function Modal({
children,
hasXButton,
i18n,
2021-04-21 16:31:12 +00:00
moduleClassName,
onClose = noop,
title,
theme,
}: Readonly<PropsType>): ReactElement {
const [scrolled, setScrolled] = useState(false);
const hasHeader = Boolean(hasXButton || title);
return (
<ModalHost onClose={onClose} theme={theme}>
<div
className={classNames(
'module-Modal',
2021-04-21 16:31:12 +00:00
hasHeader ? 'module-Modal--has-header' : 'module-Modal--no-header',
moduleClassName
)}
>
{hasHeader && (
<div className="module-Modal__header">
{hasXButton && (
<button
aria-label={i18n('close')}
type="button"
className="module-Modal__close-button"
onClick={() => {
onClose();
}}
/>
)}
{title && <h1 className="module-Modal__title">{title}</h1>}
</div>
)}
<div
className={classNames('module-Modal__body', {
'module-Modal__body--scrolled': scrolled,
})}
onScroll={event => {
setScrolled((event.target as HTMLDivElement).scrollTop > 2);
}}
>
{children}
</div>
</div>
</ModalHost>
);
}
Modal.Footer = ({
children,
}: Readonly<{ children: ReactNode }>): ReactElement => (
<div className="module-Modal__footer">{children}</div>
);