All blocks
Block
System notice + retry
The error-and-recover lane. A failed stream surfaces a spartan alert, the button switches to Try again, and once we recover, a feedback-bar prompts for a rating.
Error → retry → feedback
Phase:error
@switch (phase()) {
@case ('error') {
<div hlmAlert variant="destructive">
<ng-icon name="lucideCircleAlert" />
<p hlmAlertDescription>Stream failed: upstream timeout after 30s.</p>
<div hlmAlertAction>
<button hlmBtn variant="outline" size="xs" (click)="showDetails()">Details</button>
</div>
</div>
<button
hlmBtn
variant="outline"
size="sm"
type="button"
class="text-destructive border-destructive/40 hover:bg-destructive/10"
(click)="retry()"
>
<ng-icon name="lucideRotateCcw" />
Try again
</button>
}
@case ('recovering') {
<div hlmAlert>
<ng-icon name="lucideInfo" />
<p hlmAlertDescription>Retrying with the same prompt...</p>
</div>
<button hlmBtn variant="secondary" size="sm" type="button" (click)="abort()">
<ng-icon name="lucideSquare" />
Stop
</button>
}
@case ('recovered') {
<div hlmAlert>
<ng-icon name="lucideInfo" />
<p hlmAlertDescription>Response delivered.</p>
</div>
<pk-feedback-bar
title="How was that response after the retry?"
(helpful)="rate('helpful')"
(notHelpful)="rate('not-helpful')"
(closed)="showFeedback.set(false)"
/>
}
}
// Component
type Phase = 'error' | 'recovering' | 'recovered';
protected readonly phase = signal<Phase>('error');
protected retry(): void {
this.phase.set('recovering');
setTimeout(() => this.phase.set('recovered'), 1500);
}