feat(messaging-ui): rendered Messenger components — the drop-in UI
Turns the SDK from hooks-only into a real UI SDK: <Messenger> (conversation list + open thread + composer), plus <ConversationList> and <Thread>, all driven by the existing useConversations/useMessages hooks over the injected adapter — zero transport imports (boundary intact). - themeable via --miu-* CSS variables; default theme ships as ./styles.css - optimistic send, typing indicator, seen ticks, reactions display, unread badges - render smoke tests (jsdom + MockAdapter): mounts, auto-selects first thread, sends a message, switches threads (3 tests) — 48 total green - tsup: css bundled to dist/styles.css; dts scoped to TS entries Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useConversations } from '../hooks/use-conversations';
|
||||
import { ConversationList } from './conversation-list';
|
||||
import { Thread } from './thread';
|
||||
|
||||
/**
|
||||
* The drop-in messenger: conversation list + open thread. Owns only selection state;
|
||||
* all data flows through the injected adapter via the hooks. Auto-selects the first
|
||||
* conversation so the pane is never empty on load.
|
||||
*/
|
||||
export function Messenger() {
|
||||
const { conversations, loading, error } = useConversations();
|
||||
const [selected, setSelected] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (selected && conversations.some((c) => c.threadId === selected)) return;
|
||||
setSelected(conversations[0]?.threadId ?? null);
|
||||
}, [conversations, selected]);
|
||||
|
||||
return (
|
||||
<div className="miu-messenger">
|
||||
<aside className="miu-sidebar">
|
||||
{loading && conversations.length === 0 ? <div className="miu-empty">Loading…</div> : null}
|
||||
{error ? <div className="miu-empty miu-error">{error}</div> : null}
|
||||
<ConversationList conversations={conversations} selectedId={selected} onSelect={setSelected} />
|
||||
</aside>
|
||||
<section className="miu-main">
|
||||
<Thread threadId={selected} />
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user