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.
This commit is contained in:
justme committed 2026-10-16 05:34:38 +08:00
1 parent 06fe077ef1
commit 1db3795d6a
16 files changed
+383 -56

No files matched your search

+29
View File
@@ -0,0 +1,29 @@
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,
);
}