move to accordian

This commit is contained in:
Arjun 2026-05-13 14:51:55 +05:30
parent 21148d02b9
commit ec1420fcf5
2 changed files with 82 additions and 57 deletions

View file

@ -124,22 +124,26 @@
background: rgba(60, 64, 67, 0.08);
}
.gmail-layout {
display: grid;
grid-template-columns: minmax(420px, 0.45fr) minmax(480px, 0.55fr);
.gmail-list {
display: flex;
flex-direction: column;
min-width: 0;
min-height: 0;
flex: 1;
overflow: hidden;
overflow: auto;
border-radius: 16px;
background: #fff;
border: 1px solid #e4e7ee;
}
.gmail-list {
min-width: 0;
min-height: 0;
overflow: auto;
border-right: 1px solid #e4e7ee;
.gmail-row-group {
display: flex;
flex-direction: column;
border-bottom: 1px solid #f1f3f4;
}
.gmail-row-group:last-child {
border-bottom: none;
}
.gmail-list-header {
@ -165,7 +169,6 @@
min-height: 44px;
padding: 0 12px;
border: none;
border-bottom: 1px solid #f1f3f4;
background: #f6f8fc;
color: #5f6368;
text-align: left;
@ -248,28 +251,52 @@
.gmail-detail {
display: flex;
min-width: 0;
min-height: 0;
flex-direction: column;
background: #fff;
}
.gmail-detail-inline {
background: #f6f8fc;
border-top: 1px solid #e4e7ee;
box-shadow: inset 3px 0 0 #1a73e8;
}
.gmail-detail-toolbar {
display: flex;
align-items: center;
gap: 4px;
height: 44px;
padding: 0 12px;
justify-content: space-between;
gap: 12px;
height: 48px;
padding: 0 16px;
border-bottom: 1px solid #e8eaed;
background: #fff;
}
.gmail-back-button {
display: none;
.gmail-thread-subject-inline {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: #202124;
font-size: 15px;
font-weight: 500;
}
.gmail-thread-scroll {
min-height: 0;
overflow: auto;
padding: 24px 32px 40px;
.gmail-detail-toolbar-actions {
display: flex;
align-items: center;
gap: 2px;
}
.gmail-detail-toolbar-actions .gmail-icon-button span {
font-size: 20px;
line-height: 1;
}
.gmail-thread-body {
padding: 20px 28px 32px;
background: #fff;
}
.gmail-thread-subject-row {

View file

@ -247,29 +247,27 @@ function ComposeBox({
function ThreadDetail({
thread,
onBack,
onClose,
}: {
thread: GmailThread
onBack: () => void
onClose: () => void
}) {
const [composeMode, setComposeMode] = useState<ComposeMode | null>(null)
return (
<div className="gmail-detail">
<div className="gmail-detail gmail-detail-inline">
<div className="gmail-detail-toolbar">
<button type="button" className="gmail-icon-button gmail-back-button" onClick={onBack} aria-label="Back to inbox">
<span></span>
</button>
<button type="button" className="gmail-icon-button" aria-label="Archive"><Archive size={18} /></button>
<button type="button" className="gmail-icon-button" aria-label="More"><MoreVertical size={18} /></button>
<div className="gmail-thread-subject-inline">{thread.subject || '(No subject)'}</div>
<div className="gmail-detail-toolbar-actions">
<button type="button" className="gmail-icon-button" aria-label="Archive"><Archive size={18} /></button>
<button type="button" className="gmail-icon-button" aria-label="More"><MoreVertical size={18} /></button>
<button type="button" className="gmail-icon-button" onClick={onClose} aria-label="Close thread">
<span>×</span>
</button>
</div>
</div>
<div className="gmail-thread-scroll">
<div className="gmail-thread-subject-row">
<h1>{thread.subject || '(No subject)'}</h1>
<span>Inbox</span>
</div>
<div className="gmail-thread-body">
<div className="gmail-message-stack">
{thread.messages.map((message, index) => {
const isLast = index === thread.messages.length - 1
@ -399,7 +397,7 @@ export function EmailView() {
})
}, [query, threads])
const selectedThread = filteredThreads.find(thread => thread.threadId === selectedThreadId) ?? filteredThreads[0] ?? null
const hasThreads = filteredThreads.length > 0
return (
<div className="gmail-shell">
@ -420,23 +418,22 @@ export function EmailView() {
{error ? (
<div className="gmail-empty-state">Could not load mail: {error}</div>
) : selectedThread ? (
<div className="gmail-layout">
<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 isSelected = thread.threadId === selectedThread.threadId
const isUnread = thread.unread === true
return (
) : 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 isSelected = thread.threadId === selectedThreadId
const isUnread = thread.unread === true
return (
<div key={thread.threadId} className="gmail-row-group">
<button
key={thread.threadId}
type="button"
className={cn('gmail-row', isSelected && 'gmail-row-selected', isUnread && 'gmail-row-unread')}
onClick={() => setSelectedThreadId(thread.threadId)}
onClick={() => setSelectedThreadId(isSelected ? null : thread.threadId)}
>
<span className="gmail-row-check" />
<span className="gmail-row-star"><Star size={16} /></span>
@ -447,14 +444,15 @@ export function EmailView() {
</span>
<span className="gmail-row-date">{formatInboxTime(latest?.date || thread.date)}</span>
</button>
)
})}
</div>
<ThreadDetail
thread={selectedThread}
onBack={() => setSelectedThreadId(null)}
/>
{isSelected && (
<ThreadDetail
thread={thread}
onClose={() => setSelectedThreadId(null)}
/>
)}
</div>
)
})}
</div>
) : (
<div className="gmail-empty-state">