bb.thread-ui
The bb.thread-ui plugin owns thread presentation and consumes the headless bb.threads service.
Purpose
bb.thread-ui presents thread lists, thread views, composers, timeline items, and thread controls.
The plugin keeps presentation contracts separate from thread records and execution. It requires the bb.threads service for all thread data.
Surfaces
| ID | kind | replaceable | props contract sketch | notes |
|---|---|---|---|---|
bb.thread-ui.list |
single |
yes | ThreadListProps |
Owns the thread list. The winner receives Original. |
bb.thread-ui.view |
single |
yes | ThreadViewProps |
Owns one open thread. The winner receives Original. |
bb.thread-ui.composer |
single |
yes | ComposerProps |
Owns each thread composer. The winner receives Original. |
bb.thread-ui.composer.actions |
list |
no | ComposerActionContribution |
Adds ordered controls and cards. |
bb.thread-ui.composer.send |
chain |
no | ComposerSendMiddleware |
Wraps one send operation. |
bb.thread-ui.composer.mentionPopover |
single |
yes | ComposerMentionPopoverProps |
The default bb.thread-ui.composer implementation declares this child surface. The plugin root does not declare it. |
bb.thread-ui.timeline.item |
keyed |
yes | TimelineItemProps |
Selects one component for each timeline item type. |
bb.thread-ui.sidePanels |
list |
no | ThreadSidePanelContribution |
The default bb.thread-ui.view implementation declares this child surface. The plugin root does not declare it. |
All surface declarations use version 1.0. The first-party plugin supplies each default implementation.
The first-party plugin claims bb.layout.main. Its active main implementation declares the root thread UI surfaces.
Hierarchical surface property
The plugin root declares the main presentation surfaces. Default implementations declare their presentation-only children.
bb.layout.main
└─ bb.thread-ui main implementation declares
├─ bb.thread-ui.list
├─ bb.thread-ui.view
│ └─ default view declares bb.thread-ui.sidePanels
├─ bb.thread-ui.composer
│ └─ default composer declares bb.thread-ui.composer.mentionPopover
├─ bb.thread-ui.composer.actions
├─ bb.thread-ui.composer.send
└─ bb.thread-ui.timeline.itemThe kernel activates each child surface only while its active parent implementation declares that child.
A replacement view can declare the same child contract. It can also omit the child contract.
If a replacement omits a child, claims on that child become inactive. The domain services continue without presentation assumptions.
This example shows a required property of the hierarchical surface graph. A child surface follows the active parent implementation.
Shared surface types
The UI contracts import all durable data types from the headless plugin.
import type { ComponentType, ReactNode } from "react";
import type {
ComposerDraft,
ComposerScope,
ExecutionSelection,
JsonValue,
ProjectId,
PromptInput,
ThreadId,
ThreadRecord,
ThreadSummary,
TimelineItem,
TimelineItemId,
} from "@bb/threads/contracts";
import type {
MentionSearchGroup,
MentionSearchItem,
MentionTrigger,
} from "@bb/mentions/contracts";
export interface ThreadAction {
id: string;
title: string;
icon?: string;
when?(thread: ThreadSummary): boolean;
component?: ComponentType<{ thread: ThreadSummary; compact: boolean }>;
run?(thread: ThreadSummary): void | Promise<void>;
}A thread action supplies either component or run. The contract build rejects an incomplete action.
bb.thread-ui.list
The list receives thread state and typed actions. It does not store thread records.
export interface ThreadListProps {
activeThreadId: ThreadId | null;
activeProjectId: ProjectId | null;
compact: boolean;
searchQuery: string;
state:
| { status: "loading"; threads: readonly [] }
| { status: "ready"; threads: readonly ThreadSummary[] }
| { status: "error"; threads: readonly ThreadSummary[]; error: Error };
actions: {
open(threadId: ThreadId, options?: { split?: boolean }): void;
create(options?: { projectId?: ProjectId; focusPrompt?: boolean }): void;
setPinned(threadId: ThreadId, pinned: boolean): Promise<void>;
setRead(threadId: ThreadId, read: boolean): Promise<void>;
rename(threadId: ThreadId, title: string): Promise<void>;
archive(threadId: ThreadId): Promise<void>;
requestDelete(threadId: ThreadId): void;
onNavigate(): void;
};
}
export type ThreadListComponent = ComponentType<ThreadListProps>;The kernel gives Original to the active claimant. A claimant can wrap the default list.
bb.thread-ui.view
The view owns the thread header and the ThreadChat composition.
export interface ThreadViewProps {
threadId: ThreadId;
projectId: ProjectId;
thread: ThreadRecord;
compact: boolean;
focusRequest?: number;
leadingContent?: ReactNode;
headerActions?: readonly ThreadAction[];
messageActions?: readonly MessageAction[];
onOpenPanel?(panelId: string, params?: JsonValue): boolean;
}
export interface MessageReference {
id: string;
threadId: ThreadId;
turnId: string | null;
role: "user" | "assistant";
text: string;
sourceSeqEnd: number;
}
export interface MessageAction {
id: string;
title: string;
icon?: string;
roles?: readonly ("user" | "assistant")[];
run(message: MessageReference): void | Promise<void>;
}The old header and message slots use this wrapper contract. A plugin wraps Original and supplies typed actions.
bb.thread-ui.composer
The composer reads and writes bb.threads.drafts. A winner change does not remove a stored draft.
export interface ComposerProps {
composerId: string;
scope: ComposerScope;
layout: "regular" | "compact" | "zen";
placeholder?: string;
focusRequest?: number;
draft: ComposerDraft;
selection: ExecutionSelection;
runState: "idle" | "submitting" | "active" | "stopping";
submitMode: "ready" | "queue" | "blocked";
disabledReason: { code: string; reason: string } | null;
setDraft(next: ComposerDraft): Promise<void>;
setSelection(next: ExecutionSelection): Promise<void>;
send(intent?: ComposerSendIntent): Promise<ComposerSendResult>;
}
export interface ComposerSendIntent {
verb?: "create" | "send" | "steer" | "queue" | "send-queue-head";
clearDraftOnSuccess?: boolean;
}
export interface ComposerSendResult {
status: "sent" | "queued" | "blocked" | "cancelled";
threadId: ThreadId | null;
reason?: string;
}
export interface ComposerHandle {
getDraft(): ComposerDraft;
setText(text: string): void;
updateText(update: (text: string) => string): void;
clear(options?: { attachments?: boolean }): void;
addQuote(text: string): void;
insertMention(mention: { provider: string; id: string; label: string }): void;
setInputLock(owner: string, locked: boolean): void;
setTextEffect(owner: string, effect: { className: string } | null): void;
focus(): void;
}The component handle controls local UI behavior. The headless service stores the draft and selection.
bb.thread-ui.composer.mentionPopover
The default composer declares this child surface. It calls the optional bb.mentions service and passes presentation state to the popover.
export interface ComposerMentionPopoverProps {
composerId: string;
scope: ComposerScope;
trigger: MentionTrigger;
query: string;
anchor: {
left: number;
top: number;
width: number;
height: number;
};
state:
| { status: "loading"; groups: readonly [] }
| { status: "ready"; groups: readonly MentionSearchGroup[] }
| { status: "error"; groups: readonly []; error: Error };
activeItemId: string | null;
setActiveItem(itemId: string | null): void;
select(input: {
providerId: string;
item: MentionSearchItem;
}): void;
dismiss(): void;
}The popover renders rows and owns selection and menu chrome. It does not search or resolve mentions.
A replacement composer can declare this child contract. It can also omit the child contract.
If the replacement omits it, popover claims become inactive. The bb.mentions service remains available to other consumers.
bb.thread-ui.composer.actions
This list replaces the old composer customization bundle. Each contribution has one stable ID and one placement.
export type ComposerActionContribution =
| {
id: string;
order?: number;
placement: "action-row";
title: string;
icon?: string;
when?(context: ComposerActionContext): boolean;
component?: ComponentType<ComposerActionContext>;
run?(context: ComposerActionContext): void | Promise<void>;
}
| {
id: string;
order?: number;
placement: "plus-menu";
title: string;
description?: string;
icon?: string;
disabled?(context: ComposerActionContext): boolean;
run(context: ComposerActionContext): void | Promise<void>;
}
| {
id: string;
order?: number;
placement: "stack";
chrome?: "card" | "bare";
showDuringInteraction?: boolean;
component: ComponentType<ComposerActionContext>;
};
export interface ComposerActionContext {
composerId: string;
scope: ComposerScope;
draft: ComposerDraft;
selection: ExecutionSelection;
runState: ComposerProps["runState"];
composer: ComposerHandle;
}Rich-text effects use ComposerHandle.setTextEffect(). A plugin does not need a separate rich-text surface.
bb.thread-ui.composer.send
This chain wraps the final send. A wrapper can change the request, block it, or call the next wrapper.
export interface ComposerSendContext {
composerId: string;
scope: ComposerScope;
draft: ComposerDraft;
selection: ExecutionSelection;
intent: Required<ComposerSendIntent>;
signal: AbortSignal;
}
export interface ComposerSendBlock {
status: "blocked";
code: string;
reason: string;
}
export type ComposerSendNext = (
context?: ComposerSendContext,
) => Promise<ComposerSendResult | ComposerSendBlock>;
export interface ComposerSendMiddleware {
id: string;
order?: number;
when?(context: ComposerSendContext): boolean;
run(
context: ComposerSendContext,
next: ComposerSendNext,
): Promise<ComposerSendResult | ComposerSendBlock>;
}The host freezes one chain for each send. A wrapper calls next() at most once.
bb.thread-ui.timeline.item
Each data item has one canonical type. The keyed winner store selects one component for each item type.
export interface TimelinePresentation {
label: { pending: string; completed: string };
icon: { glyph: string };
title?: string;
detail?: string;
suppress?: boolean;
tint?: { light: string; dark: string };
}
export interface TimelineItemProps {
item: TimelineItem;
thread: ThreadRecord;
providerId: string | null;
presentation: TimelinePresentation;
view: {
depth: number;
dimmed: boolean;
inClosedTurn: boolean;
isFrontier: boolean;
};
expansion: {
expanded: boolean;
expandable: boolean;
forced: boolean;
toggle(): void;
};
children: ReactNode;
actions: readonly MessageAction[];
openPanel(panelId: string, params?: JsonValue): boolean;
}The TimelineItem data type contains no presentation member. The selected UI implementation supplies TimelinePresentation.
The key uses the exact item.type. A plugin owns an extension type with <ownerId>/<name>.
The first-party plugin owns all core keys. It also owns * as the default for an unknown extension type.
bb.thread-ui.sidePanels
The default view declares this child list. Each claim supplies a launcher and a body.
export interface ThreadSidePanelContribution {
id: string;
title: string;
icon?: string;
order?: number;
placement: "thread" | "new-thread" | "both";
layout?: "padded" | "flush";
when?(context: ThreadSidePanelContext): boolean;
run?(context: ThreadSidePanelContext): void | Promise<void>;
component: ComponentType<ThreadSidePanelProps>;
}
export type ThreadSidePanelContext =
| { kind: "thread"; threadId: ThreadId; projectId: ProjectId }
| { kind: "new-thread"; projectId: ProjectId | null };
export interface ThreadSidePanelProps {
context: ThreadSidePanelContext;
params: JsonValue | null;
close(): void;
setTitle(title: string): void;
setParams(params: JsonValue | null): void;
}The layout plugin supplies the panel frame. The default thread view supplies the child declaration and its placement contract.
Services
bb.thread-ui declares no data service. It consumes the thread service and can consume the mention service.
| service | edge | range | use |
|---|---|---|---|
bb.threads |
required |
^1 |
Reads records, timeline data, drafts, selection, events, and execution state. |
bb.mentions |
optional |
^1 |
Searches mention providers and resolves selected mentions for the default composer. |
The kernel starts bb.thread-ui after it resolves bb.threads. A thread service winner change restarts bb.thread-ui with a fresh handle.
The required edge keeps the UI independent from the first-party data implementation. A replacement service can keep the same contract.
The optional mention edge keeps the composer usable without bb.mentions. Without it, trigger characters remain plain text.
Exports
The plugin exports exact first-party components for authors who do not want winner selection.
export interface ThreadChatProps {
threadId: ThreadId;
variant?: "full" | "compact" | "timeline";
layout?: "contained" | "document";
focusRequest?: number;
permissionPolicy?: "inherit" | "editable";
className?: string;
leadingContent?: ReactNode;
messageActions?: readonly MessageAction[];
showComposer?: boolean;
}
export interface NewThreadComposerProps {
projectId: ProjectId | null;
defaults?: Partial<ExecutionSelection>;
initialPrompt?: string;
placeholder?: string;
layout?: ComposerProps["layout"];
focusRequest?: number;
className?: string;
draftKey?: string;
onSubmit(request: {
projectId: ProjectId;
selection: ExecutionSelection;
input: readonly PromptInput[];
environment?: JsonValue;
}): void | Promise<void>;
}
export interface MarkdownProps {
content: string;
className?: string;
}
export interface TimelineProps {
threadId: ThreadId;
items: readonly TimelineItem[];
frontier: number;
variant?: "full" | "compact";
searchItemId?: TimelineItemId | null;
}// @bb/thread-ui/components
export { ThreadChat } from "./ThreadChat";
export { ThreadList } from "./ThreadList";
export { ThreadView } from "./ThreadView";
export { Composer, NewThreadComposer } from "./Composer";
export { MentionPopover } from "./MentionPopover";
export { Markdown } from "./Markdown";
export { Timeline, TimelineItemFrame } from "./Timeline";
export { MessageItem, ToolItem, InteractionItem, NoticeItem } from "./timeline-items";// @bb/thread-ui/app
export function useComposer(): ComposerHandle;
export function useComposerView(): ComposerProps;
export function useThreadList(): ThreadListProps;// @bb/thread-ui/interactions
export {
ASK_USER_QUESTION_RENDERER_ID,
SECRET_REQUEST_RENDERER_ID,
interactionPayloadSchema,
interactionResponseSchema,
secretRequestPayloadSchema,
secretRequestResponseSchema,
};
export type {
InteractionOption,
InteractionQuestion,
InteractionPayload,
InteractionAnswer,
InteractionResponse,
SecretRequestPayload,
SecretRequestResponse,
};Module imports select this exact implementation. Surface contracts follow the user's current winner.
Host roles
bb.thread-ui declares no host role. It uses domain services through declared edges.
Example
This plugin adds a review panel, a composer action, a send check, and a timeline item.
// bb.plugin.jsonc
{
"id": "acme.review",
"version": "2.0.0",
"claims": [
{ "surface": "bb.thread-ui.sidePanels" },
{ "surface": "bb.thread-ui.composer.actions" },
{ "surface": "bb.thread-ui.composer.send" },
{ "surface": "bb.thread-ui.timeline.item", "key": "acme.review/review" }
],
"requires": [{ "service": "bb.threads", "range": "^1" }],
"artifacts": {
"app": "./dist/app.js",
"server": "./dist/server.js"
}
}// src/app.tsx
import { definePlugin } from "@get-bb/plugin/app";
import { ReviewItem, ReviewPanel } from "./components";
export default definePlugin((api) => {
api.surfaces.provide("bb.thread-ui.sidePanels", {
id: "acme.review/panel",
title: "Review",
placement: "thread",
component: ReviewPanel,
});
api.surfaces.provide("bb.thread-ui.composer.actions", {
id: "acme.review/request",
placement: "plus-menu",
title: "Request review",
run: ({ composer }) => composer.setText("Please review this change. "),
});
api.surfaces.provide("bb.thread-ui.composer.send", {
id: "acme.review/require-summary",
order: 550,
when: ({ draft }) => draft.text.startsWith("/review"),
async run(context, next) {
if (context.draft.text.trim() === "/review") {
return { status: "blocked", code: "acme.review/summary", reason: "Add a review summary." };
}
return next();
},
});
api.surfaces.provide("bb.thread-ui.timeline.item", {
key: "acme.review/review",
component: ReviewItem,
});
});The side-panel claim works while the active view declares bb.thread-ui.sidePanels.
A replacement view can omit that child. The other three claims continue because the plugin root declares their surfaces.
Covers
| old item ID | new contract/verb | note |
|---|---|---|
app.components.ThreadChat |
@bb/thread-ui/components: ThreadChat |
The exact component remains available as a module export. |
app.components.Markdown |
@bb/thread-ui/components: Markdown |
The chat Markdown component remains available as a module export. |
app.components.experimental_NewThreadComposer |
@bb/thread-ui/components: NewThreadComposer |
The stable export removes the experimental prefix. |
app.hooks.useComposer |
@bb/thread-ui/app: useComposer() |
The hook returns the shared composer handle. |
app.hooks.useComposerView |
@bb/thread-ui/app: useComposerView() |
The hook reads the active composer props. |
app.hooks.experimental_useSidebarThreads |
bb.thread-ui.list surface: ThreadListProps.state |
The surface receives the typed list state. |
app.hooks.experimental_useSidebarThreadActions |
bb.thread-ui.list surface: ThreadListProps.actions |
The surface receives the typed list actions. |
app.hooks.experimental_useSidebarThreadPullRequest |
bb.thread-ui.list surface: ThreadSummary and view wrappers |
A list winner can add thread status data through its own service. |
app.hooks.experimental_useSidebarThreadSplit |
bb.thread-ui.list surface: ThreadListProps.actions.open() |
The open action selects current or split placement. |
app.slots.threadPanelAction |
bb.thread-ui.sidePanels surface |
A list contribution provides the thread launcher and body. |
app.slots.experimental_newThreadPanelAction |
bb.thread-ui.sidePanels surface |
The placement field selects the new-thread context. |
app.slots.pendingInteraction |
bb.thread-ui.timeline.item surface and bb.threads interactions service |
The keyed item component shows pending and final states. |
app.slots.experimental_threadList |
bb.thread-ui.list surface |
The single surface uses the global winner store. |
app.slots.experimental_threadHeaderAction |
bb.thread-ui.view surface: ThreadViewProps.headerActions |
A view winner can wrap Original and add typed actions. |
app.slots.messageDirective |
bb.thread-ui.timeline.item surface |
A plugin-owned directive becomes a plugin-owned item type. |
app.slots.messageAction |
bb.thread-ui.view surface: ThreadViewProps.messageActions |
A view wrapper or ThreadChat instance adds typed actions. |
app.slots.experimental_timelineRenderer |
bb.thread-ui.timeline.item surface |
The keyed surface selects one winner for each item type. |
app.composer |
bb.thread-ui.composer.actions surface and ComposerHandle |
Separate contracts replace the customization bundle. |
app.composer.customize |
bb.thread-ui.composer.actions surface |
Each old bundle entry becomes one ordered contribution. |
app.contracts.PluginThreadPanelProps |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginNewThreadPanelProps |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginPendingInteractionView |
bb.thread-ui.timeline.item surface: InteractionItemProps |
The keyed timeline component displays the interaction. |
app.contracts.PluginPendingInteractionProps |
bb.thread-ui.timeline.item surface: InteractionItemProps |
The keyed timeline component displays the interaction. |
app.contracts.PluginThreadPanelActionRegistration |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginThreadPanelActionContext.openPanel |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginNewThreadPanelActionRegistration |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginNewThreadPanelActionContext.openPanel |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginPendingInteractionRegistration |
bb.thread-ui.timeline.item surface: InteractionItemProps |
The keyed timeline component displays the interaction. |
app.contracts.PluginThreadListRegistration |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginMessageDirectiveRegistration |
bb.thread-ui.timeline.item surface: plugin-owned directive item type |
The timeline item contract carries message and thread identity. |
app.contracts.PluginMessageActionRegistration |
bb.thread-ui.view surface: MessageAction |
A view wrapper or ThreadChat instance supplies the action. |
app.contracts.PluginMessageActionContext.openPanel |
bb.thread-ui.view surface: MessageAction |
A view wrapper or ThreadChat instance supplies the action. |
app.contracts.PluginTimelineRendererRegistration |
bb.thread-ui.timeline.item surface: TimelineItem and TimelineItemProps |
The keyed contract uses the canonical item type. |
app.contracts.PluginTimelineRendererProps |
bb.thread-ui.timeline.item surface: TimelineItem and TimelineItemProps |
The keyed contract uses the canonical item type. |
app.contracts.PluginThreadListProps |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginMessageDirectiveProps |
bb.thread-ui.timeline.item surface: plugin-owned directive item type |
The timeline item contract carries message and thread identity. |
app.contracts.PluginMessageDirectiveMessage |
bb.thread-ui.timeline.item surface: plugin-owned directive item type |
The timeline item contract carries message and thread identity. |
app.contracts.ThreadChatMessageReference |
@bb/thread-ui/components: ThreadChat and its props |
The exact component export keeps instance actions. |
app.contracts.PluginTargetedPanelActionOpenOptions |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginSidebarThreadsState |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarThread |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarThreadActions |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarThreadActions.open |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarThreadActions.openNewThread |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarThreadActions.setPinned |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarThreadActions.setRead |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarThreadActions.rename |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarThreadActions.archive |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarThreadActions.requestDelete |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarThreadPullRequestState |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarPullRequest |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarSplit |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginTimelineRowPresentation |
bb.thread-ui.timeline.item surface: TimelineItem and TimelineItemProps |
The keyed contract uses the canonical item type. |
app.contracts.PluginTimelineRendererRow |
bb.thread-ui.timeline.item surface: TimelineItem and TimelineItemProps |
The keyed contract uses the canonical item type. |
app.contracts.PluginTimelineRowStatus |
bb.thread-ui.timeline.item surface: TimelineItem and TimelineItemProps |
The keyed contract uses the canonical item type. |
app.composer.ComposerCustomization |
bb.thread-ui.composer.actions surface: ComposerActionContribution |
Each action, menu row, or card becomes one contribution. |
app.composer.ComposerPlusMenuItem |
bb.thread-ui.composer.actions surface: plus-menu contribution |
The list contribution keeps the action behavior. |
app.composer.ComposerPlusMenuItem.run |
bb.thread-ui.composer.actions surface: plus-menu contribution |
The list contribution keeps the action behavior. |
app.composer.ComposerView |
bb.thread-ui.composer surface: ComposerProps |
The surface props expose reactive composer state. |
app.composer.ComposerRichTextSpec |
@bb/thread-ui/components: ComposerHandle.setTextEffect() |
The composer handle owns text effects. |
app.composer.PluginComposerApi |
@bb/thread-ui/components: ComposerHandle |
The shared handle keeps imperative composer operations. |
app.composer.PluginComposerApi.setText |
@bb/thread-ui/components: ComposerHandle.setText |
The shared handle keeps imperative composer operations. |
app.composer.PluginComposerApi.updateText |
@bb/thread-ui/components: ComposerHandle.updateText |
The shared handle keeps imperative composer operations. |
app.composer.PluginComposerApi.clear |
@bb/thread-ui/components: ComposerHandle.clear |
The shared handle keeps imperative composer operations. |
app.composer.PluginComposerApi.setTextEffect |
@bb/thread-ui/components: ComposerHandle.setTextEffect |
The shared handle keeps imperative composer operations. |
app.composer.PluginComposerApi.setInputLock |
@bb/thread-ui/components: ComposerHandle.setInputLock |
The shared handle keeps imperative composer operations. |
app.composer.PluginComposerApi.addQuote |
@bb/thread-ui/components: ComposerHandle.addQuote |
The shared handle keeps imperative composer operations. |
app.composer.PluginComposerApi.insertMention |
@bb/thread-ui/components: ComposerHandle.insertMention |
The shared handle keeps imperative composer operations. |
app.composer.PluginComposerApi.focus |
@bb/thread-ui/components: ComposerHandle.focus |
The shared handle keeps imperative composer operations. |
app.contracts.ThreadChatProps |
@bb/thread-ui/components: ThreadChat and its props |
The exact component export keeps instance actions. |
app.contracts.ThreadChatMessageAction |
@bb/thread-ui/components: ThreadChat and its props |
The exact component export keeps instance actions. |
app.contracts.NewThreadRequest |
@bb/thread-ui/components: NewThreadComposer and ComposerProps |
The component uses the shared draft and selection contracts. |
app.contracts.NewThreadComposerProps |
@bb/thread-ui/components: NewThreadComposer and ComposerProps |
The component uses the shared draft and selection contracts. |
app.contracts.NewThreadComposerProps.onSubmit |
@bb/thread-ui/components: NewThreadComposer and ComposerProps |
The component uses the shared draft and selection contracts. |
app.contracts.MarkdownProps |
@bb/thread-ui/components: Markdown and MarkdownProps |
The chat Markdown component remains an exact export. |
app.composer.PluginComposerTextEffect |
@bb/thread-ui/components: ComposerHandle.setTextEffect() |
|
app.interaction-contracts |
@bb/thread-ui/interactions exports |
Shared schemas remain available to native clients. |
app.interactions.ASK_USER_QUESTION_RENDERER_ID |
@bb/thread-ui/interactions: ASK_USER_QUESTION_RENDERER_ID |
The interaction export keeps the shared wire shape. |
app.interactions.SECRET_REQUEST_RENDERER_ID |
@bb/thread-ui/interactions: SECRET_REQUEST_RENDERER_ID |
The interaction export keeps the shared wire shape. |
app.interactions.MAX_QUESTIONS |
@bb/thread-ui/interactions: MAX_QUESTIONS |
The interaction export keeps the shared wire shape. |
app.interactions.MAX_OPTIONS |
@bb/thread-ui/interactions: MAX_OPTIONS |
The interaction export keeps the shared wire shape. |
app.interactions.MAX_OPTION_PREVIEW_LENGTH |
@bb/thread-ui/interactions: MAX_OPTION_PREVIEW_LENGTH |
The interaction export keeps the shared wire shape. |
app.interactions.interactionPayloadSchema |
@bb/thread-ui/interactions: interactionPayloadSchema |
The interaction export keeps the shared wire shape. |
app.interactions.interactionResponseSchema |
@bb/thread-ui/interactions: interactionResponseSchema |
The interaction export keeps the shared wire shape. |
app.interactions.secretRequestPayloadSchema |
@bb/thread-ui/interactions: secretRequestPayloadSchema |
The interaction export keeps the shared wire shape. |
app.interactions.secretRequestResponseSchema |
@bb/thread-ui/interactions: secretRequestResponseSchema |
The interaction export keeps the shared wire shape. |
app.interactions.InteractionOption |
@bb/thread-ui/interactions: InteractionOption |
The interaction export keeps the shared wire shape. |
app.interactions.InteractionQuestion |
@bb/thread-ui/interactions: InteractionQuestion |
The interaction export keeps the shared wire shape. |
app.interactions.InteractionPayload |
@bb/thread-ui/interactions: InteractionPayload |
The interaction export keeps the shared wire shape. |
app.interactions.InteractionAnswer |
@bb/thread-ui/interactions: InteractionAnswer |
The interaction export keeps the shared wire shape. |
app.interactions.InteractionResponse |
@bb/thread-ui/interactions: InteractionResponse |
The interaction export keeps the shared wire shape. |
app.interactions.SecretRequestPayload |
@bb/thread-ui/interactions: SecretRequestPayload |
The interaction export keeps the shared wire shape. |
app.interactions.SecretRequestResponse |
@bb/thread-ui/interactions: SecretRequestResponse |
The interaction export keeps the shared wire shape. |
app.replacement.threadListPreference |
kernel winner store: bb.thread-ui.list |
The global winner replaces the client local-storage preference. |
app.contracts.PluginThreadHeaderActionProps |
bb.thread-ui.view surface: ThreadViewProps.headerActions |
A view winner can wrap Original. |
app.contracts.PluginThreadHeaderActionRegistration |
bb.thread-ui.view surface: ThreadViewProps.headerActions |
A view winner can wrap Original. |
app.contracts.PluginSidebarThreadIndicator |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarWorkspaceKind |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarThreadActivity |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarProject |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginSidebarSplitPane |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginMessageActionContext |
bb.thread-ui.view surface: MessageAction |
A view wrapper or ThreadChat instance supplies the action. |
app.contracts.PluginComposerThreadRowStatus |
bb.thread-ui.composer surface and @bb/thread-ui/components: ComposerHandle |
The surface and handle split state from local focus actions. |
app.contracts.PluginThreadPanelActionContext |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginNewThreadPanelActionContext |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.interactions.secretNameSchema |
@bb/thread-ui/interactions: secretNameSchema |
The interaction export keeps the shared wire shape. |
app.contracts.PluginThreadPanelProps.threadId |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginThreadPanelProps.params |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginNewThreadPanelProps.projectId |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginNewThreadPanelProps.params |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginPendingInteractionProps.interaction |
bb.thread-ui.timeline.item surface: InteractionItemProps |
The keyed timeline component displays the interaction. |
app.contracts.PluginPendingInteractionProps.submit |
bb.thread-ui.timeline.item surface: InteractionItemProps |
The keyed timeline component displays the interaction. |
app.contracts.PluginPendingInteractionProps.cancel |
bb.thread-ui.timeline.item surface: InteractionItemProps |
The keyed timeline component displays the interaction. |
app.contracts.PluginThreadListProps.activeThreadId |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginThreadListProps.activeProjectId |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginThreadListProps.isCompactViewport |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginThreadListProps.onNavigate |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginThreadListProps.searchQuery |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginThreadListProps.Original |
bb.thread-ui.list surface: ThreadListProps and ThreadSummary |
The list surface receives data and actions through typed props. |
app.contracts.PluginThreadHeaderActionProps.threadId |
bb.thread-ui.view surface: ThreadViewProps.headerActions |
A view winner can wrap Original. |
app.contracts.PluginThreadHeaderActionProps.projectId |
bb.thread-ui.view surface: ThreadViewProps.headerActions |
A view winner can wrap Original. |
app.contracts.PluginThreadHeaderActionProps.isCompactViewport |
bb.thread-ui.view surface: ThreadViewProps.headerActions |
A view winner can wrap Original. |
app.contracts.PluginMessageDirectiveProps.attributes |
bb.thread-ui.timeline.item surface: plugin-owned directive item type |
The timeline item contract carries message and thread identity. |
app.contracts.PluginMessageDirectiveProps.source |
bb.thread-ui.timeline.item surface: plugin-owned directive item type |
The timeline item contract carries message and thread identity. |
app.contracts.PluginMessageDirectiveProps.message |
bb.thread-ui.timeline.item surface: plugin-owned directive item type |
The timeline item contract carries message and thread identity. |
app.contracts.PluginMessageDirectiveMessage.id |
bb.thread-ui.timeline.item surface: plugin-owned directive item type |
The timeline item contract carries message and thread identity. |
app.contracts.PluginMessageDirectiveMessage.threadId |
bb.thread-ui.timeline.item surface: plugin-owned directive item type |
The timeline item contract carries message and thread identity. |
app.contracts.PluginMessageDirectiveMessage.turnId |
bb.thread-ui.timeline.item surface: plugin-owned directive item type |
The timeline item contract carries message and thread identity. |
app.contracts.PluginMessageDirectiveMessage.projectId |
bb.thread-ui.timeline.item surface: plugin-owned directive item type |
The timeline item contract carries message and thread identity. |
app.contracts.PluginThreadPanelActionRegistration.id |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginThreadPanelActionRegistration.title |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginThreadPanelActionRegistration.icon |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginThreadPanelActionRegistration.component |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginThreadPanelActionRegistration.run |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginNewThreadPanelActionRegistration.id |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginNewThreadPanelActionRegistration.title |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginNewThreadPanelActionRegistration.icon |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginNewThreadPanelActionRegistration.component |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginNewThreadPanelActionRegistration.run |
bb.thread-ui.sidePanels surface: ThreadSidePanelContribution and ThreadSidePanelProps |
One list contract replaces panel action and panel body records. |
app.contracts.PluginMessageActionRegistration.run |
bb.thread-ui.view surface: MessageAction |
A view wrapper or ThreadChat instance supplies the action. |
app.contracts.PluginTimelineRendererRegistration.kind |
bb.thread-ui.timeline.item surface: TimelineItem and TimelineItemProps |
The keyed contract uses the canonical item type. |
app.contracts.PluginTimelineRendererRegistration.component |
bb.thread-ui.timeline.item surface: TimelineItem and TimelineItemProps |
The keyed contract uses the canonical item type. |