feat(messaging-ui): Slack-style threaded-replies side panel
Replies (messages with parentInteractionId) now open in a right-hand ThreadPane instead of inline quoting: - extracted a shared Composer (draft + @mention autocomplete + attach) and MessageItem (bubble + mentions + attachment + reactions + reply affordance) - Thread shows top-level messages only; a message with replies gets a '💬 N replies' link, and hovering shows 💬 'Reply in thread' - ThreadPane renders the root + its replies + a composer that posts back with parentInteractionId; Messenger becomes 3-column (list | thread | pane), pane closes on conversation switch - no contract/adapter/backend change (parentInteractionId was already wired) - thread-pane render test (open → reply → parent shows the count); 58 green Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import { useAdapter } from '../provider';
|
||||
import { ConversationList } from './conversation-list';
|
||||
import { ChannelBrowser } from './channel-browser';
|
||||
import { Thread } from './thread';
|
||||
import { ThreadPane } from './thread-pane';
|
||||
|
||||
/**
|
||||
* The drop-in messenger: sectioned conversation list (Channels / Direct messages) + open thread,
|
||||
@@ -17,6 +18,7 @@ export function Messenger() {
|
||||
|
||||
const [selected, setSelected] = useState<string | null>(null);
|
||||
const [browsing, setBrowsing] = useState(false);
|
||||
const [activeRoot, setActiveRoot] = useState<string | null>(null); // open thread pane's root message
|
||||
|
||||
useEffect(() => {
|
||||
if (browsing) return;
|
||||
@@ -24,6 +26,9 @@ export function Messenger() {
|
||||
setSelected(conversations[0]?.threadId ?? null);
|
||||
}, [conversations, selected, browsing]);
|
||||
|
||||
// Switching conversations (or into browse) closes any open thread pane.
|
||||
useEffect(() => setActiveRoot(null), [selected, browsing]);
|
||||
|
||||
const channels = useMemo(() => conversations.filter((c) => c.membership === 'channel'), [conversations]);
|
||||
const dms = useMemo(() => conversations.filter((c) => c.membership !== 'channel'), [conversations]);
|
||||
|
||||
@@ -73,9 +78,13 @@ export function Messenger() {
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Thread threadId={selected} />
|
||||
<Thread threadId={selected} activeRootId={activeRoot} onOpenThread={setActiveRoot} />
|
||||
)}
|
||||
</section>
|
||||
|
||||
{!browsing && selected && activeRoot ? (
|
||||
<ThreadPane threadId={selected} rootId={activeRoot} onClose={() => setActiveRoot(null)} />
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user