Skip to content
txbrendan/ui

Inline Reply

beta

A reply or an edit written in place: a soft line that springs open into a field. Enter sends, and Esc cancels.

Preview

Collapsed

Opened from a Reply button

Anna Price · 18:02

Team sync is Tuesday at 6.

Starts open, without focus

Enter sends. Shift+Enter starts a new line. Esc cancels.

Sizes

Install

  1. 1. Add the registry to components.json, once per app. Without it, the shadcn CLI looks up @txbrendan in a public list that txbrendan/ui does not control.

    npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"
  2. 2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.

    npx shadcn@latest add @txbrendan/theme
  3. 3. Add the component.

    npx shadcn@latest add @txbrendan/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.

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

    The collapsed line's words and the field's name, like "Reply to Design".

    string · default "Reply" or "Edit message"

  • defaultValue

    Words to start with, like the message being edited.

    string

  • open

    Controlled: the field shows while true. Opening it this way, or rendering it with open, puts the cursor in it.

    boolean

  • defaultOpen

    Starts open, without taking focus.

    boolean · default false

  • onOpenChange

    Hears every open and close: a press on the line, a send, or Esc.

    (open: boolean) => void

  • autoFocus

    Puts the cursor in it on first render when it starts open.

    boolean · default false

  • mode

    Edit keeps the sent words in the field for the next edit.

    "reply" | "edit" · default "reply"

  • onSend

    Enter sends the words, trimmed. Empty words are never sent.

    (text: string) => void

  • onCancel

    Esc took it back. The words go back to defaultValue.

    () => void

  • size

    Height and padding, as other fields.

    "sm" | "md" | "lg" · default "md"

  • disabled

    Turns it off.

    boolean · default false

  • className

    Extra classes on the root. Later classes win.

    string

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.
  • After a send or Esc from inside, focus goes back to the line, unless something around it took focus first.
  • In forced colors, the collapsed line keeps an edge, since its gray fill is gone.

Examples

Under a post

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

Opened by a Reply button

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

<HoverActions actions={[{ label: "Reply", icon: <MessageCircle />, onClick: () => setReplying(true) }]} />
{replying && <InlineReply placeholder="Reply to Anna" open onOpenChange={setReplying} onSend={reply} />}