Files
WebDrop/web/src/ui/Drawer.tsx
T
justme 1db3795d6a feat(web): open spaces as a plain chat on phones with a side drawer
Spaces, channels, files, members and the account move into a left drawer,
the top bar keeps only the essentials, and touch devices get a tap menu
instead of always-visible delete buttons. Also fixes the history checkboxes
in the channel settings sheet.
2026-10-16 05:34:38 +08:00

30 lines
1.2 KiB
TypeScript

import { useEffect, useRef, type ReactNode } from 'react';
import { createPortal } from 'react-dom';
import { useBackToClose } from '@/lib/useBackToClose';
import styles from './Drawer.module.css';
interface Props { label: string; onClose: () => void; children: ReactNode }
/** 手机的左侧抽屉:遮罩是纯色,返回键关闭(与 Sheet 一致) */
export function Drawer({ label, onClose, children }: Props) {
const ref = useRef<HTMLDivElement>(null);
const close = useRef(onClose);
useEffect(() => { close.current = onClose; }, [onClose]);
useBackToClose(onClose);
useEffect(() => {
const prev = document.activeElement as HTMLElement | null;
ref.current?.focus();
const onKey = (event: KeyboardEvent) => { if (event.key === 'Escape') close.current(); };
window.addEventListener('keydown', onKey);
return () => { window.removeEventListener('keydown', onKey); prev?.focus(); };
}, []);
return createPortal(
<div className={styles.scrim} onClick={onClose}>
<div ref={ref} tabIndex={-1} role="dialog" aria-modal="true" aria-label={label} className={styles.drawer} onClick={(event) => event.stopPropagation()}>
{children}
</div>
</div>,
document.body,
);
}