<!-- Generated by tools/docs.php from docs/src/inline-edit.html - edit the source, not this file. -->

# 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.

```html
<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.

```js
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.

```html
<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-feedback` takes `role="alert"`, so the page's words are said at once, and the field names it in `aria-describedby`.

## Tokens

From [`css/components/inline-edit.css`](https://github.com/redz-tech/REDZ.UI/blob/main/css/components/inline-edit.css), which declares no custom property of its own.

It reads the theme's `--redz-space-8`, `--redz-space-12`.
