---
type: doc
title: Input Group
description: Add addons, buttons, and helper content to inputs.
---

> Fulldev UI for Astro. The `@fulldev` registry in `components.json` points at `https://ui.full.dev/r/styles/{style}/{name}.json`; see [installation](/astro/docs/installation.md).

```astro title="src/components/examples/input-group/input-group-demo.astro"
---
import SearchIcon from "@lucide/astro/icons/search"

import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
} from "@/components/ui/input-group"
---

<InputGroup class="max-w-xs">
  <InputGroupInput placeholder="Search..." />
  <InputGroupAddon>
    <SearchIcon />
  </InputGroupAddon>
  <InputGroupAddon align="inline-end">12 results</InputGroupAddon>
</InputGroup>
```

## Installation

```bash
npx shadcn@latest add @fulldev/input-group
```

## Usage

```ts
import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
  InputGroupInput,
  InputGroupText,
  InputGroupTextarea,
} from "@/components/ui/input-group"
```

```astro
<InputGroup>
  <InputGroupInput placeholder="Search..." />
  <InputGroupAddon>
    <SearchIcon />
  </InputGroupAddon>
</InputGroup>
```

## Composition

```text
InputGroup
├── InputGroupInput or InputGroupTextarea
├── InputGroupAddon
├── InputGroupButton
└── InputGroupText
```

## Align

Place `InputGroupAddon` after `InputGroupInput` or `InputGroupTextarea` in the
DOM for correct focus order, then use its `align` prop to position it visually.
Clicking an addon outside a button or link focuses the control.

### inline-start

Use `align="inline-start"` to position the addon at the start of the input. This is the default.

```astro title="src/components/examples/input-group/input-group-inline-start.astro"
---
import SearchIcon from "@lucide/astro/icons/search"

import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
} from "@/components/ui/input-group"
---

<Field class="max-w-sm">
  <FieldLabel for="inline-start-input">Input</FieldLabel>
  <InputGroup>
    <InputGroupInput id="inline-start-input" placeholder="Search..." />
    <InputGroupAddon align="inline-start">
      <SearchIcon class="text-muted-foreground" />
    </InputGroupAddon>
  </InputGroup>
  <FieldDescription>Icon positioned at the start.</FieldDescription>
</Field>
```

### inline-end

Use `align="inline-end"` to position the addon at the end of the input.

```astro title="src/components/examples/input-group/input-group-inline-end.astro"
---
import EyeOffIcon from "@lucide/astro/icons/eye-off"

import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
} from "@/components/ui/input-group"
---

<Field class="max-w-sm">
  <FieldLabel for="inline-end-input">Input</FieldLabel>
  <InputGroup>
    <InputGroupInput
      id="inline-end-input"
      type="password"
      placeholder="Enter password"
    />
    <InputGroupAddon align="inline-end">
      <EyeOffIcon />
    </InputGroupAddon>
  </InputGroup>
  <FieldDescription>Icon positioned at the end.</FieldDescription>
</Field>
```

### block-start

Use `align="block-start"` to position the addon above the input.

```astro title="src/components/examples/input-group/input-group-block-start.astro"
---
import CopyIcon from "@lucide/astro/icons/copy"
import FileCodeIcon from "@lucide/astro/icons/file-code"

import {
  Field,
  FieldDescription,
  FieldGroup,
  FieldLabel,
} from "@/components/ui/field"
import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
  InputGroupInput,
  InputGroupText,
  InputGroupTextarea,
} from "@/components/ui/input-group"
---

<FieldGroup class="max-w-sm">
  <Field>
    <FieldLabel for="block-start-input">Input</FieldLabel>
    <InputGroup class="h-auto">
      <InputGroupInput id="block-start-input" placeholder="Enter your name" />
      <InputGroupAddon align="block-start">
        <InputGroupText>Full Name</InputGroupText>
      </InputGroupAddon>
    </InputGroup>
    <FieldDescription>Header positioned above the input.</FieldDescription>
  </Field>
  <Field>
    <FieldLabel for="block-start-textarea">Textarea</FieldLabel>
    <InputGroup>
      <InputGroupTextarea
        id="block-start-textarea"
        placeholder="console.log('Hello, world!');"
        class="font-mono text-sm"
      />
      <InputGroupAddon align="block-start">
        <FileCodeIcon class="text-muted-foreground" />
        <InputGroupText class="font-mono">script.js</InputGroupText>
        <InputGroupButton size="icon-xs" class="ml-auto">
          <CopyIcon />
          <span class="sr-only">Copy</span>
        </InputGroupButton>
      </InputGroupAddon>
    </InputGroup>
    <FieldDescription>Header positioned above the textarea.</FieldDescription>
  </Field>
</FieldGroup>
```

### block-end

Use `align="block-end"` to position the addon below the input.

```astro title="src/components/examples/input-group/input-group-block-end.astro"
---
import {
  Field,
  FieldDescription,
  FieldGroup,
  FieldLabel,
} from "@/components/ui/field"
import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
  InputGroupInput,
  InputGroupText,
  InputGroupTextarea,
} from "@/components/ui/input-group"
---

<FieldGroup class="max-w-sm">
  <Field>
    <FieldLabel for="block-end-input">Input</FieldLabel>
    <InputGroup class="h-auto">
      <InputGroupInput id="block-end-input" placeholder="Enter amount" />
      <InputGroupAddon align="block-end">
        <InputGroupText>USD</InputGroupText>
      </InputGroupAddon>
    </InputGroup>
    <FieldDescription>Footer positioned below the input.</FieldDescription>
  </Field>
  <Field>
    <FieldLabel for="block-end-textarea">Textarea</FieldLabel>
    <InputGroup>
      <InputGroupTextarea
        id="block-end-textarea"
        placeholder="Write a comment..."
      />
      <InputGroupAddon align="block-end">
        <InputGroupText>0/280</InputGroupText>
        <InputGroupButton variant="default" size="sm" class="ml-auto">
          Post
        </InputGroupButton>
      </InputGroupAddon>
    </InputGroup>
    <FieldDescription>Footer positioned below the textarea.</FieldDescription>
  </Field>
</FieldGroup>
```

## Icon

```astro title="src/components/examples/input-group/input-group-icon.astro"
---
import CheckIcon from "@lucide/astro/icons/check"
import CreditCardIcon from "@lucide/astro/icons/credit-card"
import InfoIcon from "@lucide/astro/icons/info"
import MailIcon from "@lucide/astro/icons/mail"
import SearchIcon from "@lucide/astro/icons/search"
import StarIcon from "@lucide/astro/icons/star"

import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
} from "@/components/ui/input-group"
---

<div class="grid w-full max-w-sm gap-6">
  <InputGroup>
    <InputGroupInput placeholder="Search..." />
    <InputGroupAddon>
      <SearchIcon />
    </InputGroupAddon>
  </InputGroup>
  <InputGroup>
    <InputGroupInput type="email" placeholder="Enter your email" />
    <InputGroupAddon>
      <MailIcon />
    </InputGroupAddon>
  </InputGroup>
  <InputGroup>
    <InputGroupInput placeholder="Card number" />
    <InputGroupAddon>
      <CreditCardIcon />
    </InputGroupAddon>
    <InputGroupAddon align="inline-end">
      <CheckIcon />
    </InputGroupAddon>
  </InputGroup>
  <InputGroup>
    <InputGroupInput placeholder="Card number" />
    <InputGroupAddon align="inline-end">
      <StarIcon />
      <InfoIcon />
    </InputGroupAddon>
  </InputGroup>
</div>
```

## Text

```astro title="src/components/examples/input-group/input-group-text.astro"
---
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
  InputGroupText,
  InputGroupTextarea,
} from "@/components/ui/input-group"
---

<div class="grid w-full max-w-sm gap-6">
  <InputGroup>
    <InputGroupAddon>
      <InputGroupText>$</InputGroupText>
    </InputGroupAddon>
    <InputGroupInput placeholder="0.00" />
    <InputGroupAddon align="inline-end">
      <InputGroupText>USD</InputGroupText>
    </InputGroupAddon>
  </InputGroup>
  <InputGroup>
    <InputGroupAddon>
      <InputGroupText>https://</InputGroupText>
    </InputGroupAddon>
    <InputGroupInput placeholder="example.com" class="pl-0.5!" />
    <InputGroupAddon align="inline-end">
      <InputGroupText>.com</InputGroupText>
    </InputGroupAddon>
  </InputGroup>
  <InputGroup>
    <InputGroupInput placeholder="Enter your username" />
    <InputGroupAddon align="inline-end">
      <InputGroupText>@company.com</InputGroupText>
    </InputGroupAddon>
  </InputGroup>
  <InputGroup>
    <InputGroupTextarea placeholder="Enter your message" />
    <InputGroupAddon align="block-end">
      <InputGroupText class="text-xs text-muted-foreground">
        120 characters left
      </InputGroupText>
    </InputGroupAddon>
  </InputGroup>
</div>
```

## Button

To open a popover or dropdown menu from an `InputGroupButton`, put the root
inside the addon and give the button the trigger slot, such as
`data-slot="popover-trigger"`.

```astro title="src/components/examples/input-group/input-group-button.astro"
---
import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
  InputGroupInput,
} from "@/components/ui/input-group"
import { Popover, PopoverContent } from "@/components/ui/popover"
---

<div class="grid w-full max-w-sm gap-6" data-input-group-button-example>
  <InputGroup>
    <InputGroupInput placeholder="https://x.com/shadcn" readonly />
    <InputGroupAddon align="inline-end">
      <InputGroupButton
        aria-label="Copy"
        title="Copy"
        size="icon-xs"
        data-copy-value="https://x.com/shadcn"
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
          class="tabler-icon tabler-icon-check hidden"
          data-copied-icon
        >
          <path d="M5 12l5 5l10 -10"></path>
        </svg>
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
          class="tabler-icon tabler-icon-copy"
          data-copy-icon
        >
          <path d="M7 9.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667l0 -8.666"></path>
          <path d="M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1"></path>
        </svg>
      </InputGroupButton>
    </InputGroupAddon>
  </InputGroup>
  <InputGroup class="[--radius:9999px]">
    <InputGroupAddon>
      <Popover>
        <InputGroupButton
          data-slot="popover-trigger"
          variant="secondary"
          size="icon-xs"
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="24"
            height="24"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
            stroke-linejoin="round"
            class="tabler-icon tabler-icon-info-circle"
          >
            <path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0"></path>
            <path d="M12 9h.01"></path>
            <path d="M11 12h1v4h1"></path>
          </svg>
        </InputGroupButton>
        <PopoverContent
          align="start"
          class="flex flex-col gap-1 rounded-xl text-sm"
        >
          <p class="font-medium">Your connection is not secure.</p>
          <p>You should not enter any sensitive information on this site.</p>
        </PopoverContent>
      </Popover>
    </InputGroupAddon>
    <InputGroupAddon class="pl-1.5 text-muted-foreground">
      https://
    </InputGroupAddon>
    <InputGroupInput id="input-secure-19" />
    <InputGroupAddon align="inline-end">
      <InputGroupButton size="icon-xs" data-favorite-toggle>
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
          class="tabler-icon tabler-icon-star data-[favorite=true]:fill-blue-600 data-[favorite=true]:stroke-blue-600"
          data-favorite="false"
        >
          <path d="M12 17.75l-6.172 3.245l1.179 -6.873l-5 -4.867l6.9 -1l3.086 -6.253l3.086 6.253l6.9 1l-5 4.867l1.179 6.873l-6.158 -3.245"></path>
        </svg>
      </InputGroupButton>
    </InputGroupAddon>
  </InputGroup>
  <InputGroup>
    <InputGroupInput placeholder="Type to search..." />
    <InputGroupAddon align="inline-end">
      <InputGroupButton variant="secondary">Search</InputGroupButton>
    </InputGroupAddon>
  </InputGroup>
</div>

<script>
  const initialize = () => {
    for (const root of document.querySelectorAll<HTMLElement>(
      "[data-input-group-button-example]"
    )) {
      if (root.hasAttribute("data-bound")) continue
      root.setAttribute("data-bound", "")

      const copy = root.querySelector<HTMLElement>("[data-copy-value]")!
      const copyIcon = copy.querySelector("[data-copy-icon]")!
      const copiedIcon = copy.querySelector("[data-copied-icon]")!
      let timeout: ReturnType<typeof setTimeout> | undefined
      const setCopied = (copied: boolean) => {
        copiedIcon.classList.toggle("hidden", !copied)
        copyIcon.classList.toggle("hidden", copied)
      }
      copy.addEventListener("click", async () => {
        try {
          await navigator.clipboard.writeText(copy.dataset.copyValue!)
        } catch {
          return
        }
        setCopied(true)
        clearTimeout(timeout)
        timeout = setTimeout(() => setCopied(false), 2000)
      })

      const favorite = root.querySelector("[data-favorite-toggle]")!
      const star = favorite.querySelector<SVGElement>("[data-favorite]")!
      favorite.addEventListener("click", () => {
        star.dataset.favorite = String(star.dataset.favorite !== "true")
      })
    }
  }

  initialize()
  document.addEventListener("astro:page-load", initialize)
</script>
```

## Kbd

```astro title="src/components/examples/input-group/input-group-kbd.astro"
---
import SearchIcon from "@lucide/astro/icons/search"

import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
} from "@/components/ui/input-group"
import { Kbd } from "@/components/ui/kbd"
---

<InputGroup class="max-w-sm">
  <InputGroupInput placeholder="Search..." />
  <InputGroupAddon>
    <SearchIcon class="text-muted-foreground" />
  </InputGroupAddon>
  <InputGroupAddon align="inline-end">
    <Kbd>⌘K</Kbd>
  </InputGroupAddon>
</InputGroup>
```

## Dropdown

```astro title="src/components/examples/input-group/input-group-dropdown.astro"
---
import ChevronDownIcon from "@lucide/astro/icons/chevron-down"
import MoreHorizontal from "@lucide/astro/icons/ellipsis"

import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
} from "@/components/ui/dropdown-menu"
import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
  InputGroupInput,
} from "@/components/ui/input-group"
---

<div class="grid w-full max-w-sm gap-4">
  <InputGroup>
    <InputGroupInput placeholder="Enter file name" />
    <InputGroupAddon align="inline-end">
      <DropdownMenu>
        <InputGroupButton
          data-slot="dropdown-menu-trigger"
          variant="ghost"
          aria-label="More"
          size="icon-xs"
        >
          <MoreHorizontal />
        </InputGroupButton>
        <DropdownMenuContent align="end" sideOffset={8} alignOffset={-4}>
          <DropdownMenuGroup>
            <DropdownMenuItem>Settings</DropdownMenuItem>
            <DropdownMenuItem>Copy path</DropdownMenuItem>
            <DropdownMenuItem>Open location</DropdownMenuItem>
          </DropdownMenuGroup>
        </DropdownMenuContent>
      </DropdownMenu>
    </InputGroupAddon>
  </InputGroup>
  <InputGroup>
    <InputGroupInput placeholder="Enter search query" />
    <InputGroupAddon align="inline-end">
      <DropdownMenu>
        <InputGroupButton
          data-slot="dropdown-menu-trigger"
          variant="ghost"
          class="pr-1.5! text-xs"
        >
          Search In... <ChevronDownIcon class="size-3" />
        </InputGroupButton>
        <DropdownMenuContent align="end" sideOffset={8} alignOffset={-4}>
          <DropdownMenuGroup>
            <DropdownMenuItem>Documentation</DropdownMenuItem>
            <DropdownMenuItem>Blog Posts</DropdownMenuItem>
            <DropdownMenuItem>Changelog</DropdownMenuItem>
          </DropdownMenuGroup>
        </DropdownMenuContent>
      </DropdownMenu>
    </InputGroupAddon>
  </InputGroup>
</div>
```

## Spinner

```astro title="src/components/examples/input-group/input-group-spinner.astro"
---
import LoaderIcon from "@lucide/astro/icons/loader"

import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
  InputGroupText,
} from "@/components/ui/input-group"
import { Spinner } from "@/components/ui/spinner"
---

<div class="grid w-full max-w-sm gap-4">
  <InputGroup>
    <InputGroupInput placeholder="Searching..." />
    <InputGroupAddon align="inline-end">
      <Spinner />
    </InputGroupAddon>
  </InputGroup>
  <InputGroup>
    <InputGroupInput placeholder="Processing..." />
    <InputGroupAddon>
      <Spinner />
    </InputGroupAddon>
  </InputGroup>
  <InputGroup>
    <InputGroupInput placeholder="Saving changes..." />
    <InputGroupAddon align="inline-end">
      <InputGroupText>Saving...</InputGroupText>
      <Spinner />
    </InputGroupAddon>
  </InputGroup>
  <InputGroup>
    <InputGroupInput placeholder="Refreshing data..." />
    <InputGroupAddon>
      <LoaderIcon class="animate-spin" />
    </InputGroupAddon>
    <InputGroupAddon align="inline-end">
      <InputGroupText class="text-muted-foreground">
        Please wait...
      </InputGroupText>
    </InputGroupAddon>
  </InputGroup>
</div>
```

## Textarea

```astro title="src/components/examples/input-group/input-group-textarea.astro"
---
import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
  InputGroupText,
  InputGroupTextarea,
} from "@/components/ui/input-group"
---

<div class="grid w-full max-w-md gap-4">
  <InputGroup>
    <InputGroupTextarea
      id="textarea-code-32"
      placeholder="console.log('Hello, world!');"
      class="min-h-[200px]"
    />
    <InputGroupAddon align="block-end" class="border-t">
      <InputGroupText>Line 1, Column 1</InputGroupText>
      <InputGroupButton size="sm" class="ml-auto" variant="default">
        Run
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
          class="tabler-icon tabler-icon-corner-down-left"
        >
          <path d="M18 6v6a3 3 0 0 1 -3 3h-10l4 -4m0 8l-4 -4"></path>
        </svg>
      </InputGroupButton>
    </InputGroupAddon>
    <InputGroupAddon align="block-start" class="border-b">
      <InputGroupText class="font-mono font-medium">
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
          class="tabler-icon tabler-icon-brand-javascript"
        >
          <path d="M20 4l-2 14.5l-6 2l-6 -2l-2 -14.5l16 0"></path>
          <path d="M7.5 8h3v8l-2 -1"></path>
          <path d="M16.5 8h-2.5a.5 .5 0 0 0 -.5 .5v3a.5 .5 0 0 0 .5 .5h1.423a.5 .5 0 0 1 .495 .57l-.418 2.93l-2 .5"></path>
        </svg>
        script.js
      </InputGroupText>
      <InputGroupButton class="ml-auto" size="icon-xs">
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
          class="tabler-icon tabler-icon-refresh"
        >
          <path d="M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4"></path>
          <path d="M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4"></path>
        </svg>
      </InputGroupButton>
      <InputGroupButton variant="ghost" size="icon-xs">
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
          class="tabler-icon tabler-icon-copy"
        >
          <path d="M7 9.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667l0 -8.666"></path>
          <path d="M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1"></path>
        </svg>
      </InputGroupButton>
    </InputGroupAddon>
  </InputGroup>
</div>
```

## Custom Input

Add `data-slot="input-group-control"` to a custom control for the focus state
and addon click handling. This one grows with its content through
`field-sizing-content`.

```astro title="src/components/examples/input-group/input-group-custom.astro"
---
import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
} from "@/components/ui/input-group"
---

<div class="grid w-full max-w-sm gap-6">
  <InputGroup>
    <textarea
      data-slot="input-group-control"
      class="flex field-sizing-content min-h-16 w-full resize-none rounded-md bg-transparent px-3 py-2.5 text-base transition-[color,box-shadow] outline-none md:text-sm"
      placeholder="Autoresize textarea..."
    ></textarea>
    <InputGroupAddon align="block-end">
      <InputGroupButton class="ml-auto" size="sm" variant="default">
        Submit
      </InputGroupButton>
    </InputGroupAddon>
  </InputGroup>
</div>
```

## RTL

```astro title="src/components/examples/input-group/input-group-rtl.astro"
---
import SearchIcon from "@lucide/astro/icons/search"

import {
  Field,
  FieldDescription,
  FieldGroup,
  FieldLabel,
} from "@/components/ui/field"
import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
  InputGroupInput,
  InputGroupText,
  InputGroupTextarea,
} from "@/components/ui/input-group"
import { Spinner } from "@/components/ui/spinner"

const translations = {
  en: {
    dir: "ltr",
    values: {
      placeholder: "Search...",
      results: "12 results",
      searching: "Searching...",
      saving: "Saving...",
      savingChanges: "Saving changes...",
      textareaLabel: "Textarea",
      textareaPlaceholder: "Write a comment...",
      characterCount: "0/280",
      post: "Post",
      textareaDescription: "Footer positioned below the textarea.",
    },
  },
  ar: {
    dir: "rtl",
    values: {
      placeholder: "بحث...",
      results: "١٢ نتيجة",
      searching: "جاري البحث...",
      saving: "جاري الحفظ...",
      savingChanges: "جاري حفظ التغييرات...",
      textareaLabel: "منطقة النص",
      textareaPlaceholder: "اكتب تعليقًا...",
      characterCount: "٠/٢٨٠",
      post: "نشر",
      textareaDescription: "تذييل موضع أسفل منطقة النص.",
    },
  },
  he: {
    dir: "rtl",
    values: {
      placeholder: "חפש...",
      results: "12 תוצאות",
      searching: "מחפש...",
      saving: "שומר...",
      savingChanges: "שומר שינויים...",
      textareaLabel: "אזור טקסט",
      textareaPlaceholder: "כתוב תגובה...",
      characterCount: "0/280",
      post: "פרסם",
      textareaDescription: "כותרת תחתונה ממוקמת מתחת לאזור הטקסט.",
    },
  },
}

const { dir, values: t } = translations.ar
---

<div class="grid w-full max-w-sm gap-6" dir={dir}>
  <InputGroup class="max-w-xs">
    <InputGroupInput placeholder={t.placeholder} />
    <InputGroupAddon>
      <SearchIcon />
    </InputGroupAddon>
    <InputGroupAddon align="inline-end">{t.results}</InputGroupAddon>
  </InputGroup>
  <InputGroup>
    <InputGroupInput placeholder={t.searching} />
    <InputGroupAddon align="inline-end">
      <Spinner />
    </InputGroupAddon>
  </InputGroup>
  <InputGroup>
    <InputGroupInput placeholder={t.savingChanges} />
    <InputGroupAddon align="inline-end">
      <InputGroupText>{t.saving}</InputGroupText>
      <Spinner />
    </InputGroupAddon>
  </InputGroup>
  <FieldGroup class="max-w-sm">
    <Field>
      <FieldLabel for="rtl-textarea">{t.textareaLabel}</FieldLabel>
      <InputGroup>
        <InputGroupTextarea
          id="rtl-textarea"
          placeholder={t.textareaPlaceholder}
        />
        <InputGroupAddon align="block-end">
          <InputGroupText>{t.characterCount}</InputGroupText>
          <InputGroupButton variant="default" size="sm" class="ms-auto">
            {t.post}
          </InputGroupButton>
        </InputGroupAddon>
      </InputGroup>
      <FieldDescription>{t.textareaDescription}</FieldDescription>
    </Field>
  </FieldGroup>
</div>
```

## API Reference

Source: [`src/components/ui/input-group`](https://github.com/fulldotdev/ui/tree/main/src/components/ui/input-group)

### InputGroupAddon

| Prop    | Type                                                             | Default          |
| ------- | ---------------------------------------------------------------- | ---------------- |
| `align` | `"inline-start" \| "inline-end" \| "block-start" \| "block-end"` | `"inline-start"` |

Use `inline-start` or `inline-end` with `InputGroupInput`, and `block-start` or
`block-end` with `InputGroupTextarea`. An addon can hold several buttons, icons
and texts.

### InputGroupButton

| Prop      | Type                                                                          | Default    |
| --------- | ----------------------------------------------------------------------------- | ---------- |
| `size`    | `"xs" \| "icon-xs" \| "sm" \| "icon-sm"`                                      | `"xs"`     |
| `variant` | `"default" \| "destructive" \| "outline" \| "secondary" \| "ghost" \| "link"` | `"ghost"`  |
| `type`    | `"button" \| "submit" \| "reset"`                                             | `"button"` |

With `href`, it renders a link.

### InputGroupInput and InputGroupTextarea

Replacements for `Input` and `Textarea` inside an input group. They pass all
other attributes to the underlying control and set
`data-slot="input-group-control"`.

## Install what this page shows

```bash
npx shadcn@latest add @fulldev/input-group-examples
```
