Portfolio

Inline Edit

A click-to-edit text field. Optimistic save, escape-to-cancel, validation, async submit, and multiline mode.

Installation

bunx --bun shadcn@latest add https://ui.ahmet.studio/r/inline-edit

Usage

import { InlineEdit } from "@/components/ui/inline-edit"; export function Demo() { const [title, setTitle] = React.useState("Untitled"); return ( <InlineEdit value={title} onChange={setTitle} onSubmit={async (v) => { await fetch("/api/title", { method: "POST", body: JSON.stringify({ title: v }), }); }} required textClassName="text-lg font-semibold" /> ); }

Features

  • Click to edit — looks like text, becomes an input on click.
  • Async submit — pass onSubmit for optimistic updates with disabled-state during the request.
  • Validation — return a string from validate to show an error.
  • Multiline — set multiline for a textarea (Cmd/Ctrl+Enter to save).
  • Escape to cancel — restores the original value.
  • Custom display — pass renderDisplay to render markdown, badges, links, etc.

Props

PropTypeDefault
valuestringRequired
onChange(value: string) => voidRequired
onSubmit(value: string) => void | Promise<void>undefined
validate(value: string) => boolean | stringundefined
placeholderstring"Type something…"
emptyTextstring"Click to edit"
multilinebooleanfalse
requiredbooleanfalse
triggerOnBlur"save" | "cancel""save"
selectAllOnEditbooleantrue
showActionsbooleantrue
renderDisplay(value: string) => ReactNodeundefined