/* ========================================================================== SummaryBanner.tsx -------------------------------------------------------------------------- v2: replaces StatusBanner's rule tree with a streamed Claude summary, grounded only in the stats (never restating new numbers of its own). This component only renders a `BannerState`; it does not fetch, stream, or decide anything; that arrives in Phase 3 (fake stream) and Phase 4 (real API) as a `useStreamedSummary` hook that feeds `text` and `state` in. Accessibility (full behavior lands in Phase 3, not here): the summary must announce once on completion, not per streamed token. This component stays presentational so that wiring can slot in without a reshape. ========================================================================== */ (function (SB: any) { "use strict"; const Beacon = SB.Beacon; interface SummaryBannerProps { state: BannerState; // Activity read, bold lead line; matter summary, plain line beneath it // when present, matching v1's bold-lead pattern (StatusBanner.tsx) // without literal bullets. Both are shown exactly the same way whether // state is "streaming" or "done": useStreamedSummary.ts's revealWords // builds the real two-line shape from the first word (activity typed // out, then matter), so there is no separate "done" layout to snap // into, just the caret moving on, then off. activityText?: string; matterText?: string; error?: string; // shown when state === "error" } function SummaryBanner(props: SummaryBannerProps) { const state = props.state; if (state === "loading") { return (
); } if (state === "error") { return (
{props.error || "Couldn't generate a summary."}
); } // streaming or done: same shape throughout. While state is "streaming", // the matter line hasn't started yet (absent) or is mid-type (present, // shorter than its final text); the caret sits on whichever line is // actively growing, never both. const matterStarted = Boolean(props.matterText); const activityTyping = state === "streaming" && !matterStarted; const matterTyping = state === "streaming" && matterStarted; return (
{props.activityText} {matterStarted && (
{props.matterText}
)}
); } SB.SummaryBanner = SummaryBanner; })((window as any).SB = (window as any).SB || {});