VisorVisor
ComponentsForm

InlineEdit

Inline-editable text — the text, then a pencil. A click or Enter turns it into an input in place, at the same size; Enter, blur or Tab commits, Escape restores, and clearing it brings back a muted default.

npx visor add inline-edit

Default

The text, then a pencil. Click either one (or press Enter on the pencil) and an input takes the text's place at the same size, so nothing below it moves. A long title wraps; it is never truncated.

Technical rider

A heading, with a default

as sets the element, and the type comes with it: here an h2 at the editor's 21px display size. While value is empty, defaultValue shows, muted. Clear the text and commit, and onCommit("") is called and the default comes back.

Track record

Keyboard

KeyAction
Enter (on the pencil)Opens the input, with the text selected
EnterCommits, and returns focus to the pencil
TabCommits, and moves on to the next field
EscapeRestores the text without committing

Blur commits too. onCommit receives the trimmed text, and is not called when nothing changed.

Edges

At rest, InlineEdit is text and a pencil, with no edge. While editing, the input draws its resting edge from the shared control-edge tokens, never from border, so --control-edge-width: 0 turns it off with every other form control. Focus still draws its own ring.

Theming

The pencil is the same mark as an icon-only Button: it reads --button-icon-size (the glyph), --button-icon-pad (the hit target, drawn on ::before so it adds no height to the line) and --button-icon-ghost-color (the ink at rest). The default's muted colour is --text-tertiary.

The input takes its size, weight and line height from font: inherit, which comes from Visor's element reset (@import "@loworbitstudio/visor-core/reset"), as it does for every form control. Tailwind's preflight sets the same thing.

When not to use

Installation

npx visor add inline-edit

This copies two files into your project:

  • components/ui/inline-edit/inline-edit.tsx: the component
  • components/ui/inline-edit/inline-edit.module.css: the styles

API Reference

InlineEditProps

PropTypeDefaultDescription
value*stringThe committed text. An empty string means no override, and `defaultValue` shows instead.
onCommit*(value: string) => voidCalled with the trimmed text on Enter, blur or Tab, only when it differs from `value`. An empty string means "restore the default". The parent updates `value`.
label*stringThe field's name (e.g. "Section title"). Names the input, and the pencil as "Edit {label}".
defaultValuestring''Shown, muted, while `value` is empty, and used as the input's placeholder.
as'span' | 'div' | 'p' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6''span'The element to render. Typography inherits from it, so a title keeps its heading's size and colour.
editLabelstringAccessible name of the pencil. Defaults to "Edit {label}".
defaultEditingbooleanfalseOpens in the editing state on mount, without moving focus.

InlineEdit also accepts the standard HTML attributes of the element it renders.