feat: mobile-responsive mail plugin UI
This commit is contained in:
@@ -69,6 +69,7 @@ export function MailPage() {
|
||||
const [forwardMailState, setForwardMailState] = useState<Mail | null>(null);
|
||||
const [downloadingAttachmentId, setDownloadingAttachmentId] = useState<string | null>(null);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [activeView, setActiveView] = useState<'folders' | 'list' | 'detail'>('folders');
|
||||
|
||||
// Load accounts
|
||||
const loadAccounts = useCallback(async () => {
|
||||
@@ -168,6 +169,7 @@ export function MailPage() {
|
||||
setMailsPage(1);
|
||||
setSearchQuery('');
|
||||
setSelectedMail(null);
|
||||
setActiveView('list');
|
||||
},
|
||||
[folders],
|
||||
);
|
||||
@@ -175,6 +177,7 @@ export function MailPage() {
|
||||
// Handle mail selection
|
||||
const handleSelectMail = useCallback(
|
||||
async (mail: Mail) => {
|
||||
setActiveView('detail');
|
||||
setLoadingMail(true);
|
||||
try {
|
||||
const detail = await getMail(mail.id);
|
||||
@@ -435,8 +438,8 @@ export function MailPage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Three-pane layout with resizable panels */}
|
||||
<div className="flex flex-1 overflow-hidden">
|
||||
{/* Desktop: three-pane layout with resizable panels */}
|
||||
<div className="hidden md:flex flex-1 overflow-hidden">
|
||||
{/* Folder tree — resizable */}
|
||||
<ResizablePanel
|
||||
initialWidth={224}
|
||||
@@ -495,6 +498,82 @@ export function MailPage() {
|
||||
</ResizablePanel>
|
||||
</div>
|
||||
|
||||
{/* Mobile: single-pane view switching */}
|
||||
<div className="flex md:hidden flex-1 overflow-hidden flex-col">
|
||||
{/* View 1: Folder tree */}
|
||||
{activeView === 'folders' && (
|
||||
<div className="flex-1 overflow-y-auto bg-white" data-testid="mobile-folder-pane">
|
||||
<div className="p-3">
|
||||
<MailFolderTree
|
||||
accounts={accounts}
|
||||
folders={folders}
|
||||
selectedFolderId={selectedFolderId}
|
||||
onSelect={handleSelectFolder}
|
||||
loading={loadingFolders}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* View 2: Mail list */}
|
||||
{activeView === 'list' && (
|
||||
<div className="flex-1 overflow-y-auto bg-white" data-testid="mobile-list-pane">
|
||||
<div className="flex items-center gap-2 px-3 py-2 border-b border-secondary-200 sticky top-0 bg-white z-10">
|
||||
<button
|
||||
onClick={() => setActiveView('folders')}
|
||||
className="inline-flex items-center gap-1 px-2 py-1 rounded text-sm text-secondary-700 hover:bg-secondary-100 min-h-touch"
|
||||
aria-label="Zurück zu Ordnern"
|
||||
data-testid="mobile-back-to-folders"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
|
||||
</svg>
|
||||
<span className="text-sm font-medium">Ordner</span>
|
||||
</button>
|
||||
</div>
|
||||
<MailList
|
||||
mails={mails}
|
||||
selectedMailId={selectedMail?.id || null}
|
||||
onSelectMail={handleSelectMail}
|
||||
loading={loadingMails}
|
||||
currentPage={mailsPage}
|
||||
total={mailsTotal}
|
||||
pageSize={PAGE_SIZE}
|
||||
onPageChange={setMailsPage}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* View 3: Mail detail */}
|
||||
{activeView === 'detail' && (
|
||||
<div className="flex-1 overflow-y-auto bg-white" data-testid="mobile-detail-pane">
|
||||
<div className="flex items-center gap-2 px-3 py-2 border-b border-secondary-200 sticky top-0 bg-white z-10">
|
||||
<button
|
||||
onClick={() => setActiveView('list')}
|
||||
className="inline-flex items-center gap-1 px-2 py-1 rounded text-sm text-secondary-700 hover:bg-secondary-100 min-h-touch"
|
||||
aria-label="Zurück zur Liste"
|
||||
data-testid="mobile-back-to-list"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
|
||||
</svg>
|
||||
<span className="text-sm font-medium">Zurück</span>
|
||||
</button>
|
||||
</div>
|
||||
<MailDetail
|
||||
mail={selectedMail}
|
||||
loading={loadingMail}
|
||||
onReply={handleReply}
|
||||
onForward={handleForward}
|
||||
onCreateEvent={handleCreateEvent}
|
||||
onToggleFlag={handleToggleFlag}
|
||||
onDownloadAttachment={handleDownloadAttachment}
|
||||
downloadingAttachmentId={downloadingAttachmentId}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<ComposeModal
|
||||
open={composeOpen}
|
||||
mode={composeMode}
|
||||
|
||||
Reference in New Issue
Block a user