Closes #246. The transcript, composer and approval controls move from structured.ts/structuredRender.ts into components under web/src/components/structured/, against docs/STRUCTURED-VIEW.md: eight row kinds, both projections, the single-active approval nonce, and diff rendering with its own line counts. The pure layers stay shared — structuredDiff.ts computes the diff, structuredRender.ts still sanitizes markdown — and model.ts holds the client-side decisions (activity grouping, notice classification, offered decisions, `/` completion) so they are testable without a DOM. Like TerminalPane, the pane draws the body only; pane chrome reads the connection through onStatusChange. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
44 lines
1.3 KiB
TypeScript
44 lines
1.3 KiB
TypeScript
// A turn's collapsed activity block: two or more tool rows after the same
|
||
// `User` row, plus the narration absorbed between them. The header counts tool
|
||
// rows only (docs/STRUCTURED-VIEW.md); opening it reveals tools and text in
|
||
// chronological order.
|
||
|
||
import type { ReactNode } from "react";
|
||
|
||
export interface ToolGroupProps {
|
||
id: string;
|
||
toolCount: number;
|
||
expanded: boolean;
|
||
onExpandedChange(expanded: boolean): void;
|
||
children: ReactNode;
|
||
}
|
||
|
||
export function ToolGroup({ id, toolCount, expanded, onExpandedChange, children }: ToolGroupProps) {
|
||
return (
|
||
<div className="st-tool-group" data-tool-group-id={id}>
|
||
<button
|
||
type="button"
|
||
className="st-tool-group-head"
|
||
aria-expanded={expanded}
|
||
onClick={() => onExpandedChange(!expanded)}
|
||
>
|
||
<span className="st-tool-group-glyph" aria-hidden="true">
|
||
›
|
||
</span>
|
||
<span className="st-tool-group-title">{`${toolCount} tool calls`}</span>
|
||
</button>
|
||
<div
|
||
className={
|
||
expanded ? "st-tool-group-body st-disclosure is-expanded" : "st-tool-group-body st-disclosure"
|
||
}
|
||
aria-hidden={!expanded}
|
||
inert={!expanded}
|
||
>
|
||
<div className="st-disclosure-clip">
|
||
<div className="st-disclosure-inner">{children}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|