Skip to content

Commit 7e7bbf8

Browse files
authored
Merge pull request #25 from PMDevSolutions/4-source-and-search-results-display-component
feat: ChatSources sidebar with grouped source links
2 parents ffb668a + 631ba9f commit 7e7bbf8

16 files changed

Lines changed: 1583 additions & 39 deletions

CLAUDE.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ pnpm test # Run tests
100100
| `ChatInput` | Message input form with submit handling |
101101
| `ChatToggleButton` | Floating button to open/close chat |
102102
| `MessageBubble` | Renders individual messages with URL linking |
103+
| `ChatSources` | Slide-out sidebar displaying grouped source links |
104+
| `SourceIcon` | Icon button with badge count to trigger source sidebar |
103105

104106
### useChat Hook
105107

@@ -139,7 +141,10 @@ Manages chat state:
139141

140142
// Response
141143
{
142-
reply: "How can I help you today?"
144+
reply: "How can I help you today?",
145+
sources?: [
146+
{ url: "https://...", title: "...", type: "blog" | "page" | "external" }
147+
]
143148
}
144149
```
145150

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# ChatSources Component Design
2+
3+
**Issue:** #4 - Source and search results display component
4+
**Date:** 2026-03-24
5+
6+
## Overview
7+
8+
A slide-out sidebar panel that displays source links associated with assistant messages. Sources are returned by the worker API, grouped by type, and triggered via an icon button on each message.
9+
10+
## Types
11+
12+
```typescript
13+
interface Source {
14+
url: string;
15+
title: string;
16+
type: "blog" | "page" | "external";
17+
}
18+
19+
// ChatResponse expands:
20+
interface ChatResponse {
21+
reply: string;
22+
sources?: Source[];
23+
}
24+
25+
// ChatMessage expands:
26+
interface ChatMessage {
27+
id: string;
28+
role: "user" | "assistant";
29+
content: string;
30+
sources?: Source[];
31+
}
32+
```
33+
34+
## Components
35+
36+
### SourceIcon (new)
37+
38+
Trigger button displayed on assistant messages that have sources.
39+
40+
- Small link/document icon, bottom-left of assistant message bubble
41+
- Tiny badge circle showing source count, colored `claudius-primary`
42+
- Muted by default, more visible on hover
43+
- Tooltip: "View sources"
44+
- Clicking toggles the ChatSources sidebar for that message
45+
46+
### ChatSources (new)
47+
48+
Slide-out sidebar panel.
49+
50+
- Slides from the left edge of ChatWindow, overlaying the message area
51+
- Width: ~280px
52+
- Background: `claudius-light` (dark mode aware)
53+
- Border-right: 2px `claudius-border`
54+
- Rounded corners on right side
55+
- Smooth slide transition (~200ms ease)
56+
57+
**Header:**
58+
- "Sources" title
59+
- "{n} sources found" subtext
60+
- Close (X) button
61+
62+
**Body:**
63+
- Grouped by type: blogs first, then pages, then external
64+
- Type group headers: small muted labels ("Blog", "Page", "External"), only shown if that type has entries
65+
- Source cards: rounded-[12px], 2px border, subtle fill
66+
- Each card shows title (truncated) and domain extracted from URL
67+
- Click opens link in new tab
68+
- Hover: slight background shift
69+
70+
**No empty state needed** - icon only appears when sources exist.
71+
72+
## Integration
73+
74+
### Files to create
75+
76+
- `widget/src/components/ChatSources.tsx` - Sidebar panel
77+
- `widget/src/components/SourceIcon.tsx` - Trigger button with badge
78+
79+
### Files to modify
80+
81+
- `widget/src/api/types.ts` - Add `Source` type, update `ChatResponse`
82+
- `widget/src/hooks/useChat.ts` - Pass sources through to `ChatMessage`
83+
- `widget/src/components/MessageBubble.tsx` - Render SourceIcon for assistant messages with sources
84+
- `widget/src/components/ChatWindow.tsx` - Manage sidebar state, render ChatSources overlay
85+
- `widget/src/index.ts` - Export new types
86+
87+
### Not in scope (this PR)
88+
89+
- Worker changes to return source data. Widget will be built and testable with mock data in dev mode.
90+
91+
## Filtering
92+
93+
The worker handles domain filtering server-side using the client's `allowedDomains` config. The widget trusts and renders whatever sources the API returns.
94+
95+
## Source grouping order
96+
97+
1. Blog posts (`type: "blog"`)
98+
2. Site pages (`type: "page"`)
99+
3. External links (`type: "external"`)

0 commit comments

Comments
 (0)