import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks'
import * as EditableTextStories from './EditableText.stories'

<Meta of={EditableTextStories} />

# EditableText

Text you click to edit. It reads as text until clicked; then it is a
field. A commit that fails keeps the field open with the text in it, so an
edit is never silently lost.

<Canvas of={EditableTextStories.Title} />

## When

- **It has no size of its own.** Give it the size of the text it stands in for —
  a pane title's `text-body-2-strong` — on your element around it; the text and
  the field both take it.
- A title or description edited where it is shown — no dialog, no separate
  form.
- A reader who cannot write gets `readOnly` — the value without the edit
  affordance, because an action appears only where it can succeed.

## When not

- A field in a form or dialog → **TextInput** / **Textarea** in a
  **Field**.
- Composing something new → the field, not an edit-in-place of nothing.
- An edit that publishes something, like a message → **Textarea** with Save
  and Cancel. EditableText saves when you leave it.

## How

```tsx
import { EditableText } from '@estiva-app/ui'

<EditableText
  value={title}
  placeholder="Untitled"
  label="Title"
  onCommit={async (next) => save(next)}
/>
```

- `onCommit` resolves `true` to close; `false` (or a throw) keeps the
  field open — you have already told the person why. An unchanged value is
  not committed at all.
- `label` is required — it is the field's accessible name. This one is
  spelled rather than taken from a `Field`: the component is a line of text
  that becomes a field, and it is used where there is no label to read.
- The editing state is Base UI's `Input` since stage 3, or `Field.Control`
  as a `<textarea>` when `multiline`. **Everything below is ours**, because
  Base UI has no inline-edit part and no opinion about what an edit means.
- `display` shows something other than what is edited (a value carrying
  raw references, rendered richer when read) without losing the original
  on commit.

- **Its text size is where it sits**, like `Person`'s: put `text-h2` on your own
  element around it, and the text and the field both take it (a field inherits
  the page's font). `className` places it — `-mx-2` to line its text up with
  a header's inset — and a size passed there is refused by the lint.

- **Planned:** rich text edited where it is shown (UIG-30).

## What it owns

It does these by itself. Write none of them around it.

| It does | So you never write | Refused when written by hand |
|---|---|---|
| Opens its field on a click, with the value selected | an edit mode of your own |  |
| Enter and leaving the field save; Escape cancels and puts the value back (`multiline`: Shift+Enter is a new line) | key or blur handlers |  |

## Keys

| Input | What happens |
|---|---|
| click the text | opens the field, selects the value |
| Enter | commits (`multiline`: Shift+Enter is a new line) |
| Escape | cancels, restores the value |
| blur | commits |

## Props

<Controls of={EditableTextStories.Title} />
