# InlineEdit

> Text that turns into an input in place with Save and Cancel, async save, validation by type, and keyboard and focus handling.

Source: https://docs.nasaqui.com/components/inline-edit

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/inline-edit.json
```

A value that reads as plain text until you click it. Then it becomes an input (or a textarea) in the same place, with Save and Cancel buttons. Use it for titles, names, descriptions and other single fields where opening a dialog or a form page would be too heavy.

## When to use

- Renaming a document, project or list item.
- A profile or settings value edited one field at a time.
- Short text or one paragraph that changes now and then.

## When not to use

- Several related fields saved together: use a form ([profile-form](https://docs.nasaqui.com/components/profile-form), [field](https://docs.nasaqui.com/components/field)).
- Editing cells of a table: use DataTable's column `edit` and `onCellEdit`.
- Long or formatted content: use [rich-text-editor](https://docs.nasaqui.com/components/rich-text-editor).

## Import

```tsx
import { InlineEdit } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"
```

## Quick start

```tsx
import { useState } from "react";
import { InlineEdit } from "@fadymondy/nasaq/web";

export function ProjectTitle() {
  const [title, setTitle] = useState("Website redesign");
  return (
    <InlineEdit
      label="title"
      value={title}
      required
      maxLength={80}
      displayClassName="text-h2"
      onSave={async (next) => {
        await api.rename(next);
        setTitle(next);
      }}
    />
  );
}
```

## Anatomy

```
InlineEdit           data-slot="inline-edit"  data-state="display" | "editing"
├─ display           <button> with the text and a pencil (shown on hover, focus and touch)
└─ editing           role="group"
    ├─ Input | Textarea
    ├─ Save (check) and Cancel (x) buttons
    └─ message       role="alert" for errors, or the multi-line key hint
```

## API

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `string` | required | The saved value. |
| `onSave` | `(value) => void \| { error?: string } \| Promise<...>` | required | Save the new value. Return `{ error }` or throw to keep editing. Busy while pending. |
| `label` | `string` | required | Names the field ("Edit title") and the empty text ("Add title"). |
| `type` | `"text" \| "number" \| "url" \| "email"` | `"text"` | Validates on save. `number` accepts Arabic-Indic digits. `url` accepts only http and https. |
| `multiline`, `rows` | `boolean`, `number` | `false`, `3` | A textarea. Enter adds a line, Ctrl or Cmd+Enter saves. |
| `placeholder` | `string` | none | Shown for an empty value and in the input. |
| `required` | `boolean` | `false` | An empty value is refused. |
| `maxLength` | `number` | none | Counted in characters. |
| `validate` | `(value) => string \| undefined` | none | Return a message to refuse the value. Runs after the built-in checks. |
| `onBlurAction` | `"save" \| "cancel" \| "none"` | `"save"` | What leaving the open editor does. |
| `renderValue` | `(value) => ReactNode` | none | Custom display, such as a link. |
| `displayClassName`, `inputClassName` | `string` | none | Make the display match the heading it replaces. |
| `ltr` | `boolean` | true for number, email, url | Force left-to-right entry for codes and links inside Arabic pages. |
| `disabled`, `readOnly` | `boolean` | `false` | No edit affordance. |
| `editing`, `onEditingChange` | `boolean`, `(boolean) => void` | uncontrolled | Control the state, for example to start editing from a menu. |
| `labels` | `InlineEditLabels` | English or Arabic | Overrides for the strings. |

## Examples

```tsx
<InlineEdit label="website" type="url" value={site} onSave={saveSite} />
```

```tsx
<InlineEdit label="description" multiline rows={4} value={about} onSave={saveAbout} onBlurAction="none" />
```

```tsx
<InlineEdit
  label="handle"
  value={handle}
  validate={(v) => (/^[a-z0-9_]+$/.test(v) ? undefined : "Use lowercase letters, digits and underscores.")}
  onSave={async (v) => ((await api.isTaken(v)) ? { error: "That handle is taken." } : void (await api.save(v)))}
/>
```

Arabic copy:

```tsx
<InlineEdit label="العنوان" value="إعادة تصميم الموقع" onSave={save} labels={{ edit: "تعديل {label}" }} />
```

## Accessibility

| Key | Action |
| --- | --- |
| Enter, Space | On the text: start editing. In a single-line field: save. |
| Ctrl or Cmd + Enter | Save a multi-line field. |
| Escape | Cancel and give focus back to the text. |
| Tab | Move between the field, Save and Cancel. |

- The display is a real button named "Edit title". The editor is a group with the same name; the input has `aria-invalid` and `aria-describedby` pointing at the error.
- Focus returns to the text after saving or cancelling, so keyboard users keep their place.
- Enter during IME composition (Arabic or CJK input methods) is left to the IME.
- Localise `label`, and `labels` where wording matters.

## RTL & i18n

- The text and input use `dir="auto"`, so Arabic and English values each align naturally.
- `number`, `email` and `url` fields are left-to-right so codes and links keep their order.
- Numbers typed with Arabic-Indic digits are converted before validating.

## Styling & tokens

Uses `--nq-hover`, `--nq-focus` and the control tokens. Target `data-slot="inline-edit"`, `data-state` and `data-pending`. Pass `displayClassName` to match the surrounding type role.

## Do / Don't

- Do show what will happen: Save and Cancel are always visible while editing.
- Do keep the display looking like the text it replaces.
- Don't use it where a mistake is costly and needs review. Use a form with a confirmation.
- Don't rely on hover for discovery. The pencil is always shown on touch and focus.

## Related

- [field](https://docs.nasaqui.com/components/field), [profile-form](https://docs.nasaqui.com/components/profile-form), [data-table](https://docs.nasaqui.com/components/data-table)

## Lab

https://docs.nasaqui.com/?path=/docs/components-forms-inline-edit--docs

## Code

### React

```tsx
import { useState } from "react";
import { InlineEdit } from "@fadymondy/nasaq/web";

export function ProjectTitle() {
  const [title, setTitle] = useState("Website redesign");
  return (
    <InlineEdit
      label="title"
      value={title}
      required
      maxLength={80}
      displayClassName="text-h2"
      onSave={async (next) => {
        await api.rename(next);
        setTitle(next);
      }}
    />
  );
}
```

### shadcn

```tsx
import { useState } from "react";
import { InlineEdit } from "@/components/ui/inline-edit";

export function ProjectTitle() {
  const [title, setTitle] = useState("Website redesign");
  return (
    <InlineEdit
      label="title"
      value={title}
      required
      maxLength={80}
      displayClassName="text-h2"
      onSave={async (next) => {
        await api.rename(next);
        setTitle(next);
      }}
    />
  );
}
```

### Vue

```vue
<script setup lang="ts">
import { ref } from "vue";
import { NqInlineEdit } from "@fadymondy/nasaq/vue";

const title = ref("Launch plan");
const email = ref("sara@example.com");
const save = (target: typeof title) => (value: string) => new Promise<void>((resolve) => setTimeout(() => ((target.value = value), resolve()), 400));
</script>

<template>
  <div class="flex flex-col gap-4">
    <NqInlineEdit :value="title" label="title" required :max-length="60" display-class="text-h3" :on-save="save(title)" />
    <NqInlineEdit :value="email" label="email" type="email" :on-save="save(email)" />
  </div>
</template>
```

### Blade

```blade
<div class="flex w-full max-w-sm flex-col gap-4">
    <x-nq::inline-edit value="Launch plan" label="title" required :max-length="20" display-class="text-h3" />
    <x-nq::inline-edit value="" label="description" />
    <x-nq::inline-edit value="42" label="quantity" type="number" />
    <x-nq::inline-edit value="Read only" label="note" read-only />
</div>
```

### HTML + Alpine

```html
<div class="flex w-full max-w-sm flex-col gap-4">
    <div data-slot="inline-edit" data-state="display" x-data="nqInlineEdit('Launch plan', JSON.parse('{\u0022type\u0022:\u0022text\u0022,\u0022multiline\u0022:false,\u0022required\u0022:true,\u0022maxLength\u0022:20,\u0022blur\u0022:\u0022save\u0022,\u0022locked\u0022:false}'))" x-modelable="value" x-bind="root"
    class="min-w-0">
        <div x-show="!editing"  x-on:click="open()" >
        <button type="button" x-ref="display"   aria-label="Edit title"             class="group/inline -mx-1.5 inline-flex max-w-full min-w-0 cursor-text items-center gap-2 rounded-control px-1.5 py-0.5 text-start outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover focus-visible:outline-2 focus-visible:outline-nq-focus disabled:cursor-default disabled:hover:bg-transparent ">
            <span dir="auto" x-bind="text"
                class="min-w-0 break-words   text-h3">Launch plan</span>
                            <svg aria-hidden="true" class="size-3.5 shrink-0 text-muted-foreground opacity-0 transition-opacity duration-150 group-hover/inline:opacity-100 group-focus-visible/inline:opacity-100 pointer-coarse:opacity-100" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/>
  <path d="m15 5 4 4"/>
</svg>                    </button>
    </div>
            <div role="group" aria-label="Edit title" x-show="editing" x-cloak style="display: none" x-ref="editor" x-bind="group" class="flex min-w-0 flex-col gap-1.5">
            <div class="flex gap-1.5 items-center">
                                    <input data-slot="input" type="text"
                    x-model="draft" x-bind="input" aria-label="Edit title" placeholder="" dir="auto" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control-sm">
                                <div class="flex shrink-0 gap-1 ">
                    <button data-slot="button"
     type="button"                         aria-label="Save" x-bind="saveButton" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] size-control-sm p-0">
        <svg data-slot="spinner" aria-hidden="true" style="display: none;" x-show="pending" x-cloak="1" class="size-4 animate-spin motion-reduce:animate-none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21 12a9 9 0 1 1-6.219-8.56"/>
</svg>                        <svg x-show="!pending" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg></button>
                    <button data-slot="button"
     type="button"                         aria-label="Cancel" x-bind="cancelButton" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg></button>
                </div>
            </div>
            <p role="alert" x-show="error" x-cloak style="display: none" x-text="error" x-bind:id="$id('inline-edit-error')" class="text-caption text-nq-danger-text"></p>
                    </div>
    </div>
    <div data-slot="inline-edit" data-state="display" x-data="nqInlineEdit('', JSON.parse('{\u0022type\u0022:\u0022text\u0022,\u0022multiline\u0022:false,\u0022required\u0022:false,\u0022maxLength\u0022:null,\u0022blur\u0022:\u0022save\u0022,\u0022locked\u0022:false}'))" x-modelable="value" x-bind="root"
    class="min-w-0">
        <div x-show="!editing"  x-on:click="open()" >
        <button type="button" x-ref="display"   aria-label="Edit description"             class="group/inline -mx-1.5 inline-flex max-w-full min-w-0 cursor-text items-center gap-2 rounded-control px-1.5 py-0.5 text-start outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover focus-visible:outline-2 focus-visible:outline-nq-focus disabled:cursor-default disabled:hover:bg-transparent ">
            <span dir="auto" x-bind="text"
                class="min-w-0 break-words  text-muted-foreground ">Add description</span>
                            <svg aria-hidden="true" class="size-3.5 shrink-0 text-muted-foreground opacity-0 transition-opacity duration-150 group-hover/inline:opacity-100 group-focus-visible/inline:opacity-100 pointer-coarse:opacity-100" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/>
  <path d="m15 5 4 4"/>
</svg>                    </button>
    </div>
            <div role="group" aria-label="Edit description" x-show="editing" x-cloak style="display: none" x-ref="editor" x-bind="group" class="flex min-w-0 flex-col gap-1.5">
            <div class="flex gap-1.5 items-center">
                                    <input data-slot="input" type="text"
                    x-model="draft" x-bind="input" aria-label="Edit description" placeholder="" dir="auto" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] h-control-sm">
                                <div class="flex shrink-0 gap-1 ">
                    <button data-slot="button"
     type="button"                         aria-label="Save" x-bind="saveButton" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] size-control-sm p-0">
        <svg data-slot="spinner" aria-hidden="true" style="display: none;" x-show="pending" x-cloak="1" class="size-4 animate-spin motion-reduce:animate-none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21 12a9 9 0 1 1-6.219-8.56"/>
</svg>                        <svg x-show="!pending" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg></button>
                    <button data-slot="button"
     type="button"                         aria-label="Cancel" x-bind="cancelButton" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg></button>
                </div>
            </div>
            <p role="alert" x-show="error" x-cloak style="display: none" x-text="error" x-bind:id="$id('inline-edit-error')" class="text-caption text-nq-danger-text"></p>
                    </div>
    </div>
    <div data-slot="inline-edit" data-state="display" x-data="nqInlineEdit('42', JSON.parse('{\u0022type\u0022:\u0022number\u0022,\u0022multiline\u0022:false,\u0022required\u0022:false,\u0022maxLength\u0022:null,\u0022blur\u0022:\u0022save\u0022,\u0022locked\u0022:false}'))" x-modelable="value" x-bind="root"
    class="min-w-0">
        <div x-show="!editing"  x-on:click="open()" >
        <button type="button" x-ref="display"   aria-label="Edit quantity"             class="group/inline -mx-1.5 inline-flex max-w-full min-w-0 cursor-text items-center gap-2 rounded-control px-1.5 py-0.5 text-start outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover focus-visible:outline-2 focus-visible:outline-nq-focus disabled:cursor-default disabled:hover:bg-transparent ">
            <span dir="auto" x-bind="text"
                class="min-w-0 break-words   ">42</span>
                            <svg aria-hidden="true" class="size-3.5 shrink-0 text-muted-foreground opacity-0 transition-opacity duration-150 group-hover/inline:opacity-100 group-focus-visible/inline:opacity-100 pointer-coarse:opacity-100" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/>
  <path d="m15 5 4 4"/>
</svg>                    </button>
    </div>
            <div role="group" aria-label="Edit quantity" x-show="editing" x-cloak style="display: none" x-ref="editor" x-bind="group" class="flex min-w-0 flex-col gap-1.5">
            <div class="flex gap-1.5 items-center">
                                    <input data-slot="input" type="text"
     dir="ltr"                 x-model="draft" x-bind="input" aria-label="Edit quantity" placeholder="" inputmode="decimal" class="w-full min-w-0 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] transition-colors duration-150 ease-nq outline-none placeholder:text-muted-foreground focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px] text-start h-control-sm">
                                <div class="flex shrink-0 gap-1 ">
                    <button data-slot="button"
     type="button"                         aria-label="Save" x-bind="saveButton" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] size-control-sm p-0">
        <svg data-slot="spinner" aria-hidden="true" style="display: none;" x-show="pending" x-cloak="1" class="size-4 animate-spin motion-reduce:animate-none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21 12a9 9 0 1 1-6.219-8.56"/>
</svg>                        <svg x-show="!pending" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg></button>
                    <button data-slot="button"
     type="button"                         aria-label="Cancel" x-bind="cancelButton" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M18 6 6 18"/>
  <path d="m6 6 12 12"/>
</svg></button>
                </div>
            </div>
            <p role="alert" x-show="error" x-cloak style="display: none" x-text="error" x-bind:id="$id('inline-edit-error')" class="text-caption text-nq-danger-text"></p>
                    </div>
    </div>
    <div data-slot="inline-edit" data-state="display" x-data="nqInlineEdit('Read only', JSON.parse('{\u0022type\u0022:\u0022text\u0022,\u0022multiline\u0022:false,\u0022required\u0022:false,\u0022maxLength\u0022:null,\u0022blur\u0022:\u0022save\u0022,\u0022locked\u0022:true}'))" x-modelable="value" x-bind="root"
    class="min-w-0">
        <div x-show="!editing" >
        <button type="button" x-ref="display"  disabled              class="group/inline -mx-1.5 inline-flex max-w-full min-w-0 cursor-text items-center gap-2 rounded-control px-1.5 py-0.5 text-start outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover focus-visible:outline-2 focus-visible:outline-nq-focus disabled:cursor-default disabled:hover:bg-transparent cursor-default hover:bg-transparent">
            <span dir="auto" x-bind="text"
                class="min-w-0 break-words   ">Read only</span>
                    </button>
    </div>
    </div>
</div>
```
