Editable
An edit-in-place text field that swaps a preview for an input.
Edit contract
Anatomy
Editable
├── EditableArea
│ ├── EditablePreview
│ └── EditableInput
└── EditableControl
├── EditableEditTrigger
├── EditableCancelTrigger
└── EditableSubmitTriggerUsage
import {
Editable,
EditableArea,
EditableCancelTrigger,
EditableControl,
EditableEditTrigger,
EditableInput,
EditablePreview,
EditableSubmitTrigger,
} from "@kanzo-tech/ui";<Field>
<FieldLabel>Contract title</FieldLabel>
<Editable defaultValue="A wyrm under the granary">
<EditableArea>
<EditableInput asChild>
<Input />
</EditableInput>
<EditablePreview />
</EditableArea>
<EditableControl>
<EditableCancelTrigger asChild>
<Button aria-label="Cancel" size="icon-md" variant="outline">
<XIcon />
</Button>
</EditableCancelTrigger>
<EditableSubmitTrigger asChild>
<Button aria-label="Save" size="icon-md" variant="outline">
<CheckIcon />
</Button>
</EditableSubmitTrigger>
</EditableControl>
</Editable>
</Field>EditableInput and the triggers render bare: compose them over a styled Input (or Textarea)
and Button with asChild. Inside a Field, the label points at the input and the field's
disabled, invalid, readOnly and required reach the editable. Ark shows the edit trigger at
rest and the submit/cancel pair while editing, so neither needs a conditional.
Controlled
edit puts a whole form into edit mode at once; value and onValueChange control the value.
Edit contract
Modes
activationMode decides what starts editing.
Focus
The default: editing starts when the preview takes focus, by click or by Tab.
Edit with focus
Click
Edit with click
Double-click
Edit with double-click
None
Nothing on the preview starts editing; EditableEditTrigger does.
Edit with a trigger
Submit modes
submitMode decides what saves: "both" (the default) saves on Enter and on clicking away,
"enter" reverts on clicking away, "blur" ignores Enter, and "none" leaves it to
EditableSubmitTrigger. Escape always cancels.
Enter or clicking away saves.
Only Enter saves; clicking away reverts.
Only clicking away saves; Enter does nothing.
Sizes
size on EditablePreview is the height of the control it stands in for — sm, md, lg or
xl. Give the Input the same size, so nothing moves when the two swap.
Small
Large
Truncation
Over an Input the preview is one line: a value wider than its box ends in an ellipsis and carries
the whole value as its title, which appears only once it is cut off. Bound the width on the root
— the preview needs no classes of its own. This is a name inline in a header strip:
Orientation
orientation lays out EditableControl: its triggers in a row, or stacked and aligned to the end
of the area — the arrangement a textarea wants.
Horizontal
Vertical
Examples
With Textarea
Over a Textarea the preview wraps and grows instead of truncating.
Edit briefing
Without Controls
No triggers: Enter saves, Escape cancels.
Edit without controls
API Reference
Editable
Root. Manages edit mode and the value.
| Prop | Type | Default |
|---|---|---|
activationMode | "focus" | "click" | "dblclick" | "none" | "focus" |
submitMode | "both" | "enter" | "blur" | "none" | "both" |
orientation | "horizontal" | "vertical" | "horizontal" |
selectOnFocus | boolean | true |
orientation is ours, mirrored to data-orientation. The rest is Ark's, and so is everything
React.ComponentProps<typeof ArkEditable.Root> carries: value / defaultValue,
onValueChange / onValueCommit / onValueRevert, edit / defaultEdit / onEditChange,
placeholder, maxLength, autoResize, disabled, invalid, readOnly, required, name,
form and ref.
EditablePreview
The value at rest.
| Prop | Type | Default |
|---|---|---|
size | "sm" | "md" | "lg" | "xl" | "md" |
variant | ButtonProps["variant"] | "outline" |
title | string | the value, when truncated |
It is styled with buttonVariants at clickEffect: false, so it already looks like the control it
is about to become. There is no xs, for the reason Button has none.
Other parts
EditableArea and EditableControl take their Ark part's props. EditableInput and the three
triggers render bare — pass a styled Input / Textarea or Button with asChild;
EditableInput omits the native size attribute, the way Input does.
useEditable re-exports Ark's useEditableContext.
EditableProps, EditablePreviewProps and EditableInputProps are exported, so a wrapper can
take the same props without restating them.