> ## Documentation Index
> Fetch the complete documentation index at: https://api.fanvue.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# InlineEdit

> A chip-styled inline edit field.

```tsx theme={null}
import { InlineEdit } from "@fanvue/ui";
import type { InlineEditProps, InlineEditSize } from "@fanvue/ui";
```

## Examples

## Default

<Frame>
  <iframe src={"https://main--697a1b6dd4dad73ee9c0e5f5.chromatic.com/iframe.html?id=components-inlineedit--default&viewMode=story&shortcuts=false&singleStory=true&globals=theme:light"} width="100%" height="240" style={{border: "none", borderRadius: "8px"}} loading="lazy" title="InlineEdit — Default" />
</Frame>

```tsx theme={null}
import { useState } from "react";
import { InlineEdit } from "@fanvue/ui";

function Example() {
  const [value, setValue] = useState("New folder");
  return <InlineEdit value={value} onSubmit={setValue} />;
}
```

## Disabled

<Frame>
  <iframe src={"https://main--697a1b6dd4dad73ee9c0e5f5.chromatic.com/iframe.html?id=components-inlineedit--disabled&viewMode=story&shortcuts=false&singleStory=true&globals=theme:light"} width="100%" height="240" style={{border: "none", borderRadius: "8px"}} loading="lazy" title="InlineEdit — Disabled" />
</Frame>

```tsx theme={null}
import { InlineEdit } from "@fanvue/ui";

<InlineEdit disabled value="Locked folder" onSubmit={() => {}} />
```

## Size 32

<Frame>
  <iframe src={"https://main--697a1b6dd4dad73ee9c0e5f5.chromatic.com/iframe.html?id=components-inlineedit--size-32&viewMode=story&shortcuts=false&singleStory=true&globals=theme:light"} width="100%" height="240" style={{border: "none", borderRadius: "8px"}} loading="lazy" title="InlineEdit — Size 32" />
</Frame>

```tsx theme={null}
import { useState } from "react";
import { InlineEdit } from "@fanvue/ui";

function Example() {
  const [value, setValue] = useState("Inbox folder");
  return <InlineEdit size="32" value={value} onSubmit={setValue} />;
}
```

## With Left Icon

<Frame>
  <iframe src={"https://main--697a1b6dd4dad73ee9c0e5f5.chromatic.com/iframe.html?id=components-inlineedit--with-left-icon&viewMode=story&shortcuts=false&singleStory=true&globals=theme:light"} width="100%" height="240" style={{border: "none", borderRadius: "8px"}} loading="lazy" title="InlineEdit — With Left Icon" />
</Frame>

```tsx theme={null}
import { useState } from "react";
import { InlineEdit, PlusIcon } from "@fanvue/ui";

function Example() {
  const [value, setValue] = useState("New folder");
  return <InlineEdit
           leftIcon={<PlusIcon className="size-4" />}
           value={value}
           onSubmit={setValue}
         />;
}
```

## In A List

<Frame>
  <iframe src={"https://main--697a1b6dd4dad73ee9c0e5f5.chromatic.com/iframe.html?id=components-inlineedit--in-a-list&viewMode=story&shortcuts=false&singleStory=true&globals=theme:light"} width="100%" height="240" style={{border: "none", borderRadius: "8px"}} loading="lazy" title="InlineEdit — In A List" />
</Frame>

```tsx theme={null}
import { useState } from "react";
import { InlineEdit } from "@fanvue/ui";

function Example() {
  const [folders, setFolders] = useState([
    { id: "inbox", name: "Inbox" },
    { id: "drafts", name: "Drafts" },
    { id: "sent", name: "Sent" },
  ]);
  return (
    <div className="flex flex-wrap gap-2">
      {folders.map((folder) => (
        <InlineEdit
          key={folder.id}
          value={folder.name}
          onSubmit={(next) =>
            setFolders((prev) =>
              prev.map((current) =>
                current.id === folder.id ? { ...current, name: next } : current,
              ),
            )
          }
        />
      ))}
    </div>
  );
}
```

## Props

## InlineEdit

A chip-styled inline edit field. Renders as a dashed-border button that swaps to a text input on click, allowing the value to be edited in place.

Enter and blur commit the draft via `onSubmit`. Escape reverts to `value` and calls `onCancel`. Drafts that fail `validate` are reverted.

The forwarded ref points at the underlying `<input>` and is only populated while the field is in edit mode — it resolves to `null` in display mode.

Consumers may pass `onChange`, `onBlur`, and `onKeyDown` to participate in input events. The component's own handlers run after the consumer's, and keyboard handling is skipped if the consumer calls `event.preventDefault()`.

<ParamField path="onSubmit" type="(value: string) => void" required>
  Called with the trimmed draft when the user commits an edit (Enter or blur).
</ParamField>

<ParamField path="value" type="string" required>
  Current value displayed in the chip and used as the starting draft when editing.
</ParamField>

<ParamField path="className" type="string">
  Additional class name applied to the root element.
</ParamField>

<ParamField path="disabled" type="boolean" default="false">
  Whether the field is disabled — prevents entering edit mode.
</ParamField>

<ParamField path="editLabel" type="string" default="Edit">
  Accessible label for the edit input.
</ParamField>

<ParamField path="leftIcon" type="ReactNode">
  Icon rendered before the value in display mode. Hidden when editing.
</ParamField>

<ParamField path="onCancel" type="(() => void)">
  Called when the user cancels an edit with Escape.
</ParamField>

<ParamField path="size" type="&#x22;32&#x22; | &#x22;40&#x22;" default="40">
  Height of the field in pixels.
</ParamField>

<ParamField path="validate" type="((draft: string) => boolean)" default="rejects empty drafts">
  Validator for the trimmed draft on commit. Returning `false` reverts to the previous value without calling `onSubmit`.
</ParamField>

## Exported types

Also exported from `@fanvue/ui`: `InlineEditProps`, `InlineEditSize`.

***

**Setup:** [Installation](/docs/ui/installation) · [Theming](/docs/ui/theming)
