Inline edit
A value changed where it shows - a title in a list, a name on a page - behind a real Edit button, in a small form of its own that saves or cancels.
Examples
The value has an id; the Edit button names the form by commandfor with command="--edit"; the form, of class inline-edit-form, names the value by data-for and holds the field, its Save button and a Cancel button with command="--cancel". --edit shows the form in place of the value, the field focused and its text selected; Enter saves, Esc or Cancel puts the field back, and the focus returns to the Edit button. A click elsewhere leaves the form open.
Excursions
<section class="card" aria-labelledby="inline-edit-row-title">
<div class="card-header"><h2 class="fs-14" id="inline-edit-row-title">Excursions</h2></div>
<div class="list-group list-group-flush">
<div class="list-group-item hstack gap-8">
<span class="table-title flex-fill" id="inline-edit-row-1">North Bay: marine park by speedboat</span>
<button class="btn btn-sm btn-icon btn-text" type="button" commandfor="inline-edit-row-1-form" command="--edit" aria-label="Edit the title: North Bay"><i class="bi bi-pencil" aria-hidden="true"></i></button>
<form class="inline-edit-form flex-fill" id="inline-edit-row-1-form" data-for="inline-edit-row-1" hidden>
<input class="form-control form-control-sm" name="title" value="North Bay: marine park by speedboat" aria-label="Title" required>
<button class="btn btn-sm btn-primary" type="submit">Save</button>
<button class="btn btn-sm" type="button" commandfor="inline-edit-row-1-form" command="--cancel">Cancel</button>
<div class="invalid-feedback" hidden></div>
</form>
</div>
<div class="list-group-item hstack gap-8">
<span class="table-title flex-fill" id="inline-edit-row-2">Night market and street food</span>
<button class="btn btn-sm btn-icon btn-text" type="button" commandfor="inline-edit-row-2-form" command="--edit" aria-label="Edit the title: Night market"><i class="bi bi-pencil" aria-hidden="true"></i></button>
<form class="inline-edit-form flex-fill" id="inline-edit-row-2-form" data-for="inline-edit-row-2" data-docs-save hidden>
<input class="form-control form-control-sm" name="title" value="Night market and street food" aria-label="Title">
<button class="btn btn-sm btn-primary" type="submit">Save</button>
<button class="btn btn-sm" type="button" commandfor="inline-edit-row-2-form" command="--cancel">Cancel</button>
<div class="invalid-feedback" hidden></div>
</form>
</div>
</div>
</section>Saved by the page
The form's submit fires redz:save on it, with the form and the field's value. A page that saves cancels it and answers with a promise: the Save button is busy until it settles - resolved, the value shows the saved text and the form closes; rejected with words, the form stays open, the field marked invalid and the words in its invalid-feedback, said at once. Left alone, the value shows the text and the field keeps it. The second row above answers after 600 ms and refuses an empty title.
document.addEventListener('redz:save', (event) => {
event.preventDefault();
event.detail.respondWith(fetch(event.detail.form.action, {method: 'POST', body: new FormData(event.detail.form)})
.then((answer) => answer.ok ? answer.text() : answer.text().then((words) => Promise.reject(words))));
});
Inside another form
A form cannot sit in a form: where the value lives in one - a settings page with a save bar - the edit form is a popover="manual" placed outside it, with the class menu for its panel; --edit opens it beside the Edit button.
<div class="hstack gap-8">
<span class="fs-16 fw-600" id="inline-edit-popover-name">Example Cruises</span>
<button class="btn btn-sm btn-icon btn-text" type="button" commandfor="inline-edit-popover-form" command="--edit" aria-label="Edit the company's name"><i class="bi bi-pencil" aria-hidden="true"></i></button>
</div>
<form class="menu inline-edit-form" id="inline-edit-popover-form" data-for="inline-edit-popover-name" popover="manual">
<input class="form-control form-control-sm" name="company" value="Example Cruises" aria-label="The company's name" required>
<button class="btn btn-sm btn-primary" type="submit">Save</button>
<button class="btn btn-sm" type="button" commandfor="inline-edit-popover-form" command="--cancel">Cancel</button>
<div class="invalid-feedback" hidden></div>
</form>Keyboard and accessibility
| Key | Does |
|---|---|
| Enter, Space on Edit | Opens the form, the focus in the field, its text selected |
| Enter in the field | Saves |
| Esc | Puts the field back and closes the form, the focus on Edit |
- Edit is a real button named after what it edits - the value's own text may be a link to its record and stays one.
- The form saves only by its Save button or Enter: a blur never commits half an edit, and never throws one away.
- A refused save keeps the focus in the field;
invalid-feedbacktakesrole="alert", so the page's words are said at once, and the field names it inaria-describedby.
Tokens
From css/components/inline-edit.css, which declares no custom property of its own.
It reads the theme's --redz-space-8, --redz-space-12.