---
title: Input Group
description: Display additional information or actions to an input or textarea.
---

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/icon"
	"github.com/axadrn/shadcn-templ/v2/components/inputgroup"
)

templ InputGroupDemo() {
	@inputgroup.InputGroup(inputgroup.Props{Class: "max-w-xs"}) {
		@inputgroup.Input(inputgroup.InputProps{Placeholder: "Search..."})
		@inputgroup.Addon() {
			@icon.Search()
		}
		@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
			12 results
		}
	}
}
```

## Installation

<CodeTabs>

<TabsList>
  <TabsTrigger value="cli">Command</TabsTrigger>
  <TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">

```bash
shadcn-templ add input-group
```

</TabsContent>

<TabsContent value="manual">

<Steps className="mb-0 pt-2">

<Step>Copy and paste the following code into your project.</Step>

<ComponentSource name="input-group" title="components/inputgroup/inputgroup.templ" />

Component scripts are loaded through the shared script bundle, see [JavaScript](/docs/installation#javascript).

<Step>Update the import paths to match your project setup.</Step>

</Steps>

</TabsContent>

</CodeTabs>

## Usage

```go showLineNumbers
import "github.com/axadrn/shadcn-templ/v2/components/inputgroup"
```

```templ showLineNumbers
@inputgroup.InputGroup() {
	@inputgroup.Input(inputgroup.InputProps{Placeholder: "Search..."})
	@inputgroup.Addon() {
		@icon.Search()
	}
}
```

## Composition

Use the following composition to build an `InputGroup`:

```text
inputgroup.InputGroup
├── inputgroup.Input or inputgroup.Textarea
├── inputgroup.Addon
├── inputgroup.Button
└── inputgroup.Text
```

## Align

Use the `Align` prop on `inputgroup.Addon` to position the addon relative to the input.

<Callout>
For proper focus management, `inputgroup.Addon` should always be placed after `inputgroup.Input` or `inputgroup.Textarea` in the DOM. Use the `Align` prop to visually position the addon.
</Callout>

### inline-start

Use `Align: inputgroup.AlignInlineStart` to position the addon at the start of the input. This is the default.

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/field"
	"github.com/axadrn/shadcn-templ/v2/components/icon"
	"github.com/axadrn/shadcn-templ/v2/components/inputgroup"
)

templ InputGroupInlineStart() {
	@field.Field(field.Props{Class: "max-w-sm"}) {
		@field.Label(field.LabelProps{For: "inline-start-input"}) {
			Input
		}
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{ID: "inline-start-input", Placeholder: "Search..."})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineStart}) {
				@icon.Search(icon.Props{Class: "text-muted-foreground"})
			}
		}
		@field.Description() {
			Icon positioned at the start.
		}
	}
}
```

### inline-end

Use `Align: inputgroup.AlignInlineEnd` to position the addon at the end of the input.

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/field"
	"github.com/axadrn/shadcn-templ/v2/components/icon"
	"github.com/axadrn/shadcn-templ/v2/components/inputgroup"
)

templ InputGroupInlineEnd() {
	@field.Field(field.Props{Class: "max-w-sm"}) {
		@field.Label(field.LabelProps{For: "inline-end-input"}) {
			Input
		}
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{ID: "inline-end-input", Type: "password", Placeholder: "Enter password"})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
				@icon.EyeOff()
			}
		}
		@field.Description() {
			Icon positioned at the end.
		}
	}
}
```

### block-start

Use `Align: inputgroup.AlignBlockStart` to position the addon above the input.

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/field"
	"github.com/axadrn/shadcn-templ/v2/components/icon"
	"github.com/axadrn/shadcn-templ/v2/components/inputgroup"
)

templ InputGroupBlockStart() {
	@field.Group(field.GroupProps{Class: "max-w-sm"}) {
		@field.Field() {
			@field.Label(field.LabelProps{For: "block-start-input"}) {
				Input
			}
			@inputgroup.InputGroup(inputgroup.Props{Class: "h-auto"}) {
				@inputgroup.Input(inputgroup.InputProps{ID: "block-start-input", Placeholder: "Enter your name"})
				@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignBlockStart}) {
					@inputgroup.Text() {
						Full Name
					}
				}
			}
			@field.Description() {
				Header positioned above the input.
			}
		}
		@field.Field() {
			@field.Label(field.LabelProps{For: "block-start-textarea"}) {
				Textarea
			}
			@inputgroup.InputGroup() {
				@inputgroup.Textarea(inputgroup.TextareaProps{ID: "block-start-textarea", Placeholder: "console.log('Hello, world!');", Class: "font-mono text-sm"})
				@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignBlockStart}) {
					@icon.FileCode(icon.Props{Class: "text-muted-foreground"})
					@inputgroup.Text(inputgroup.TextProps{Class: "font-mono"}) {
						script.js
					}
					@inputgroup.Button(inputgroup.ButtonProps{Size: inputgroup.ButtonSizeIconXs, Class: "ml-auto"}) {
						@icon.Copy()
						<span class="sr-only">Copy</span>
					}
				}
			}
			@field.Description() {
				Header positioned above the textarea.
			}
		}
	}
}
```

### block-end

Use `Align: inputgroup.AlignBlockEnd` to position the addon below the input.

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/button"
	"github.com/axadrn/shadcn-templ/v2/components/field"
	"github.com/axadrn/shadcn-templ/v2/components/inputgroup"
)

templ InputGroupBlockEnd() {
	@field.Group(field.GroupProps{Class: "max-w-sm"}) {
		@field.Field() {
			@field.Label(field.LabelProps{For: "block-end-input"}) {
				Input
			}
			@inputgroup.InputGroup(inputgroup.Props{Class: "h-auto"}) {
				@inputgroup.Input(inputgroup.InputProps{ID: "block-end-input", Placeholder: "Enter amount"})
				@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignBlockEnd}) {
					@inputgroup.Text() {
						USD
					}
				}
			}
			@field.Description() {
				Footer positioned below the input.
			}
		}
		@field.Field() {
			@field.Label(field.LabelProps{For: "block-end-textarea"}) {
				Textarea
			}
			@inputgroup.InputGroup() {
				@inputgroup.Textarea(inputgroup.TextareaProps{ID: "block-end-textarea", Placeholder: "Write a comment..."})
				@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignBlockEnd}) {
					@inputgroup.Text() {
						0/280
					}
					@inputgroup.Button(inputgroup.ButtonProps{Variant: button.VariantDefault, Size: inputgroup.ButtonSizeSm, Class: "ml-auto"}) {
						Post
					}
				}
			}
			@field.Description() {
				Footer positioned below the textarea.
			}
		}
	}
}
```

## Icon

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/icon"
	"github.com/axadrn/shadcn-templ/v2/components/inputgroup"
)

templ InputGroupIcon() {
	<div class="grid w-full max-w-sm gap-6">
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{Placeholder: "Search..."})
			@inputgroup.Addon() {
				@icon.Search()
			}
		}
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{Type: "email", Placeholder: "Enter your email"})
			@inputgroup.Addon() {
				@icon.Mail()
			}
		}
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{Placeholder: "Card number"})
			@inputgroup.Addon() {
				@icon.CreditCard()
			}
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
				@icon.Check()
			}
		}
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{Placeholder: "Card number"})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
				@icon.Star()
				@icon.Info()
			}
		}
	</div>
}
```

## Text

```templ
package examples

import "github.com/axadrn/shadcn-templ/v2/components/inputgroup"

templ InputGroupText() {
	<div class="grid w-full max-w-sm gap-6">
		@inputgroup.InputGroup() {
			@inputgroup.Addon() {
				@inputgroup.Text() {
					$
				}
			}
			@inputgroup.Input(inputgroup.InputProps{Placeholder: "0.00"})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
				@inputgroup.Text() {
					USD
				}
			}
		}
		@inputgroup.InputGroup() {
			@inputgroup.Addon() {
				@inputgroup.Text() {
					https://
				}
			}
			@inputgroup.Input(inputgroup.InputProps{Placeholder: "example.com", Class: "pl-0.5!"})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
				@inputgroup.Text() {
					.com
				}
			}
		}
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{Placeholder: "Enter your username"})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
				@inputgroup.Text() {
					{ "@company.com" }
				}
			}
		}
		@inputgroup.InputGroup() {
			@inputgroup.Textarea(inputgroup.TextareaProps{Placeholder: "Enter your message"})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignBlockEnd}) {
				@inputgroup.Text(inputgroup.TextProps{Class: "text-xs text-muted-foreground"}) {
					120 characters left
				}
			}
		}
	</div>
}
```

## Button

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/icon"
	"github.com/axadrn/shadcn-templ/v2/components/inputgroup"
	"github.com/axadrn/shadcn-templ/v2/components/popover"
)

templ InputGroupButton() {
	<div class="grid w-full max-w-sm gap-6" data-inputgroup-button-demo>
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{Value: "https://x.com/axadrn", Attributes: templ.Attributes{"readonly": true}})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
				@inputgroup.Button(inputgroup.ButtonProps{
					Size:       inputgroup.ButtonSizeIconXs,
					Attributes: templ.Attributes{"aria-label": "Copy", "title": "Copy", "data-copy-url": "https://x.com/axadrn"},
				}) {
					<span class="[[data-copied=true]_&]:hidden">
						@icon.Copy()
					</span>
					<span class="hidden [[data-copied=true]_&]:inline">
						@icon.Check()
					</span>
				}
			}
		}
		@inputgroup.InputGroup(inputgroup.Props{Class: "[--radius:9999px]"}) {
			@popover.Popover() {
				@inputgroup.Addon(inputgroup.AddonProps{Attributes: popover.Trigger(ctx)}) {
					@inputgroup.Button(inputgroup.ButtonProps{
						Variant: "secondary",
						Size:    inputgroup.ButtonSizeIconXs,
					}) {
						@icon.Info()
					}
				}
				@popover.Content(popover.ContentProps{
					Align: popover.AlignStart,
					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>
				}
			}
			@inputgroup.Addon(inputgroup.AddonProps{Class: "pl-1.5 text-muted-foreground"}) {
				https://
			}
			@inputgroup.Input(inputgroup.InputProps{ID: "input-secure-19"})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
				@inputgroup.Button(inputgroup.ButtonProps{
					Size:       inputgroup.ButtonSizeIconXs,
					Attributes: templ.Attributes{"data-favorite-toggle": true},
				}) {
					@icon.Star(icon.Props{Class: "data-[favorite=true]:fill-blue-600 data-[favorite=true]:stroke-blue-600"})
				}
			}
		}
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{Placeholder: "Type to search..."})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
				@inputgroup.Button(inputgroup.ButtonProps{Variant: "secondary"}) {
					Search
				}
			}
		}
	</div>
	<script nonce={ templ.GetNonce(ctx) }>
		// The vanilla pendant of the demo's copy and favorite state.
		document.addEventListener('click', (e) => {
			if (!(e.target instanceof Element)) return;
			const copy = e.target.closest('[data-copy-url]');
			if (copy && copy.closest('[data-inputgroup-button-demo]')) {
				navigator.clipboard.writeText(copy.getAttribute('data-copy-url')).then(() => {
					copy.setAttribute('data-copied', 'true');
					setTimeout(() => copy.setAttribute('data-copied', 'false'), 1500);
				});
			}
			const fav = e.target.closest('[data-favorite-toggle]');
			if (fav && fav.closest('[data-inputgroup-button-demo]')) {
				const star = fav.querySelector('svg');
				star.setAttribute('data-favorite', star.getAttribute('data-favorite') === 'true' ? 'false' : 'true');
			}
		});
	</script>
}
```

## Kbd

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/icon"
	"github.com/axadrn/shadcn-templ/v2/components/inputgroup"
	"github.com/axadrn/shadcn-templ/v2/components/kbd"
)

templ InputGroupKbd() {
	@inputgroup.InputGroup(inputgroup.Props{Class: "max-w-sm"}) {
		@inputgroup.Input(inputgroup.InputProps{Placeholder: "Search..."})
		@inputgroup.Addon() {
			@icon.Search(icon.Props{Class: "text-muted-foreground"})
		}
		@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
			@kbd.Kbd() {
				⌘K
			}
		}
	}
}
```

## Dropdown

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/dropdownmenu"
	"github.com/axadrn/shadcn-templ/v2/components/icon"
	"github.com/axadrn/shadcn-templ/v2/components/inputgroup"
	"github.com/axadrn/shadcn-templ/v2/utils"
)

templ InputGroupDropdown() {
	<div class="grid w-full max-w-sm gap-4">
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{Placeholder: "Enter file name"})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
				@dropdownmenu.DropdownMenu() {
					@inputgroup.Button(inputgroup.ButtonProps{
						Variant:    "ghost",
						Size:       inputgroup.ButtonSizeIconXs,
						Attributes: utils.MergeAttributes(dropdownmenu.Trigger(ctx), templ.Attributes{"aria-label": "More"}),
					}) {
						@icon.Ellipsis()
					}
					@dropdownmenu.Content(dropdownmenu.ContentProps{Align: dropdownmenu.AlignEnd, SideOffset: 8, AlignOffset: -4}) {
						@dropdownmenu.Group() {
							@dropdownmenu.Item() {
								Settings
							}
							@dropdownmenu.Item() {
								Copy path
							}
							@dropdownmenu.Item() {
								Open location
							}
						}
					}
				}
			}
		}
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{Placeholder: "Enter search query"})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
				@dropdownmenu.DropdownMenu() {
					@inputgroup.Button(inputgroup.ButtonProps{
						Variant:    "ghost",
						Class:      "pr-1.5! text-xs",
						Attributes: dropdownmenu.Trigger(ctx),
					}) {
						Search In...
						@icon.ChevronDown(icon.Props{Class: "size-3"})
					}
					@dropdownmenu.Content(dropdownmenu.ContentProps{Align: dropdownmenu.AlignEnd, SideOffset: 8, AlignOffset: -4}) {
						@dropdownmenu.Group() {
							@dropdownmenu.Item() {
								Documentation
							}
							@dropdownmenu.Item() {
								Blog Posts
							}
							@dropdownmenu.Item() {
								Changelog
							}
						}
					}
				}
			}
		}
	</div>
}
```

## Spinner

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/icon"
	"github.com/axadrn/shadcn-templ/v2/components/inputgroup"
	"github.com/axadrn/shadcn-templ/v2/components/spinner"
)

templ InputGroupSpinner() {
	<div class="grid w-full max-w-sm gap-4">
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{Placeholder: "Searching..."})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
				@spinner.Spinner()
			}
		}
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{Placeholder: "Processing..."})
			@inputgroup.Addon() {
				@spinner.Spinner()
			}
		}
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{Placeholder: "Saving changes..."})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
				@inputgroup.Text() {
					Saving...
				}
				@spinner.Spinner()
			}
		}
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{Placeholder: "Refreshing data..."})
			@inputgroup.Addon() {
				@icon.Loader(icon.Props{Class: "animate-spin"})
			}
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
				@inputgroup.Text(inputgroup.TextProps{Class: "text-muted-foreground"}) {
					Please wait...
				}
			}
		}
	</div>
}
```

## Textarea

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/button"
	"github.com/axadrn/shadcn-templ/v2/components/icon"
	"github.com/axadrn/shadcn-templ/v2/components/inputgroup"
)

templ InputGroupTextareaExample() {
	<div class="grid w-full max-w-md gap-4">
		@inputgroup.InputGroup() {
			@inputgroup.Textarea(inputgroup.TextareaProps{
				ID:          "textarea-code",
				Placeholder: "console.log('Hello, world!');",
				Class:       "min-h-[200px]",
			})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignBlockEnd, Class: "border-t"}) {
				@inputgroup.Text() {
					Line 1, Column 1
				}
				@inputgroup.Button(inputgroup.ButtonProps{Variant: button.VariantDefault, Size: inputgroup.ButtonSizeSm, Class: "ml-auto"}) {
					Run
					@icon.CornerDownLeft()
				}
			}
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignBlockStart, Class: "border-b"}) {
				@inputgroup.Text(inputgroup.TextProps{Class: "font-mono font-medium"}) {
					@icon.FileCode()
					script.js
				}
				@inputgroup.Button(inputgroup.ButtonProps{Size: inputgroup.ButtonSizeIconXs, Class: "ml-auto"}) {
					@icon.RefreshCw()
				}
				@inputgroup.Button(inputgroup.ButtonProps{Variant: button.VariantGhost, Size: inputgroup.ButtonSizeIconXs}) {
					@icon.Copy()
				}
			}
		}
	</div>
}
```

## Custom Input

Add the `data-slot="input-group-control"` attribute to your custom input for automatic focus state handling.

Here's an example of a custom resizable textarea.

```templ
package examples

import "github.com/axadrn/shadcn-templ/v2/components/inputgroup"

templ InputGroupCustom() {
	<div class="grid w-full max-w-sm gap-6">
		@inputgroup.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>
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignBlockEnd}) {
				@inputgroup.Button(inputgroup.ButtonProps{Class: "ml-auto", Size: inputgroup.ButtonSizeSm, Variant: "default"}) {
					Submit
				}
			}
		}
	</div>
}
```

## API Reference

### InputGroup

The main component that wraps inputs and addons.

| Prop    | Type     | Default |
| ------- | -------- | ------- |
| `Class` | `string` | -       |

```templ
@inputgroup.InputGroup() {
	@inputgroup.Input()
	@inputgroup.Addon()
}
```

### InputGroupAddon

Displays icons, text, buttons, or other content alongside inputs.

<Callout>
For proper focus navigation, the `inputgroup.Addon` component should be placed after the input. Set the `Align` prop to position the addon.
</Callout>

| Prop    | Type                                                                      | Default            |
| ------- | ------------------------------------------------------------------------- | ------------------ |
| `Align` | `AlignInlineStart \| AlignInlineEnd \| AlignBlockStart \| AlignBlockEnd` | `AlignInlineStart` |
| `Class` | `string`                                                                  | -                  |

```templ
@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
	@icon.Search()
}
```

**For `inputgroup.Input`, use the `inline-start` or `inline-end` alignment. For `inputgroup.Textarea`, use the `block-start` or `block-end` alignment.**

The `inputgroup.Addon` component can have multiple `inputgroup.Button` components and icons.

```templ
@inputgroup.Addon() {
	@inputgroup.Button() {
		Button
	}
	@inputgroup.Button() {
		Button
	}
}
```

### InputGroupButton

Displays buttons within input groups.

| Prop       | Type                                                                    | Default        |
| ---------- | ------------------------------------------------------------------------ | -------------- |
| `Size`     | `ButtonSizeXs \| ButtonSizeSm \| ButtonSizeIconXs \| ButtonSizeIconSm` | `ButtonSizeXs` |
| `Variant`  | `button.Variant`                                                        | `VariantGhost` |
| `Type`     | `button.Type`                                                           | `TypeButton`   |
| `Disabled` | `bool`                                                                  | `false`        |
| `Class`    | `string`                                                                | -              |

```templ
@inputgroup.Button() {
	Button
}
@inputgroup.Button(inputgroup.ButtonProps{Size: inputgroup.ButtonSizeIconXs, Attributes: templ.Attributes{"aria-label": "Copy"}}) {
	@icon.Copy()
}
```

### InputGroupInput

Replacement for `input.Input` when building input groups. This component has the input group styles pre-applied and uses the unified `data-slot="input-group-control"` for focus state handling.

| Prop          | Type     | Default |
| ------------- | -------- | ------- |
| `Placeholder` | `string` | -       |
| `Value`       | `string` | -       |
| `Class`       | `string` | -       |

```templ
@inputgroup.InputGroup() {
	@inputgroup.Input(inputgroup.InputProps{Placeholder: "Enter text..."})
	@inputgroup.Addon() {
		@icon.Search()
	}
}
```

### InputGroupTextarea

Replacement for `textarea.Textarea` when building input groups. This component has the textarea group styles pre-applied and uses the unified `data-slot="input-group-control"` for focus state handling.

| Prop          | Type     | Default |
| ------------- | -------- | ------- |
| `Placeholder` | `string` | -       |
| `Class`       | `string` | -       |

```templ
@inputgroup.InputGroup() {
	@inputgroup.Textarea(inputgroup.TextareaProps{Placeholder: "Enter message..."})
	@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignBlockEnd}) {
		@inputgroup.Button() {
			Send
		}
	}
}
```

### InputGroupText

The `inputgroup.Text` component displays muted text inside the group.

| Prop    | Type     | Default |
| ------- | -------- | ------- |
| `Class` | `string` | -       |
