Add messaging UI mockups — inbox feed and conversation views
Slack-inspired mobile-first messaging interface with: - Main inbox with tab navigation (All, @Mentions, DMs, Channels) - Slide-in sidebar menu with channels and portal links - Full conversation view with message bubbles, reactions, typing indicators - Thread/channel drill-down with compose bar - Touch gestures (swipe to close sidebar/threads) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f8ea11601e
commit
a8a9861d90
2 changed files with 1807 additions and 0 deletions
625
messaging-conversation.html
Normal file
625
messaging-conversation.html
Normal file
|
|
@ -0,0 +1,625 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
|
<title>Payfrit — #general</title>
|
||||||
|
<style>
|
||||||
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--primary: #2D7FF9;
|
||||||
|
--primary-dark: #1A5FD1;
|
||||||
|
--bg: #FFFFFF;
|
||||||
|
--bg-secondary: #F5F7FA;
|
||||||
|
--bg-tertiary: #EDF0F5;
|
||||||
|
--text: #1A1D26;
|
||||||
|
--text-secondary: #6B7280;
|
||||||
|
--text-muted: #9CA3AF;
|
||||||
|
--border: #E5E7EB;
|
||||||
|
--green: #10B981;
|
||||||
|
--red: #EF4444;
|
||||||
|
--orange: #F59E0B;
|
||||||
|
--purple: #7C3AED;
|
||||||
|
--shadow-sm: 0 1px 2px rgba(0,0,0,0.06);
|
||||||
|
--radius: 12px;
|
||||||
|
--radius-sm: 8px;
|
||||||
|
--radius-msg: 18px;
|
||||||
|
--safe-top: env(safe-area-inset-top, 0px);
|
||||||
|
--safe-bottom: env(safe-area-inset-bottom, 0px);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
color: var(--text);
|
||||||
|
line-height: 1.5;
|
||||||
|
overflow: hidden;
|
||||||
|
height: 100dvh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-shell {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100dvh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== HEADER ========== */
|
||||||
|
.conv-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 10px 16px;
|
||||||
|
padding-top: calc(10px + var(--safe-top));
|
||||||
|
background: var(--bg);
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
min-height: 56px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-btn {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-btn:active { background: var(--bg-secondary); }
|
||||||
|
.back-btn svg { width: 22px; height: 22px; color: var(--text); }
|
||||||
|
|
||||||
|
.conv-header-info { flex: 1; min-width: 0; }
|
||||||
|
|
||||||
|
.conv-header-title {
|
||||||
|
font-size: 17px;
|
||||||
|
font-weight: 700;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conv-header-title .channel-hash {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conv-header-meta {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-btn {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-btn:active { background: var(--bg-secondary); }
|
||||||
|
.icon-btn svg { width: 20px; height: 20px; color: var(--text-secondary); }
|
||||||
|
|
||||||
|
/* ========== MESSAGE FEED ========== */
|
||||||
|
.message-feed {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
padding: 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Date divider */
|
||||||
|
.date-divider {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
margin: 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-divider::before, .date-divider::after {
|
||||||
|
content: '';
|
||||||
|
flex: 1;
|
||||||
|
height: 1px;
|
||||||
|
background: var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-divider span {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-muted);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Message bubble group */
|
||||||
|
.msg-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg-group-avatar {
|
||||||
|
width: 34px;
|
||||||
|
height: 34px;
|
||||||
|
border-radius: 8px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #fff;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg-group-body { flex: 1; min-width: 0; }
|
||||||
|
|
||||||
|
.msg-group-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg-author {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg-timestamp {
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg-bubble {
|
||||||
|
background: var(--bg);
|
||||||
|
padding: 10px 14px;
|
||||||
|
border-radius: var(--radius-msg);
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.5;
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
max-width: 100%;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg-bubble + .msg-bubble {
|
||||||
|
margin-top: 4px;
|
||||||
|
border-top-left-radius: var(--radius-msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg-bubble.own {
|
||||||
|
background: var(--primary);
|
||||||
|
color: #fff;
|
||||||
|
border-top-left-radius: var(--radius-msg);
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg-bubble .mention {
|
||||||
|
background: rgba(45, 127, 249, 0.15);
|
||||||
|
color: var(--primary);
|
||||||
|
padding: 1px 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg-bubble.own .mention {
|
||||||
|
background: rgba(255,255,255,0.2);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* System message */
|
||||||
|
.system-msg {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reactions */
|
||||||
|
.msg-reactions {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
margin-top: 6px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reaction {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
background: var(--bg-tertiary);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 13px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reaction:active { background: var(--bg-secondary); border-color: var(--primary); }
|
||||||
|
.reaction.active { background: #E0EDFF; border-color: var(--primary); }
|
||||||
|
.reaction-count { font-size: 12px; color: var(--text-secondary); font-weight: 600; }
|
||||||
|
|
||||||
|
/* Image attachment */
|
||||||
|
.msg-attachment {
|
||||||
|
margin-top: 8px;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
overflow: hidden;
|
||||||
|
max-width: 280px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg-attachment-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 160px;
|
||||||
|
background: linear-gradient(135deg, var(--bg-tertiary), var(--border));
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg-attachment-info {
|
||||||
|
padding: 8px 10px;
|
||||||
|
background: var(--bg);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-top: none;
|
||||||
|
border-radius: 0 0 var(--radius) var(--radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg-attachment-name { font-size: 13px; font-weight: 600; }
|
||||||
|
.msg-attachment-size { font-size: 11px; color: var(--text-muted); }
|
||||||
|
|
||||||
|
/* ========== COMPOSE ========== */
|
||||||
|
.compose-area {
|
||||||
|
padding: 8px 12px;
|
||||||
|
padding-bottom: calc(8px + var(--safe-bottom));
|
||||||
|
background: var(--bg);
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.compose-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compose-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 2px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compose-input-wrap {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compose-textarea {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 40px;
|
||||||
|
max-height: 120px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: inherit;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
color: var(--text);
|
||||||
|
outline: none;
|
||||||
|
resize: none;
|
||||||
|
line-height: 1.4;
|
||||||
|
transition: border-color 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compose-textarea:focus { border-color: var(--primary); }
|
||||||
|
.compose-textarea::placeholder { color: var(--text-muted); }
|
||||||
|
|
||||||
|
.send-btn {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border: none;
|
||||||
|
background: var(--primary);
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
transition: background 0.15s, transform 0.1s;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.send-btn:active { background: var(--primary-dark); transform: scale(0.95); }
|
||||||
|
.send-btn svg { width: 20px; height: 20px; }
|
||||||
|
|
||||||
|
/* Typing indicator */
|
||||||
|
.typing-indicator {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
padding: 4px 14px 0;
|
||||||
|
min-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typing-dots {
|
||||||
|
display: inline-flex;
|
||||||
|
gap: 3px;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typing-dots span {
|
||||||
|
width: 5px;
|
||||||
|
height: 5px;
|
||||||
|
background: var(--text-muted);
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: typingBounce 1.2s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typing-dots span:nth-child(2) { animation-delay: 0.2s; }
|
||||||
|
.typing-dots span:nth-child(3) { animation-delay: 0.4s; }
|
||||||
|
|
||||||
|
@keyframes typingBounce {
|
||||||
|
0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
|
||||||
|
30% { transform: translateY(-4px); opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== SCROLL TO BOTTOM FAB ========== */
|
||||||
|
.scroll-bottom-fab {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 80px;
|
||||||
|
right: 16px;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background: var(--bg);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
||||||
|
display: none;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-bottom-fab svg { width: 20px; height: 20px; color: var(--text-secondary); }
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.message-feed { padding: 16px 24px; }
|
||||||
|
.conv-header { padding: 10px 20px; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="conversation-shell">
|
||||||
|
<!-- HEADER -->
|
||||||
|
<header class="conv-header">
|
||||||
|
<a class="back-btn" href="messaging.html" aria-label="Back">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 12H5"/><path d="M12 19l-7-7 7-7"/></svg>
|
||||||
|
</a>
|
||||||
|
<div class="conv-header-info">
|
||||||
|
<div class="conv-header-title"><span class="channel-hash">#</span> general</div>
|
||||||
|
<div class="conv-header-meta">John, Koda, Sarah, Zara, Claude, Ava</div>
|
||||||
|
</div>
|
||||||
|
<div class="header-actions">
|
||||||
|
<button class="icon-btn" aria-label="Search">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
|
||||||
|
</button>
|
||||||
|
<button class="icon-btn" aria-label="Channel info">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- MESSAGE FEED -->
|
||||||
|
<div class="message-feed" id="messageFeed">
|
||||||
|
|
||||||
|
<div class="date-divider"><span>March 25, 2026</span></div>
|
||||||
|
|
||||||
|
<!-- John -->
|
||||||
|
<div class="msg-group">
|
||||||
|
<div class="msg-group-avatar" style="background: #2D7FF9;">J</div>
|
||||||
|
<div class="msg-group-body">
|
||||||
|
<div class="msg-group-header">
|
||||||
|
<span class="msg-author" style="color: #2D7FF9;">John</span>
|
||||||
|
<span class="msg-timestamp">9:15 AM</span>
|
||||||
|
</div>
|
||||||
|
<div class="msg-bubble">Morning team! Quick update — we've got a demo scheduled for next Friday. Let's make sure the scan → health score → alternatives flow is rock solid by then 💪</div>
|
||||||
|
<div class="msg-reactions">
|
||||||
|
<span class="reaction active">🔥 <span class="reaction-count">4</span></span>
|
||||||
|
<span class="reaction">👍 <span class="reaction-count">3</span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Koda -->
|
||||||
|
<div class="msg-group">
|
||||||
|
<div class="msg-group-avatar" style="background: #7C3AED;">K</div>
|
||||||
|
<div class="msg-group-body">
|
||||||
|
<div class="msg-group-header">
|
||||||
|
<span class="msg-author" style="color: #7C3AED;">Koda</span>
|
||||||
|
<span class="msg-timestamp">9:22 AM</span>
|
||||||
|
</div>
|
||||||
|
<div class="msg-bubble">On it! Android scanner is already reading barcodes reliably. Just need to finalize the API call format with the backend.</div>
|
||||||
|
<div class="msg-bubble">Also pushed about 50 files yesterday — layouts, activities, data layer. It's coming together 🧱</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Sarah -->
|
||||||
|
<div class="msg-group">
|
||||||
|
<div class="msg-group-avatar" style="background: #059669;">S</div>
|
||||||
|
<div class="msg-group-body">
|
||||||
|
<div class="msg-group-header">
|
||||||
|
<span class="msg-author" style="color: #059669;">Sarah</span>
|
||||||
|
<span class="msg-timestamp">9:40 AM</span>
|
||||||
|
</div>
|
||||||
|
<div class="msg-bubble">Health score algorithm v3 is finalized! Much better handling of edge cases now. The weighted nutrient scoring really smooths out the weird outliers we were seeing.</div>
|
||||||
|
<div class="msg-reactions">
|
||||||
|
<span class="reaction">🎉 <span class="reaction-count">3</span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Claude -->
|
||||||
|
<div class="msg-group">
|
||||||
|
<div class="msg-group-avatar" style="background: #DC2626;">C</div>
|
||||||
|
<div class="msg-group-body">
|
||||||
|
<div class="msg-group-header">
|
||||||
|
<span class="msg-author" style="color: #DC2626;">Claude</span>
|
||||||
|
<span class="msg-timestamp">10:05 AM</span>
|
||||||
|
</div>
|
||||||
|
<div class="msg-bubble">API v2 endpoint for alternatives is live! Response times averaging 120ms. The new matching algorithm considers nutrient similarity + price range + availability.</div>
|
||||||
|
<div class="msg-attachment">
|
||||||
|
<div class="msg-attachment-img">📊 API Response Time Chart</div>
|
||||||
|
<div class="msg-attachment-info">
|
||||||
|
<div class="msg-attachment-name">api-v2-benchmarks.png</div>
|
||||||
|
<div class="msg-attachment-size">245 KB</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="date-divider"><span>Today</span></div>
|
||||||
|
|
||||||
|
<!-- Zara (own message) -->
|
||||||
|
<div class="msg-group" style="flex-direction: row-reverse;">
|
||||||
|
<div class="msg-group-avatar" style="background: #EC4899;">Z</div>
|
||||||
|
<div class="msg-group-body" style="display: flex; flex-direction: column; align-items: flex-end;">
|
||||||
|
<div class="msg-group-header" style="flex-direction: row-reverse;">
|
||||||
|
<span class="msg-author" style="color: #EC4899;">Zara</span>
|
||||||
|
<span class="msg-timestamp">8:30 AM</span>
|
||||||
|
</div>
|
||||||
|
<div class="msg-bubble own">Dashboard page is looking solid! Added the health score breakdown section and the scan history. Testing on mobile now.</div>
|
||||||
|
<div class="msg-reactions">
|
||||||
|
<span class="reaction">👀 <span class="reaction-count">2</span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- John -->
|
||||||
|
<div class="msg-group">
|
||||||
|
<div class="msg-group-avatar" style="background: #2D7FF9;">J</div>
|
||||||
|
<div class="msg-group-body">
|
||||||
|
<div class="msg-group-header">
|
||||||
|
<span class="msg-author" style="color: #2D7FF9;">John</span>
|
||||||
|
<span class="msg-timestamp">9:45 AM</span>
|
||||||
|
</div>
|
||||||
|
<div class="msg-bubble"><span class="mention">@zara</span> get those mockups created, i want to see some designs. Maybe look at how Slack does their mobile layout — tabs, slide-in menu, the basics.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Koda -->
|
||||||
|
<div class="msg-group">
|
||||||
|
<div class="msg-group-avatar" style="background: #7C3AED;">K</div>
|
||||||
|
<div class="msg-group-body">
|
||||||
|
<div class="msg-group-header">
|
||||||
|
<span class="msg-author" style="color: #7C3AED;">Koda</span>
|
||||||
|
<span class="msg-timestamp">10:02 AM</span>
|
||||||
|
</div>
|
||||||
|
<div class="msg-bubble"><span class="mention">@zara</span> can you check the health score display on the scan page? Something looks off with the color mapping — scores in the 60-70 range are showing green instead of yellow</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Sarah -->
|
||||||
|
<div class="msg-group">
|
||||||
|
<div class="msg-group-avatar" style="background: #059669;">S</div>
|
||||||
|
<div class="msg-group-body">
|
||||||
|
<div class="msg-group-header">
|
||||||
|
<span class="msg-author" style="color: #059669;">Sarah</span>
|
||||||
|
<span class="msg-timestamp">10:15 AM</span>
|
||||||
|
</div>
|
||||||
|
<div class="msg-bubble">That might be related to the v3 scoring changes — thresholds shifted. The new breakpoints are: 0-40 red, 41-65 orange, 66-80 yellow, 81-100 green.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Zara (own) -->
|
||||||
|
<div class="msg-group" style="flex-direction: row-reverse;">
|
||||||
|
<div class="msg-group-avatar" style="background: #EC4899;">Z</div>
|
||||||
|
<div class="msg-group-body" style="display: flex; flex-direction: column; align-items: flex-end;">
|
||||||
|
<div class="msg-group-header" style="flex-direction: row-reverse;">
|
||||||
|
<span class="msg-author" style="color: #EC4899;">Zara</span>
|
||||||
|
<span class="msg-timestamp">10:20 AM</span>
|
||||||
|
</div>
|
||||||
|
<div class="msg-bubble own">On it! Building the messaging mockups now — slide-in menu, tab nav, rolling message feed. And I'll fix those color breakpoints on the scan page too 🎨</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- COMPOSE AREA -->
|
||||||
|
<div class="compose-area">
|
||||||
|
<div class="typing-indicator" id="typingIndicator">
|
||||||
|
<span class="typing-dots"><span></span><span></span><span></span></span>
|
||||||
|
Koda is typing...
|
||||||
|
</div>
|
||||||
|
<div class="compose-row">
|
||||||
|
<div class="compose-actions">
|
||||||
|
<button class="icon-btn" aria-label="Attach file">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.49"/></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="compose-input-wrap">
|
||||||
|
<textarea class="compose-textarea" placeholder="Message #general..." rows="1" id="composeTextarea"></textarea>
|
||||||
|
</div>
|
||||||
|
<button class="send-btn" aria-label="Send message">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 2L11 13"/><path d="M22 2l-7 20-4-9-9-4 20-7z"/></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Scroll to bottom FAB -->
|
||||||
|
<button class="scroll-bottom-fab" id="scrollFab" onclick="scrollToBottom()">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14"/><path d="m19 12-7 7-7-7"/></svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const feed = document.getElementById('messageFeed');
|
||||||
|
const fab = document.getElementById('scrollFab');
|
||||||
|
const textarea = document.getElementById('composeTextarea');
|
||||||
|
|
||||||
|
// Scroll to bottom on load
|
||||||
|
feed.scrollTop = feed.scrollHeight;
|
||||||
|
|
||||||
|
// Show/hide scroll FAB
|
||||||
|
feed.addEventListener('scroll', () => {
|
||||||
|
const atBottom = feed.scrollHeight - feed.scrollTop - feed.clientHeight < 100;
|
||||||
|
fab.style.display = atBottom ? 'none' : 'flex';
|
||||||
|
});
|
||||||
|
|
||||||
|
function scrollToBottom() {
|
||||||
|
feed.scrollTo({ top: feed.scrollHeight, behavior: 'smooth' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto-resize textarea
|
||||||
|
textarea.addEventListener('input', () => {
|
||||||
|
textarea.style.height = 'auto';
|
||||||
|
textarea.style.height = Math.min(textarea.scrollHeight, 120) + 'px';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Simulate typing indicator
|
||||||
|
const typingEl = document.getElementById('typingIndicator');
|
||||||
|
setTimeout(() => {
|
||||||
|
typingEl.innerHTML = '';
|
||||||
|
}, 4000);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1182
messaging.html
Normal file
1182
messaging.html
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue