React Inline Ghost-Text Assist

The completion pattern people know from their editor, brought to a form field: a greyed suggestion trails the cursor, Tab takes it, and typing carries on as if it were never there. It stays out of the way — a suggestion you can ignore by continuing to type, never a modal you have to dismiss.

Tabto accept the suggestion

Try continuing the sentence, or type a new line beginning “I recommend”, “Root cause”, or “Next steps”. Press Tab to accept the greyed suggestion.

Installation

npx shadcn@latest add "http://localhost:3000/registry/ghost-text.json"

Props

PropTypeDescription
getSuggestion(value: string) => stringReturns the completion suffix, or ""
defaultValuestringInitial text
placeholderstringEmpty-field placeholder
rowsnumberTextarea height
onAccept(value) => voidFires when a suggestion is accepted

The overlay-mirror trick

A textarea can't render two colours of text, so the ghost lives in a second element: an overlay mirror positioned exactly behind the textarea, sharing its font, padding, and line metrics to the pixel. The mirror renders an invisible copy of what you typed — present only to take up the same space — followed by the greyed completion. The real textarea sits transparent on top, so you see your own text and caret from it and the ghost from the mirror, perfectly aligned, with no second editable surface to keep in sync.

The ghost only appears when the caret is at the end of the text — completing from the middle is a different, more ambiguous interaction, and pretending otherwise puts suggestions where they don't belong. Caret position is tracked on every key and click, so moving into the text hides the ghost until you return to the end.

Suggestion is a function, model is optional

The component knows nothing about where completions come from — it calls getSuggestion(value) and renders whatever string comes back. In the demo that's a lookup keyed on how the sentence ends; in production it's a debounced call to your model, and nothing else changes. Tab accepts, Esc dismisses until the next keystroke, and typing past a suggestion simply replaces it — the three behaviours a ghost-text field has to get right so it assists without ever interrupting.

New components every week

Get the week's new Kelvin UI components and templates in one short email. No spam, unsubscribe anytime.