Overview
InsightList provides a forum-style view for browsing and interacting with insights. Designed for participants to vote, add themselves as affected users, and engage with the community. Includes filtering, sorting, and pagination.
Features
- Card-based layout optimized for browsing
- Voting with optimistic updates
- "This affects me too" action for adding submitters
- Filter by type, status, and search
- Sort by impact score, activity, date, or submitter count
- Submitter avatar stack with tooltips
- Responsive design (stacks on mobile)
- Pagination controls
Layout Structure
┌─────────────────────────────────────────────────┐ │ [Search...] [Type ▼] [Status ▼] [Sort ▼] │ ├─────────────────────────────────────────────────┤ │ ┌─────────────────────────────────────────────┐ │ │ │ [▲] Bug Report | Open │ │ │ │ 42 Login crashes on iOS │ │ │ │ [▼] Summary text here... │ │ │ │ 💬 12 👥 ○○○+5 2 hours ago │ │ │ │ [This affects me] [View →] │ │ │ └─────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────┐ │ │ │ ... │ │ │ └─────────────────────────────────────────────┘ │ │ [< 1 2 3 ... 10 >] │ └─────────────────────────────────────────────────┘
Examples
Vote Buttons
Upvote/downvote with optimistic updates
Vertical (default)
+42
Neutral
0
Downvoted
-5
Horizontal
+12
Small
+8
Disabled
+15
Submitter Badges
Avatar stack with overflow count
Single submitter
AC
Three submitters
AC
BS
CD
With overflow (+2)
AC
BS
CD
+2
maxDisplay=4
AC
BS
CD
DL
+1
Hover over avatars to see user names and original submitter designation.
Two Views Pattern
The Insights page has two modes based on user role:
┌─────────────────────────────────────────────┐ │ [Management] [Collaborate] ← Toggle │ └─────────────────────────────────────────────┘ Management (InsightManagementTable): - For Owners/Builders - Table view with bulk actions - Status management, merging Collaborate (InsightList): - For all project members - Forum-style card view - Voting, "This affects me" - Participants ONLY see this view
Props Reference
InsightList Props
| Prop | Type | Default | Description |
|---|---|---|---|
projectId | string | - | Project ID for API calls |
projectSlug | string | - | Project slug for links |
programSlug | string | - | Program slug for links |
insights | Insight[] | - | Array of insights to display |
total | number | - | Total count for pagination |
insightTypes | InsightTypeOption[] | - | Available types for filtering |
currentUserId | string | - | Current user's ID |
isAdmin | boolean | false | Whether user is Owner/Builder |
pageSize | number | 10 | Items per page |
userVotes | Record<string, 1 | -1> | - | Map of user's votes by insight ID |
InsightVoteButtons Props
| Prop | Type | Default | Description |
|---|---|---|---|
voteScore | number | - | Current vote score |
userVote | 1 | -1 | null | - | User's current vote |
onVote | (value: 1 | -1) => Promise<void> | - | Vote callback |
vertical | boolean | true | Vertical or horizontal layout |
size | "sm" | "md" | "md" | Size variant |
disabled | boolean | false | Disable voting |
InsightSubmitterBadges Props
| Prop | Type | Default | Description |
|---|---|---|---|
submitters | InsightSubmitter[] | - | Array of submitter objects with user info |
maxDisplay | number | 3 | Max avatars to show before +N overflow |
Usage
import { InsightList } from '@/features/insights';
// Forum-style view for participants
<InsightList
projectId={projectId}
projectSlug={projectSlug}
programSlug={programSlug}
insights={insights}
total={total}
insightTypes={insightTypes}
currentUserId={userId}
isAdmin={false}
pageSize={10}
userVotes={userVotes}
/>
// Sub-components can be used independently:
// Vote buttons with optimistic updates
<InsightVoteButtons
voteScore={42}
userVote={1}
onVote={(value) => handleVote(value)}
vertical
size="md"
/>
// Submitter avatar stack
<InsightSubmitterBadges
submitters={insight.submitters}
maxDisplay={3}
/>