1import { ChangeDetectionStrategy, Component } from "@angular/core";
2
3import { FeatureHeaderComponent } from "../feature-header.component";
4import { HeadlessChatController } from "./headless-chat";
5import { messageText } from "./headless-message-utils";
6
7@Component({
8 selector: "showcase-headless-simple-feature",
9 imports: [FeatureHeaderComponent],
10 changeDetection: ChangeDetectionStrategy.OnPush,
11 host: { class: "feature-page" },
12 template: `
13 <showcase-feature-header />
14 <main class="headless-page" aria-label="Simple headless chat">
15 <section class="headless-panel">
16 <h2>Headless Chat (Simple)</h2>
17 <div class="headless-messages" aria-live="polite">
18 @if (messages().length === 0) {
19 <p class="headless-empty">No messages yet. Say hi!</p>
20 }
21 @for (message of messages(); track message.id) {
22 @if (message.role === "user") {
23 <div
24 class="headless-user-message"
25 data-testid="headless-message-user"
26 data-message-role="user"
27 >
28 {{ messageText(message) }}
29 </div>
30 } @else if (message.role === "assistant") {
31 <div
32 class="headless-assistant-message"
33 data-testid="headless-message-assistant"
34 data-message-role="assistant"
35 >
36 {{ messageText(message) }}
37 </div>
38 }
39 }
40 @if (isRunning()) {
41 <p class="headless-status">Agent is thinking…</p>
42 }
43 </div>
44 <div class="headless-suggestions" data-testid="headless-suggestions">
45 @for (suggestion of suggestions; track suggestion) {
46 <button
47 type="button"
48 [disabled]="isRunning()"
49 (click)="send(suggestion)"
50 >
51 {{ suggestion }}
52 </button>
53 }
54 </div>
55 @if (error()) {
56 <p
57 class="headless-error"
58 data-testid="headless-simple-error"
59 role="alert"
60 >
61 {{ error() }}
62 </p>
63 }
64 <div class="headless-composer" data-testid="headless-composer">
65 <textarea
66 rows="2"
67 aria-label="Message"
68 placeholder="Type a message"
69 [value]="inputValue()"
70 (input)="updateInput($event)"
71 (keydown)="handleComposerKeydown($event)"
72 ></textarea>
73 <button
74 type="button"
75 [disabled]="isRunning() || !inputValue().trim()"
76 (click)="send()"
77 >
78 Send
79 </button>
80 </div>
81 </section>
82 </main>
83 `,
84})
85export class HeadlessSimpleFeatureComponent extends HeadlessChatController {
86 protected readonly messageText = messageText;
87 protected readonly suggestions = [
88 "Say hello in one short sentence.",
89 "Tell me a one-line joke.",
90 "Give me a fun fact.",
91 ] as const;
92
93 constructor() {
94 super("headless-simple");
95 }
96}
97