Marble UI
← Components

Editable (inline edit)

Preview: Default

Click-to-edit text. Preview is a button ("Edit <label>"); Enter saves, Escape cancels, blur saves. `size` sets the preview's text style (heading vs body). Saving an empty value clears it unless `required`, which keeps the old value. Enter and Escape return focus to the preview.

Import

import { Editable } from '@marbleui/ui'

Props

<Editable>

PropTypeDefaultDescription
label *requiredstring—
onChange *required(v: string) => void—
value *requiredstring—
classNamestring—
placeholderstring'Empty'
requiredboolean—
size'md' | 'lg''md'

Accessibility

Keyboard interaction, focus management and ARIA semantics come from the underlying primitives: React Aria Button · React Aria Input · React Aria TextField. Follow the primitive's docs for the full keyboard map.

Usage notes

Click-to-edit text for titles and short values that are read more often than changed. For a field that is always editable use TextField.

const [title, setTitle] = useState('Q4 planning')
<Editable size="lg" label="Title" value={title} onChange={setTitle} />
<Editable label="Description" placeholder="Add a description…" value={description} onChange={setDescription} />
  • Controlled only: value and onChange are required. onChange fires on save (even if nothing changed), not on each keystroke.
  • The preview is a button announced as “Edit Title: Q4 planning”. Enter or blur saves; Escape cancels. After Enter or Escape focus returns to the preview.
  • Saved text is trimmed. An empty edit clears the value; with required it restores the previous value instead.
  • Single line only. size="lg" gives heading-sized text; placeholder (default “Empty”) shows when the value is blank.
Example source · show
import { useState } from 'react'
import { Editable } from './editable'

function Demo() {
  const [title, setTitle] = useState('Q4 planning')
  const [desc, setDesc] = useState('')
  return <div className="flex w-80 flex-col gap-2"><Editable size="lg" label="Title" value={title} onChange={setTitle} /><Editable label="Description" placeholder="Add a description…" value={desc} onChange={setDesc} /></div>
}
export const styles = { Default: Demo }

Source: packages/ui/src/editable/editable.tsx

Catalog

Category
inputs
Priority
Extra
Primitive
composed
React Aria
TextField
Base UI
Input