Панель со списками заявок (#1)
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>
This commit was merged in pull request #1.
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
@import '../../../../styles/design-tokens';
|
||||
|
||||
// Выезжающая панель поверх страницы. position: fixed — панель должна перекрывать
|
||||
// всю страницу SharePoint, а не только канву web part.
|
||||
.overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.backdrop {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(10, 27, 48, .45);
|
||||
animation: fade .2s ease-out;
|
||||
}
|
||||
|
||||
.drawer {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: min(920px, 100%);
|
||||
height: 100%;
|
||||
background: $gray-50;
|
||||
box-shadow: $sh-modal;
|
||||
animation: slide .22s ease-out;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: $sp-4;
|
||||
flex-shrink: 0;
|
||||
padding: $sp-4 $sp-6;
|
||||
background: $white;
|
||||
border-bottom: 1px solid $gray-200;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-family: $font-serif;
|
||||
font-size: 18px;
|
||||
color: $navy-900;
|
||||
}
|
||||
|
||||
.close {
|
||||
flex-shrink: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
border: 1px solid $gray-300;
|
||||
border-radius: $r-sm;
|
||||
background: $white;
|
||||
color: $navy-700;
|
||||
cursor: pointer;
|
||||
transition: .16s;
|
||||
|
||||
&:hover {
|
||||
border-color: $red-500;
|
||||
color: $red-500;
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: $sp-6;
|
||||
}
|
||||
|
||||
@keyframes slide {
|
||||
from { transform: translateX(24px); opacity: .6; }
|
||||
to { transform: translateX(0); opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes fade {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
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>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user