# Inline Reply

> A reply or an edit written in place: a soft line that opens into a field. Enter sends, and Esc cancels. With new words in it, Cancel and Send show under it.

- Name: `inline-reply`
- Status: beta
- Categories: ai, forms
- File: the install writes `inline-reply.tsx` to your `ui` alias, `@/components/ui` by default.
- Other registry items: `@arbokui/button`, `@arbokui/button-variants`, `@arbokui/motion`. The install adds them.
- Gallery: https://arbokui.com/components/inline-reply
- Registry item: https://arbokui.com/r/inline-reply.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the component:

   ```bash
   npx shadcn@latest add @arbokui/inline-reply
   ```

## Use it for

- Replying under a message, a comment, or a post, right where it is.
- Editing your own message in place, with mode edit and the message in defaultValue.
- Open it from a Reply button with open and onOpenChange. The cursor goes in. Render it in a Motion box, so the space it takes glides open and shut.

## Avoid it for

- A new message to a group. Use Composer, which says who it reaches.
- Long, formatted writing. Use Editor.
- A form field that waits for a Save button. Use Textarea.

## Props

- `placeholder`: `string`. Default `"Reply" or "Edit message"`. The collapsed line's words and the field's name, like "Reply to Design".
- `defaultValue`: `string`. Default `""`. Words to start with, like the message being edited.
- `open`: `boolean`. Controlled: the field shows while true. Opening it this way, or rendering it with open, puts the cursor in it.
- `defaultOpen`: `boolean`. Default `false`. Starts open, without taking focus, and stays open when you leave it.
- `onOpenChange`: `(open: boolean) => void`. Hears every open and close: a press on the line, a send, Esc, Cancel, or leaving it with nothing new in it.
- `autoFocus`: `boolean`. Default `false`. Puts the cursor in it on first render when it starts open.
- `mode`: `"reply" | "edit"`. Default `"reply"`. Edit keeps the sent words in the field for the next edit, and names its button Save.
- `onSend`: `(text: string) => void`. Enter, or Send, sends the words, trimmed. Empty words are never sent: the field shakes once.
- `onCancel`: `() => void`. Esc or Cancel took it back, or you left it with nothing new in it. The words go back to defaultValue.
- `size`: `"sm" | "md" | "lg"`. Default `"md"`. Height and padding, as other fields.
- `disabled`: `boolean`. Default `false`. Turns it off. The line keeps its fill and gains the field's edge, as a disabled field does, and keeps its words readable, so a placeholder like "Replies are closed" can say why.
- `className`: `string`. Extra classes on the root. Later classes win.

## Accessibility

- Collapsed, it is a button named by placeholder. Open, it is a textarea with the same name.
- The field is described by a hidden line: Enter sends, Shift+Enter starts a new line, Esc cancels.
- Esc cancels it and goes no further, so a sheet or a row around it stays.
- With new words in it, Cancel and Send, or Save for an edit, show under it as buttons, so a tap or a pointer has a way out with no keys. They are 44 px tall on touch.
- Leaving it empty, or leaving an edit with its words unchanged, cancels it, so a press or a tap anywhere else is a way out with no Esc key. Words you typed stay, and so does a field that starts open.
- After a send or Esc from inside, focus goes back to the line, unless something around it took focus first. Rendered only while open, as from a Reply button, the line is gone, so what holds it gives focus back, as Message Row does.
- In forced colors, the collapsed line keeps an edge, since its gray fill is gone.

## Examples

### Under a post

```tsx
<InlineReply placeholder="Reply to Design" onSend={(text) => reply(text)} />
```

### Opened by a Reply button (needs @arbokui/hover-actions)

```tsx
const [replying, setReplying] = useState(false);

<HoverActions actions={[{ label: "Reply", icon: <MessageCircle />, onClick: () => setReplying(true) }]} />
{/* The Motion box glides open to make room, and fades the field in and out. */}
<Motion>
  {replying && <InlineReply placeholder="Reply to Anna" open onOpenChange={setReplying} onSend={reply} />}
</Motion>
```

### Edit a message in place (needs @arbokui/toast)

```tsx
<Motion>
  {editing ? (
    <InlineReply mode="edit" defaultValue={message} open onOpenChange={setEditing} onSend={setMessage} onCancel={() => toast("Edit discarded")} />
  ) : (
    <p>{message}</p>
  )}
</Motion>
```
