Inbox Preview Panel is a messaging widget that renders a compact list of inbox threads showing sender, subject snippet, timestamp, and unread count. It builds on the existing InboxThreadList pattern component, elevating it into a self-contained panel widget with header, unread badge, and integration-ready callbacks. The widget is designed for SaaS sidebar panels, notification centers, and messaging overviews.
Goals
Deliver an <InboxPreviewPanel> component that wraps InboxThreadList with a panel header, unread count badge, and thread-selection callback.
Display sender name/avatar, subject or snippet, timestamp, and unread indicator per thread.
Support loading, empty, and error states.
Ship Storybook stories with realistic inbox data.
Non-Goals
Full email client functionality (compose, forward, archive, search).
Message body rendering (this is a preview list, not a reader pane).
Real-time sync or push notification integration.
Pagination or infinite scroll (deferred to future enhancement).
Scope
In Scope
Area
Description
Component
<InboxPreviewPanel> wrapping InboxThreadList with panel chrome
Panel Header
Title, total unread count badge, optional action button (e.g., “Mark all read”)
Storybook stories for populated inbox, empty inbox, loading, error, and themed variants
Out of Scope
Area
Reason
Message body / reader pane
Separate component; this is a preview list only
Compose / reply
Handled by Compose Panel widget (#53)
Thread actions (archive, delete, star)
Future enhancement; initial version is read + select
Search / filter
Future enhancement
Pagination / infinite scroll
Future enhancement
Users and Pain Points
User Groups
User
Description
Needs
Developers
Engineers building SaaS messaging features
A ready-made inbox preview using DS components
Designers
Design-system consumers
Consistent inbox UX aligned with DS tokens
End Users
SaaS application users
Quick scan of recent messages with clear unread indicators
Pain Points
User
Pain Point
Impact
Developers
Building inbox previews requires assembling avatar, text truncation, timestamp formatting, and unread indicators from scratch
Slow development, inconsistent results
End Users
Inconsistent inbox UIs across SaaS apps make it hard to quickly identify unread messages
Missed messages, poor UX
Definitions
Term
Definition
Inbox Thread
A conversation thread in the inbox, represented by its most recent message
Snippet
A truncated preview of the most recent message text
Unread Count
The total number of threads with unread messages
Preview Panel
A compact panel showing a list of thread summaries
Current State
Existing Behavior
InboxThreadList in src/components/patterns/inbox-thread-list.tsx renders a list of inbox threads. It exists as a pattern component with stories but is not wrapped in a panel with header, unread count, or standardized callbacks.
Current Limitations
InboxThreadList is a raw list without panel chrome (header, badge, actions).
No standardized empty, loading, or error state handling at the panel level.
No unread count badge aggregation.
Existing Workarounds
Developers wrap InboxThreadList in custom panel containers and add their own headers and badges.
Proposed Solution
Summary
Introduce <InboxPreviewPanel> that wraps InboxThreadList with a panel header containing a title, unread count badge, and optional action slot. The component accepts a threads array, renders them via the existing list pattern, and calls onThreadSelect when a thread is clicked.
Key Capabilities
Panel header with title and unread count badge.
Optional header action (e.g., “Mark all read” button).
Thread list rendering via InboxThreadList composition.
Thread selection callback.
Empty inbox state with configurable message.
Loading skeleton matching thread item shapes.
Error state with retry.
User Experience
Users see a panel with a header showing “Inbox” and an unread count badge (e.g., “3”). Below is a scrollable list of thread previews. Each thread shows a sender avatar, name, message snippet (truncated), and relative timestamp. Unread threads have a dot indicator and bolder text. Clicking a thread fires the selection callback.
Developer Experience
<InboxPreviewPanel
title="Inbox"
threads={threads}
onThreadSelect={(threadId)=>openThread(threadId)}
onMarkAllRead={()=>markAllRead()}
/>
Requirements
ID
Requirement
Priority
Notes
FR-001
InboxPreviewPanel renders a panel header with title and unread badge
Must
-
FR-002
Thread list renders sender, snippet, timestamp, and unread indicator
Must
Delegates to InboxThreadList
FR-003
onThreadSelect fires when a thread item is clicked
Must
-
FR-004
Optional “Mark all read” action in header
Should
-
FR-005
Loading, empty, and error states are handled
Must
-
Priority Definitions
Priority
Meaning
Must
Required for this feature to ship.
Should
Important, but can be deferred if needed.
Could
Nice to have. Not required for initial release.
Functional Requirements
ID
Requirement
User Benefit
Priority
FUNC-001
threads prop accepts InboxThread[] with id, senderName, senderAvatar, snippet, timestamp, and isUnread fields
Typed thread data structure
Must
FUNC-002
Unread count badge in header auto-calculates from threads.filter(t => t.isUnread).length
No manual count management
Must
FUNC-003
Thread items show sender avatar (via Avatar), sender name, truncated snippet, and relative timestamp
Familiar inbox layout
Must
FUNC-004
Unread threads display a dot indicator and bolder sender name
Quick visual identification
Must
FUNC-005
Clicking a thread fires onThreadSelect(threadId)
Navigation to thread detail
Must
FUNC-006
Header action slot accepts a button (e.g., “Mark all read”) with onClick
Batch actions
Should
FUNC-007
Empty state shows configurable message when threads is empty and not loading