System Prompt Editor
A controlled system-prompt editor with quick-pick presets composed via Option List — value in, onChange out; persistence stays in the consumer.
System Prompt Editor
The System Prompt Editor is a controlled editor for a chat/completion system
prompt with quick-pick presets. Selecting a preset replaces the textarea value;
free-form edits that match no preset deselect all presets. It composes the
Option List primitive for the presets and
exports SYSTEM_PROMPT_PRESETS and DEFAULT_SYSTEM_PROMPT as sensible defaults.
Presentational (value in,
onChangeout). Persistence and model wiring stay in the consumer — the editor never touches storage. Recommended destination: thesystemPromptyou pass touseChat/useGenerateText(a recommendation, never a requirement).
When to use it: any chat or generation surface that lets the user set or switch the assistant's system prompt with a few opinionated presets.
Preview
Installation
pnpm dlx shadcn@latest add @localmode/ui/input-controls/system-prompt-editornpx shadcn@latest add @localmode/ui/input-controls/system-prompt-editoryarn dlx shadcn@latest add @localmode/ui/input-controls/system-prompt-editorbunx --bun shadcn@latest add @localmode/ui/input-controls/system-prompt-editorDependencies
- Data source: fully controlled — emits
onChange(value); the consumer owns persistence and applies the value to a model. Recommended destination:useChat/useGenerateTextsystemPrompt(optional). clsx+tailwind-merge— via the sharedcn()util (installed automatically as a registry dependency)- Composes
@localmode/ui/input-controls/option-list(installed automatically as a registry dependency)
Files installed
system-prompt-editor.tsx— the component (exportsSYSTEM_PROMPT_PRESETS,DEFAULT_SYSTEM_PROMPT)option-list.tsx— the composed preset listlib/utils.ts— thecn()helper (if not already present)
Props
SystemPromptEditor
Prop
Type
SystemPromptPreset
Prop
Type
Examples
Wire to a chat system prompt (consumer owns persistence)
import { useState } from 'react';
import {
SystemPromptEditor,
DEFAULT_SYSTEM_PROMPT,
} from '@/components/system-prompt-editor';
export function PromptPanel() {
const [prompt, setPrompt] = useState(
() => localStorage.getItem('systemPrompt') ?? DEFAULT_SYSTEM_PROMPT,
);
return (
<SystemPromptEditor
value={prompt}
onChange={(v) => {
setPrompt(v);
localStorage.setItem('systemPrompt', v); // persistence is yours
}}
/>
);
}Extend the presets
SYSTEM_PROMPT_PRESETS is exported — spread it and add your own before rendering,
or edit the copied file directly.
Accessible name
The textarea carries an aria-label (default "System prompt") so it has a
programmatic name independent of the visible heading. Override ariaLabel if
your surrounding copy names the field differently.
<SystemPromptEditor value={prompt} onChange={setPrompt} ariaLabel="Assistant instructions" />Customization
The editor is purely presentational: value in, onChange out. Because you own
the copied file, add or remove presets, change the textarea rows, or attach your
own persistence and useChat wiring — the primitive stays free of orchestration
state.
Copy Button
A copy-to-clipboard button with a 2-second Copied confirmation that disables when there is nothing to copy and no-ops on an unavailable clipboard.
Model Downloader
The headline local-first card a user sees while a model loads on-device — name, size, context, live progress, and cached-vs-downloading copy.