Spartan replacements
Components that spartan/ui now ships, or that another ngx-prompt-kit component covers, were removed. Add the spartan helm component with its CLI (ng g @spartan-ng/cli:ui) and compose it as below.
Examples
loader → hlm-spinner
pk-loader's spinner variants are hlm-spinner; its text variants are a span with spartan's shimmer utility.
<hlm-spinner />
<span class="shimmer text-sm font-medium">Thinking</span>
import { HlmSpinner } from '@spartan-ng/helm/spinner';text-shimmer → shimmer
Spartan's tailwind preset ships a shimmer utility. Tune it with --shimmer-duration, --shimmer-spread and --shimmer-color.
<span class="shimmer text-muted-foreground">Searching the web…</span>
<!-- needs spartan's preset in styles.css -->
@import '@spartan-ng/brain/hlm-tailwind-preset.css';message → hlm-message + hlm-bubble
hlmMessage lays out the row, hlmMessageAvatar the avatar, hlmBubble the bubble. Render markdown with pk-markdown inside the bubble content.
<div hlmMessage align="end">
<div hlmMessageContent>
<div hlmBubble variant="secondary">
<div hlmBubbleContent>What's the capital of France?</div>
</div>
</div>
</div>
<div hlmMessage>
<div hlmMessageAvatar>
<hlm-avatar><span hlmAvatarFallback>AI</span></hlm-avatar>
</div>
<div hlmMessageContent>
<div hlmBubble variant="muted">
<div hlmBubbleContent>
<pk-markdown [content]="reply()" />
</div>
</div>
</div>
</div>
import { HlmAvatarImports } from '@spartan-ng/helm/avatar';
import { HlmBubbleImports } from '@spartan-ng/helm/bubble';
import { HlmMessageImports } from '@spartan-ng/helm/message';system-message → hlm-alert
An out-of-band notice is an hlm-alert; put the call to action in hlmAlertAction.
<div hlmAlert>
<ng-icon name="lucideInfo" />
<h4 hlmAlertTitle>Model switched</h4>
<p hlmAlertDescription>Replies now come from a faster model.</p>
<div hlmAlertAction>
<button hlmBtn size="sm" (click)="undo()">Undo</button>
</div>
</div>
import { HlmAlertImports } from '@spartan-ng/helm/alert';chat-empty → hlm-empty
The empty state of a chat is hlm-empty; suggestions go in hlm-empty-content.
How can I help today?
Ask anything, or start from a suggestion.
<hlm-empty>
<hlm-empty-header>
<h3 hlmEmptyTitle>How can I help today?</h3>
<p hlmEmptyDescription>Ask anything, or start from a suggestion.</p>
</hlm-empty-header>
<hlm-empty-content class="flex-row flex-wrap justify-center">
@for (s of suggestions; track s) {
<button hlmBtn variant="outline" size="sm" class="rounded-full" (click)="pick(s)">
{{ s }}
</button>
}
</hlm-empty-content>
</hlm-empty>
import { HlmEmptyImports } from '@spartan-ng/helm/empty';prompt-input → hlm-input-group
A textarea in an input group with a block-end addon for the actions. For a full chat composer (autosize, Enter to send, stop button, attachments) use pk-composer.
<div hlmInputGroup class="rounded-2xl">
<textarea
hlmInputGroupTextarea
placeholder="Ask anything…"
[value]="draft()"
(input)="draft.set($any($event.target).value)"
(keydown.enter)="onEnter($event)"
></textarea>
<div hlmInputGroupAddon align="block-end" class="justify-between">
<button hlmInputGroupButton size="icon-sm" hlmTooltip="Attach" aria-label="Attach">
<ng-icon name="lucidePaperclip" />
</button>
<button hlmInputGroupButton variant="default" size="icon-sm" class="rounded-full"
aria-label="Send" (click)="send()">
<ng-icon name="lucideArrowUp" />
</button>
</div>
</div>
import { HlmInputGroupImports } from '@spartan-ng/helm/input-group';scroll-button → hlmBtn
A scroll-to-bottom button is an hlmBtn that calls the chat container. With spartan's hlm-message-scroller, use its hlmMessageScrollerButton instead.
<pk-chat-container-root #thread class="relative h-96">
<pk-chat-container-content>…</pk-chat-container-content>
</pk-chat-container-root>
<button
hlmBtn
variant="outline"
size="icon"
class="rounded-full transition-all"
[class.opacity-0]="thread.isAtBottom()"
[class.pointer-events-none]="thread.isAtBottom()"
aria-label="Scroll to bottom"
(click)="thread.scrollToBottom()"
>
<ng-icon name="lucideChevronDown" />
</button>model-picker, model-list → pk-model-selector
pk-model-selector covers both: search, maker rail, curated sections, price tiers, a bottom sheet on phones and an inline mode. For a full catalogue page use pk-model-browser.
See the Model Selector and Model Browser pages for live examples.
<pk-model-selector
[models]="models"
[sections]="sections"
[(value)]="modelId"
/>
import { PkModelSelectorImports } from 'ngx-prompt-kit/model-selector';stream-controls → hlmBtn
Swap the button on the stream state. Inside pk-composer the send button already turns into stop while busy.
@if (streaming()) {
<button hlmBtn variant="secondary" size="sm" (click)="stop()">
<ng-icon name="lucideSquare" /> Stop
</button>
} @else {
<button hlmBtn variant="ghost" size="sm" (click)="regenerate()">
<ng-icon name="lucideRefreshCw" /> Regenerate
</button>
}thinking-bar → shimmer
A status line is a span with the shimmer utility; put a stop button next to it if you need one. To show the thinking itself, use pk-reasoning or pk-chain-of-thought.
<div class="flex items-center justify-between">
<span role="status" class="shimmer text-muted-foreground font-medium">Thinking</span>
<button hlmBtn variant="link" size="sm" (click)="stop()">Answer now</button>
</div>