Inline edit
Text that turns into a one-line field on click. Enter or leaving the field saves; Escape cancels. It takes the font of the text around it, so it works in a heading or a table cell.
import { useState } from "react";
import { Text } from "@etched/reticle/text";
import { InlineEdit } from "@etched/reticle/inline-edit";
export function Preview() {
const [name, setName] = useState("Ana Ruiz");
return (
<Text as="h3" variant="heading" size="lg">
<InlineEdit aria-label="Name" value={name} onSave={setName} />
</Text>
);
}Installation
import { InlineEdit } from "@etched/reticle/inline-edit";Examples
Name, title and company
Click the text, or press Enter on it. Enter or leaving the field saves; Escape cancels.
at
import { useState } from "react";
import { Text } from "@etched/reticle/text";
import { InlineEdit } from "@etched/reticle/inline-edit";
export function NameTitleAndCompany() {
const [person, setPerson] = useState({ name: "José Núñez", title: "", company: "Tenstorrent" });
return (
<div className="grid">
<Text as="h3" variant="heading" size="lg">
<InlineEdit aria-label="Name" value={person.name} onSave={(name) => setPerson({ ...person, name })} />
</Text>
<Text as="p">
<InlineEdit aria-label="Title" placeholder="Add a title" value={person.title} onSave={(title) => setPerson({ ...person, title })} />
{" at "}
<InlineEdit aria-label="Company" value={person.company} onSave={(company) => setPerson({ ...person, company })} />
</Text>
</div>
);
}Errors and slow saves
Throw from onSave to show a message: the field stays open with the typed text. A slow save shows the field as busy.
import { useState } from "react";
import { InlineEdit } from "@etched/reticle/inline-edit";
export function ErrorsAndSlowSaves() {
const [name, setName] = useState("Lee Park");
const save = async (next: string) => {
if (!next.trim()) throw new Error("Enter a name.");
await new Promise((done) => setTimeout(done, 600));
setName(next.trim());
};
return <InlineEdit aria-label="Name" value={name} onSave={save} />;
}Opened from outside
editing and onEditingChange let the app open the field, for example when Tab moves to the next field. Keys other than Enter and Escape bubble up from the field.
import { useState } from "react";
import { Button } from "@etched/reticle/button";
import { InlineEdit } from "@etched/reticle/inline-edit";
export function OpenedFromOutside() {
const [title, setTitle] = useState("Thermal engineer");
const [editing, setEditing] = useState(false);
return (
<div className="row">
<InlineEdit aria-label="Title" value={title} onSave={setTitle} editing={editing} onEditingChange={setEditing} />
<Button size="sm" onClick={() => setEditing(true)}>
Edit title
</Button>
</div>
);
}In a table
In a one-line table (Table truncate), long text is cut with an ellipsis; the field shows all of it.
| Ana Ruiz |
import { useState } from "react";
import { Table } from "@etched/reticle/table";
import { InlineEdit } from "@etched/reticle/inline-edit";
export function InATable() {
const [title, setTitle] = useState("Distributed Systems Engineer, Infrastructure and Platform Reliability");
return (
<Table aria-label="People" truncate style={{ inlineSize: "24rem", tableLayout: "fixed" }}>
<tbody>
<tr>
<td>Ana Ruiz</td>
<td>
<InlineEdit aria-label="Long title" value={title} onSave={setTitle} />
</td>
</tr>
</tbody>
</Table>
);
}API reference
| Prop | Type | Default | Description |
|---|---|---|---|
| value * | string | – | |
| onSave * | (value: string) => void | Promise<void> | – | Saves the new text. Throw (or reject) with a message to show it as an error; the field then stays open. Runs only when the text changed. |
| aria-label * | string | – | Names the field, for example "Name". |
| placeholder | string | – | Shown at rest while the value is empty. |
| disabled | boolean | – | |
| editing | boolean | – | Whether the field is open, to open it from outside (for example when Tab moves to the next field). Leave it out to let a click open it. |
| onEditingChange | (editing: boolean) => void | – | Called when the field opens or closes. |
| className | string | – | Class on the outer element, for layout. |