diff --git a/cockpit/chat/input/angular/src/app/input.component.ts b/cockpit/chat/input/angular/src/app/input.component.ts index 142f42d2..2a11e36a 100644 --- a/cockpit/chat/input/angular/src/app/input.component.ts +++ b/cockpit/chat/input/angular/src/app/input.component.ts @@ -1,7 +1,13 @@ // SPDX-License-Identifier: MIT import { Component, computed } from '@angular/core'; -import { ChatInputComponent as ChatInputPrimitive } from '@ngaf/chat'; -import { ChatMessageListComponent } from '@ngaf/chat'; +import { + ChatInputComponent as ChatInputPrimitive, + ChatMessageListComponent, + ChatMessageComponent, + ChatStreamingMdComponent, + MessageTemplateDirective, + messageContent, +} from '@ngaf/chat'; import { ExampleChatLayoutComponent } from '@ngaf/example-layouts'; import { agent } from '@ngaf/langgraph'; import { environment } from '../environments/environment'; @@ -10,11 +16,23 @@ import { environment } from '../environments/environment'; * InputComponent showcases ChatInputComponent features including * keyboard handling, disabled state, and custom placeholder. * A sidebar displays the current input state. + * + * ChatMessageListComponent renders nothing on its own — it discovers + * projected `` blocks via + * contentChildren. Templates are projected here so the conversation + * surface actually displays user + assistant turns. */ @Component({ selector: 'app-input', standalone: true, - imports: [ChatInputPrimitive, ChatMessageListComponent, ExampleChatLayoutComponent], + imports: [ + ChatInputPrimitive, + ChatMessageListComponent, + ChatMessageComponent, + ChatStreamingMdComponent, + MessageTemplateDirective, + ExampleChatLayoutComponent, + ], template: `
@@ -22,7 +40,27 @@ import { environment } from '../environments/environment';

Chat Input Demo

- + + + {{ messageContent(message) }} + + + + + + + + + {{ messageContent(message) }} + +
@@ -59,6 +97,7 @@ export class InputComponent { protected readonly streamStatus = computed(() => this.agent.status()); protected readonly isLoading = computed(() => this.agent.isLoading()); + protected readonly messageContent = messageContent; submitMessage(content: string) { this.agent.submit({ message: content }); diff --git a/cockpit/chat/messages/angular/src/app/messages.component.ts b/cockpit/chat/messages/angular/src/app/messages.component.ts index 516d7f0d..259fad8a 100644 --- a/cockpit/chat/messages/angular/src/app/messages.component.ts +++ b/cockpit/chat/messages/angular/src/app/messages.component.ts @@ -4,6 +4,10 @@ import { ChatMessageListComponent, ChatInputComponent, ChatTypingIndicatorComponent, + ChatMessageComponent, + ChatStreamingMdComponent, + MessageTemplateDirective, + messageContent, } from '@ngaf/chat'; import { ExampleChatLayoutComponent } from '@ngaf/example-layouts'; import { agent } from '@ngaf/langgraph'; @@ -15,11 +19,25 @@ import { environment } from '../environments/environment'; * Uses ChatMessageListComponent, ChatInputComponent, and ChatTypingIndicatorComponent * individually rather than the composed ChatComponent, giving full control * over layout and message rendering. + * + * ChatMessageListComponent renders nothing on its own — it discovers + * projected `` blocks via + * contentChildren and uses them per message type. The composed `` + * component provides default templates internally; primitive consumers + * must project them explicitly. */ @Component({ selector: 'app-messages', standalone: true, - imports: [ChatMessageListComponent, ChatInputComponent, ChatTypingIndicatorComponent, ExampleChatLayoutComponent], + imports: [ + ChatMessageListComponent, + ChatInputComponent, + ChatTypingIndicatorComponent, + ChatMessageComponent, + ChatStreamingMdComponent, + MessageTemplateDirective, + ExampleChatLayoutComponent, + ], template: `
@@ -27,7 +45,27 @@ import { environment } from '../environments/environment';

Chat Messages Primitives

- + + + {{ messageContent(message) }} + + + + + + + + + {{ messageContent(message) }} + +
@@ -52,6 +90,8 @@ export class MessagesComponent { assistantId: environment.streamingAssistantId, }); + protected readonly messageContent = messageContent; + submitMessage(content: string) { this.agent.submit({ message: content }); }