split inbox

This commit is contained in:
Arjun 2026-05-13 19:51:00 +05:30
parent 83b54feb0c
commit 375d8bf2e0
2 changed files with 69 additions and 35 deletions

View file

@ -215,6 +215,15 @@
letter-spacing: 0.08em; letter-spacing: 0.08em;
} }
.gmail-section {
display: flex;
flex-direction: column;
}
.gmail-section + .gmail-section {
margin-top: 28px;
}
.gmail-row { .gmail-row {
display: grid; display: grid;
grid-template-columns: 12px minmax(140px, 0.22fr) minmax(0, 1fr) 60px; grid-template-columns: 12px minmax(140px, 0.22fr) minmax(0, 1fr) 60px;

View file

@ -558,34 +558,19 @@ export function EmailView() {
}) })
}, [query, threads]) }, [query, threads])
const { importantThreads, otherThreads } = useMemo(() => {
const important: GmailThread[] = []
const other: GmailThread[] = []
for (const thread of filteredThreads) {
if (thread.messages.length > 1) important.push(thread)
else other.push(thread)
}
return { importantThreads: important, otherThreads: other }
}, [filteredThreads])
const hasThreads = filteredThreads.length > 0 const hasThreads = filteredThreads.length > 0
return ( const renderRow = (thread: GmailThread) => {
<div className="gmail-shell">
<div className="gmail-main">
<div className="gmail-topbar">
<div className="gmail-search">
<Search size={18} />
<input
value={query}
onChange={(event) => setQuery(event.target.value)}
placeholder="Search mail"
/>
</div>
<button type="button" className="gmail-icon-button" onClick={() => void loadThreads()} aria-label="Refresh">
{loading ? <LoaderIcon size={18} className="animate-spin" /> : <RefreshCw size={18} />}
</button>
</div>
{error ? (
<div className="gmail-empty-state">Could not load mail: {error}</div>
) : hasThreads ? (
<div className="gmail-list" aria-label="Recent emails">
<div className="gmail-list-header">
<span>Last 2 days</span>
<span>{filteredThreads.length} threads</span>
</div>
{filteredThreads.map((thread) => {
const latest = latestMessage(thread) const latest = latestMessage(thread)
const isSelected = thread.threadId === selectedThreadId const isSelected = thread.threadId === selectedThreadId
const isUnread = thread.unread === true const isUnread = thread.unread === true
@ -616,7 +601,47 @@ export function EmailView() {
)} )}
</div> </div>
) )
})} }
return (
<div className="gmail-shell">
<div className="gmail-main">
<div className="gmail-topbar">
<div className="gmail-search">
<Search size={18} />
<input
value={query}
onChange={(event) => setQuery(event.target.value)}
placeholder="Search mail"
/>
</div>
<button type="button" className="gmail-icon-button" onClick={() => void loadThreads()} aria-label="Refresh">
{loading ? <LoaderIcon size={18} className="animate-spin" /> : <RefreshCw size={18} />}
</button>
</div>
{error ? (
<div className="gmail-empty-state">Could not load mail: {error}</div>
) : hasThreads ? (
<div className="gmail-list" aria-label="Recent emails">
{importantThreads.length > 0 && (
<section className="gmail-section">
<div className="gmail-list-header">
<span>Important</span>
<span>{importantThreads.length} thread{importantThreads.length === 1 ? '' : 's'}</span>
</div>
{importantThreads.map(renderRow)}
</section>
)}
{otherThreads.length > 0 && (
<section className="gmail-section">
<div className="gmail-list-header">
<span>Everything else</span>
<span>{otherThreads.length} thread{otherThreads.length === 1 ? '' : 's'}</span>
</div>
{otherThreads.map(renderRow)}
</section>
)}
</div> </div>
) : ( ) : (
<div className="gmail-empty-state"> <div className="gmail-empty-state">