0aa0a60e40
Co-authored-by: gorbenko.pavel <gorbenko.pavel@tansu.kz> Reviewed-on: http://git.tnsu.kz/timur.gorodetskiy/request-portal/pulls/1 Co-authored-by: gorbenko.pavel <gorbenko.pavel@tnsu.kz> Co-committed-by: gorbenko.pavel <gorbenko.pavel@tnsu.kz>
40 lines
1.7 KiB
TypeScript
40 lines
1.7 KiB
TypeScript
import * as React from 'react';
|
|
import styles from './Drawer.module.scss';
|
|
import { Icon } from '../../shared/ui/Icon/Icon';
|
|
|
|
interface IDrawerProps {
|
|
title: string;
|
|
onClose: () => void;
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
// Выезжающая справа панель: открывается по клику на строку таблицы заявок,
|
|
// внутри — заявка в режиме просмотра/согласования. Закрывается крестиком,
|
|
// кликом по затемнению и клавишей Esc.
|
|
export const Drawer: React.FC<IDrawerProps> = ({ title, onClose, children }) => {
|
|
React.useEffect(() => {
|
|
const onKeyDown = (e: KeyboardEvent): void => {
|
|
if (e.key === 'Escape') onClose();
|
|
};
|
|
window.addEventListener('keydown', onKeyDown);
|
|
return () => window.removeEventListener('keydown', onKeyDown);
|
|
}, [onClose]);
|
|
|
|
return (
|
|
<div className={styles.overlay}>
|
|
{/* Затемнение — не кнопка (внутри панели свои интерактивные элементы),
|
|
поэтому клик обрабатываем на этом слое напрямую. */}
|
|
<div className={styles.backdrop} onClick={onClose} aria-hidden="true" />
|
|
<aside className={styles.drawer} role="dialog" aria-modal="true" aria-label={title}>
|
|
<div className={styles.header}>
|
|
<span className={styles.title}>{title}</span>
|
|
<button type="button" className={styles.close} onClick={onClose} aria-label="Закрыть">
|
|
<Icon name="close" size="sm" />
|
|
</button>
|
|
</div>
|
|
<div className={styles.body}>{children}</div>
|
|
</aside>
|
|
</div>
|
|
);
|
|
};
|