diff --git a/docs/inbox-ui-gap-analysis.md b/docs/inbox-ui-gap-analysis.md new file mode 100644 index 0000000..6bdb84d --- /dev/null +++ b/docs/inbox-ui-gap-analysis.md @@ -0,0 +1,116 @@ +# AGMail Inbox UI — Expectation vs Reality + +Reference: target mock (populated, high-density inbox). +Current: implementation screenshot (sparse real data, 3 emails). + +--- + +## 1. Email rows — structure & density + +| Area | Expected | Current | Gap | +|------|----------|---------|-----| +| Grid columns | Fixed: checkbox, star, avatar, sender, subject—preview, labels, attachment, date/actions | Partial grid; labels column collapses when empty; date/actions compete for space | Labels need reserved column; rail must overlay date | +| Row height | Fixed 44–48px; hover never changes height | Row 1 visibly taller on hover | **Bug:** hover actions affect layout | +| Hover actions | 30×30 hit areas, 14–16px icons, replace date in-place | Icons crammed at far right; row expands | Absolute overlay in date rail | +| Unread | Blue dot + semibold sender/subject + warmer row bg | Weak/unused unread pip; read/unread similar | Stronger unread treatment | +| Stars | Outline inactive, amber fill active | Present but low contrast | Tune star states | +| Labels | Dedicated column, vertically aligned across rows | Labels drift near date when present | Fixed label column always reserved | +| Attachments | Paperclip column before date | Works when present | Keep dedicated column | +| Sender avatars | Brand logos + deterministic initials | All senders same purple SD | Vary initials colors; logos when domain known | +| Overflow | Three-dot menu at row end | Missing | Optional future | + +## 2. Category navigation + +| Area | Expected | Current | Gap | +|------|----------|---------|-----| +| Zero badges | Hidden | Hidden ✓ | OK | +| Non-zero badges | Coral pills when data exists | None shown (only 3 emails, counts may be 0) | Mechanism OK; needs real unread per category | +| Active tab | 600 weight, coral underline under label width | Present but weak | Stronger active typography | +| Icons | Distinct per category | Present | OK | +| Pagination in tab bar | `1–10 of 243` + controls on right | `1–3` floating in tab bar only | Move to footer control cluster | + +## 3. Surface hierarchy + +| Area | Expected | Current | Gap | +|------|----------|---------|-----| +| Canvas | Warm off-white, slightly darker than cards | `#F4F3F1` — very close to white cards | Darken canvas ~2–3% | +| Inbox card | White, subtle shadow, light border | White, very subtle contrast | Increase shadow, not border | +| Layering | Canvas → workspace tone → white cards | Mostly two layers | Add workspace header tone | + +## 4. Right panel — AG Agent + +| Area | Expected | Current | Gap | +|------|----------|---------|-----| +| Empty state | Caught-up card when all metrics zero | Present ✓ | Improve green success tint | +| Populated state | 4 metric cards + greeting + agenda + needs attention | Only shows when `hasSignals`; user sees empty with 3 emails | Threshold/data wiring OK; greeting missing in populated mode | +| Quick actions | Equal-size buttons, no wrap | "Summarize inbox" wraps | Fix button width/height | +| Today's agenda | Time + title + venue + color bar | Implemented when meeting emails exist | Needs richer extraction | +| Needs attention | Avatar + name + status + age | Text only | Add mini avatars | +| Ask input | Paperclip + send | Send only | Add attach icon | +| Header | 15px/650 title, larger spark container | Slightly small | Increase presence | + +## 5. Sidebar + +| Area | Expected | Current | Gap | +|------|----------|---------|-----| +| Badges | Inbox 12, Drafts 3, labels, Action Items 3 | Only Clients 1 | Mechanism exists; apply consistent badge component | +| Label badge style | Dark translucent pill | Same coral as inbox | Neutral pill for labels | +| More | Collapsible after Personal | Missing | Add More row | +| Compose | Gradient + coral shadow + split dropdown | Flat coral, caret not separate hit area | Split button styling | +| Profile block | Anchored bottom, not clipped | May clip on short viewports | Flex column + `margin-top: auto` | +| Active inbox | Coral indicator + count | Active state weak | Polish active row | + +## 6. Header / toolbar + +| Area | Expected | Current | Gap | +|------|----------|---------|-----| +| Search width | Wide command surface | OK but large dead zone before filter | Tighten action cluster | +| Icon contrast | Secondary but readable | Too faint (~disabled) | +10–15% contrast | +| Account block | Name 12px/600, email 10px, chevron | Typography too small | Increase legibility | +| Ask Agent | Lavender pill | Present ✓ | OK | + +## 7. Pagination / list controls + +| Area | Expected | Current | Gap | +|------|----------|---------|-----| +| Footer cluster | Range + prev/next + density toggles | Only when paginating; minimal | Always show when emails exist | +| Range format | `1–10 of 243` | `1–3` in tab bar | Full footer cluster | + +## 8. Notes utility + +| Area | Expected | Current | Gap | +|------|----------|---------|-----| +| Zero notes | Low emphasis | Same weight as agent card | Reduce contrast when `Notes (0)` | +| With notes | More visible | Collapsible ✓ | OK | + +## 9. Micro-interactions + +| Area | Expected | Current | Gap | +|------|----------|---------|-----| +| Row hover | Actions fade in, no layout shift | Layout shift | Fix overlay | +| Nav/category hover | Subtle surfaces | Partial | Consistent transitions | +| Compose press | Slight scale/brightness | Minimal | Add press feedback | + +## 10. Color anchors + +| Area | Expected | Current | Gap | +|------|----------|---------|-----| +| Contextual labels | Blue, green, amber, lavender pills in rows | Some labels on row 2 | More label types in `emailLabels` ✓ | +| Sender diversity | Brand colors/logos | Same purple for self-sent | Deterministic initials colors | + +--- + +## Priority fix order + +1. **Row height bug** — hover rail overlay (blocking) +2. **Surface contrast** — canvas + shadow +3. **Row grid** — fixed columns, unread, labels column +4. **Pagination footer** — full control cluster +5. **Sidebar** — More, compose split, profile anchor, badge variants +6. **Agent panel** — greeting, quick action sizing, attention avatars, empty-state tint +7. **Header** — icon contrast, account typography, toolbar spacing +8. **Notes** — zero-state de-emphasis + +## Visual rule + +Every component: **absent → present → interactive**. Zero data reduces complexity; real data increases density. **No state change may alter row dimensions.** diff --git a/frontend/src/components/AgAgentPanel.jsx b/frontend/src/components/AgAgentPanel.jsx index efc7b4a..25f0f6a 100644 --- a/frontend/src/components/AgAgentPanel.jsx +++ b/frontend/src/components/AgAgentPanel.jsx @@ -5,6 +5,7 @@ import { ChevronRight, FileSearch, ListChecks, + Paperclip, PenLine, Receipt, Send, @@ -12,6 +13,7 @@ import { } from "lucide-react"; import AgentInsight from "./AgentInsight"; import AgentSpark from "./AgentSpark"; +import SenderAvatar from "./SenderAvatar"; import { inboxContext } from "../utils/inboxSignals"; const ICON = { size: 14, strokeWidth: 1.75 }; @@ -19,10 +21,16 @@ const ICON = { size: 14, strokeWidth: 1.75 }; const cards = [ { key: "important", label: "Important emails", captionKey: "importantFromClients", captionSuffix: "from clients", icon: Star, tone: "rose" }, { key: "actionItems", label: "Action items", hint: "Need response", icon: ListChecks, tone: "blue" }, - { key: "meetings", label: "Meetings mentioned", hint: "On calendar", icon: Calendar, tone: "green" }, + { key: "meetings", label: "Meetings mentioned", hint: "In your emails", icon: Calendar, tone: "green" }, { key: "invoices", label: "Invoices & bills", hint: "This week", icon: Receipt, tone: "amber" }, ]; +function greeting(name) { + const hour = new Date().getHours(); + const period = hour < 12 ? "Good morning" : hour < 17 ? "Good afternoon" : "Good evening"; + return `${period}, ${name}`; +} + export default function AgAgentPanel({ account, emails, @@ -34,6 +42,7 @@ export default function AgAgentPanel({ }) { const { stats, needsReply, today, deadlines } = inboxContext(emails); const [agentQuery, setAgentQuery] = useState(""); + const firstName = account?.first_name || "there"; const hasSignals = stats.important + stats.actionItems + stats.meetings + stats.invoices > 0; function submitAgentQuery(event) { @@ -56,9 +65,16 @@ export default function AgAgentPanel({ + {!insight && hasSignals && ( +
+ {greeting(firstName)} + Here's what needs your attention today. +
+ )} + {!insight && !hasSignals && (
-

You're all caught up.

+

You're all caught up.

No urgent messages or outstanding actions.

Inbox is quiet right now.
@@ -79,7 +95,7 @@ export default function AgAgentPanel({ className={`agent-stat agent-stat-${card.tone}`} onClick={() => onQuickAction(card.key)} > - + {count} {card.label} {caption} @@ -95,16 +111,20 @@ export default function AgAgentPanel({

Quick actions

@@ -138,8 +158,12 @@ export default function AgAgentPanel({ {needsReply.slice(0, 3).map((item) => (
  • ))} @@ -167,8 +191,11 @@ export default function AgAgentPanel({ onChange={(event) => setAgentQuery(event.target.value)} placeholder="Ask about your emails..." /> - + diff --git a/frontend/src/components/DashboardPage.jsx b/frontend/src/components/DashboardPage.jsx index 204d204..3e86348 100644 --- a/frontend/src/components/DashboardPage.jsx +++ b/frontend/src/components/DashboardPage.jsx @@ -63,9 +63,9 @@ function SidebarSection({ title, children, className = "" }) { ); } -function NavBadge({ value }) { +function NavBadge({ value, variant = "coral" }) { if (!value || value <= 0) return null; - return {value}; + return {value}; } export default function DashboardPage() { @@ -81,6 +81,7 @@ export default function DashboardPage() { const [mailRefreshKey, setMailRefreshKey] = useState(0); const [lens, setLens] = useState("all"); const [agentNav, setAgentNav] = useState(null); + const [labelsExpanded, setLabelsExpanded] = useState(false); const [mailStats, setMailStats] = useState({ unread: 0, starred: 0, @@ -223,11 +224,17 @@ export default function DashboardPage() { - +
    + + +
    diff --git a/frontend/src/components/MailRow.jsx b/frontend/src/components/MailRow.jsx index 451134b..a1ae1f1 100644 --- a/frontend/src/components/MailRow.jsx +++ b/frontend/src/components/MailRow.jsx @@ -2,6 +2,7 @@ import { Archive, Clock3, MailOpen, + MoreHorizontal, Paperclip, Star, Trash2, @@ -11,7 +12,7 @@ import SenderAvatar from "./SenderAvatar"; import { senderDisplayName } from "../utils/senderAvatar"; import { attachmentCount, emailLabels } from "../utils/inboxSignals"; -const ICON = { size: 14, strokeWidth: 1.75 }; +const ICON = { size: 15, strokeWidth: 1.75 }; function formatTimestamp(value) { if (!value) return ""; @@ -101,10 +102,13 @@ export default function MailRow({ title={starred ? "Unstar" : "Star"} aria-pressed={starred} > - + - {senderName} + + {unread &&