Zaidan

Command Palette

Search for a command to run...

GitHub

Input Group

Display additional information or actions to an input or textarea.

Installation

CLI

Manual

Copy and paste the following code into your project.

import { cva, type VariantProps } from "class-variance-authority";
import { type ComponentProps, type JSX, splitProps } from "solid-js";
import { cn } from "~/lib/utils";
import { Button, type ButtonProps } from "~/components/ui/button";
import { Input } from "~/components/ui/input";
import { Textarea } from "~/components/ui/textarea";
type InputGroupProps = ComponentProps<"div">;
const InputGroup = (props: InputGroupProps) => {
const [local, others] = splitProps(props, ["class"]);
return (
// biome-ignore lint/a11y/useSemanticElements: <exception for input group>
<div
data-slot="input-group"
role="group"
class={cn(
"group/input-group relative z-input-group flex w-full min-w-0 items-center outline-none has-[>textarea]:h-auto",
local.class,
)}
{...others}
/>
);
};
const inputGroupAddonVariants = cva(
"z-input-group-addon flex cursor-text select-none items-center justify-center",
{
variants: {
align: {
"inline-start": "z-input-group-addon-align-inline-start order-first",
"inline-end": "z-input-group-addon-align-inline-end order-last",
"block-start": "z-input-group-addon-align-block-start order-first w-full justify-start",
"block-end": "z-input-group-addon-align-block-end order-last w-full justify-start",
},
},
defaultVariants: {
align: "inline-start",
},
},
);
type InputGroupAddonProps = ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>;
const InputGroupAddon = (props: InputGroupAddonProps) => {
const [local, others] = splitProps(props, ["class", "align", "onClick"]);
const align = () => local.align ?? "inline-start";
const handleClick: JSX.EventHandler<HTMLDivElement, MouseEvent> = (e) => {
if ((e.target as HTMLElement).closest("button")) {
return;
}
e.currentTarget.parentElement?.querySelector("input")?.focus();
if (typeof local.onClick === "function") {
local.onClick(e);
}
};
return (
// biome-ignore lint/a11y/useSemanticElements: <exception for input group addon>
// biome-ignore lint/a11y/useKeyWithClickEvents: <click delegates focus to input>
<div
role="group"
data-slot="input-group-addon"
data-align={align()}
class={cn(inputGroupAddonVariants({ align: align() }), local.class)}
onClick={handleClick}
{...others}
/>
);
};
const inputGroupButtonVariants = cva("z-input-group-button flex items-center shadow-none", {
variants: {
size: {
xs: "z-input-group-button-size-xs",
sm: "z-input-group-button-size-sm",
"icon-xs": "z-input-group-button-size-icon-xs",
"icon-sm": "z-input-group-button-size-icon-sm",
},
},
defaultVariants: {
size: "xs",
},
});
type InputGroupButtonProps = Omit<ButtonProps, "size"> &
VariantProps<typeof inputGroupButtonVariants> & {
type?: "button" | "submit" | "reset";
};
const InputGroupButton = (props: InputGroupButtonProps) => {
const [local, others] = splitProps(props, ["class", "type", "variant", "size"]);
const size = () => local.size ?? "xs";
const variant = () => local.variant ?? "ghost";
const type = () => local.type ?? "button";
return (
<Button
type={type()}
data-size={size()}
variant={variant()}
class={cn(inputGroupButtonVariants({ size: size() }), local.class)}
{...others}
/>
);
};
type InputGroupTextProps = ComponentProps<"span">;
const InputGroupText = (props: InputGroupTextProps) => {
const [local, others] = splitProps(props, ["class"]);
return (
<span
class={cn("z-input-group-text flex items-center [&_svg]:pointer-events-none", local.class)}
{...others}
/>
);
};
type InputGroupInputProps = ComponentProps<"input">;
const InputGroupInput = (props: InputGroupInputProps) => {
const [local, others] = splitProps(props, ["class"]);
return (
<Input
data-slot="input-group-control"
class={cn("z-input-group-input flex-1", local.class)}
{...others}
/>
);
};
type InputGroupTextareaProps = ComponentProps<"textarea">;
const InputGroupTextarea = (props: InputGroupTextareaProps) => {
const [local, others] = splitProps(props, ["class"]);
return (
<Textarea
data-slot="input-group-control"
class={cn("z-input-group-textarea flex-1 resize-none", local.class)}
{...others}
/>
);
};
export {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupText,
InputGroupInput,
InputGroupTextarea,
type InputGroupProps,
type InputGroupAddonProps,
type InputGroupButtonProps,
type InputGroupTextProps,
type InputGroupInputProps,
type InputGroupTextareaProps,
};

Examples

Here are the source code of all the examples from the preview page:

Basic

import { Field, FieldGroup, FieldLabel } from "~/components/ui/field";
import { Input } from "~/components/ui/input";
import { InputGroup, InputGroupInput } from "~/components/ui/input-group";
function InputGroupBasic() {
return (
<Example title="Basic">
<FieldGroup>
<Field>
<FieldLabel for="input-default-01">Default (No Input Group)</FieldLabel>
<Input placeholder="Placeholder" id="input-default-01" />
</Field>
<Field>
<FieldLabel for="input-group-02">Input Group</FieldLabel>
<InputGroup>
<InputGroupInput id="input-group-02" placeholder="Placeholder" />
</InputGroup>
</Field>
<Field data-disabled="true">
<FieldLabel for="input-disabled-03">Disabled</FieldLabel>
<InputGroup>
<InputGroupInput id="input-disabled-03" placeholder="This field is disabled" disabled />
</InputGroup>
</Field>
<Field data-invalid="true">
<FieldLabel for="input-invalid-04">Invalid</FieldLabel>
<InputGroup>
<InputGroupInput
id="input-invalid-04"
placeholder="This field is invalid"
aria-invalid="true"
/>
</InputGroup>
</Field>
</FieldGroup>
</Example>
);
}

With Addons

import { toast } from "solid-sonner";
import {
Copy,
EyeOff,
Info,
Mic,
Radio,
Search,
Star,
} from "lucide-solid";
import { Field, FieldDescription, FieldGroup, FieldLabel } from "~/components/ui/field";
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupInput,
InputGroupText,
} from "~/components/ui/input-group";
function InputGroupWithAddons() {
return (
<Example title="With Addons">
<FieldGroup>
<Field>
<FieldLabel for="input-icon-left-05">Addon (inline-start)</FieldLabel>
<InputGroup>
<InputGroupInput id="input-icon-left-05" />
<InputGroupAddon>
<Search class="text-muted-foreground" />
</InputGroupAddon>
</InputGroup>
</Field>
<Field>
<FieldLabel for="input-icon-right-07">Addon (inline-end)</FieldLabel>
<InputGroup>
<InputGroupInput id="input-icon-right-07" />
<InputGroupAddon align="inline-end">
<EyeOff />
</InputGroupAddon>
</InputGroup>
</Field>
<Field>
<FieldLabel for="input-icon-both-09">Addon (inline-start and inline-end)</FieldLabel>
<InputGroup>
<InputGroupInput id="input-icon-both-09" />
<InputGroupAddon>
<Mic class="text-muted-foreground" />
</InputGroupAddon>
<InputGroupAddon align="inline-end">
<Radio class="animate-pulse text-red-500" />
</InputGroupAddon>
</InputGroup>
</Field>
<Field>
<FieldLabel for="input-addon-20">Addon (block-start)</FieldLabel>
<InputGroup class="h-auto">
<InputGroupInput id="input-addon-20" />
<InputGroupAddon align="block-start">
<InputGroupText>First Name</InputGroupText>
<Info class="ml-auto text-muted-foreground" />
</InputGroupAddon>
</InputGroup>
</Field>
<Field>
<FieldLabel for="input-addon-21">Addon (block-end)</FieldLabel>
<InputGroup class="h-auto">
<InputGroupInput id="input-addon-21" />
<InputGroupAddon align="block-end">
<InputGroupText>20/240 characters</InputGroupText>
<Info class="ml-auto text-muted-foreground" />
</InputGroupAddon>
</InputGroup>
</Field>
<Field>
<FieldLabel for="input-icon-both-10">Multiple Icons</FieldLabel>
<InputGroup>
<InputGroupInput id="input-icon-both-10" />
<InputGroupAddon align="inline-end">
<Star />
<InputGroupButton size="icon-xs" onClick={() => toast("Copied to clipboard")}>
<Copy />
</InputGroupButton>
</InputGroupAddon>
<InputGroupAddon>
<Radio class="animate-pulse text-red-500" />
</InputGroupAddon>
</InputGroup>
</Field>
<Field>
<FieldLabel for="input-description-10">Description</FieldLabel>
<InputGroup>
<InputGroupInput id="input-description-10" />
<InputGroupAddon align="inline-end">
<Info />
</InputGroupAddon>
</InputGroup>
<FieldDescription>This is a description of the input group.</FieldDescription>
</Field>
<Field>
<FieldLabel for="input-label-10">Label</FieldLabel>
<InputGroup>
<InputGroupAddon>
<FieldLabel for="input-label-10">Label</FieldLabel>
</InputGroupAddon>
<InputGroupInput id="input-label-10" />
</InputGroup>
<InputGroup>
<InputGroupInput id="input-optional-12" aria-label="Optional" />
<InputGroupAddon align="inline-end">
<InputGroupText>(optional)</InputGroupText>
</InputGroupAddon>
</InputGroup>
</Field>
</FieldGroup>
</Example>
);
}

With Buttons

import { Copy, Trash } from "lucide-solid";
import { Field, FieldGroup, FieldLabel } from "~/components/ui/field";
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupInput,
} from "~/components/ui/input-group";
function InputGroupWithButtons() {
return (
<Example title="With Buttons">
<FieldGroup>
<Field>
<FieldLabel for="input-button-13">Button</FieldLabel>
<InputGroup>
<InputGroupInput id="input-button-13" />
<InputGroupAddon>
<InputGroupButton>Default</InputGroupButton>
</InputGroupAddon>
</InputGroup>
<InputGroup>
<InputGroupInput id="input-button-14" />
<InputGroupAddon>
<InputGroupButton variant="outline">Outline</InputGroupButton>
</InputGroupAddon>
</InputGroup>
<InputGroup>
<InputGroupInput id="input-button-15" />
<InputGroupAddon>
<InputGroupButton variant="secondary">Secondary</InputGroupButton>
</InputGroupAddon>
</InputGroup>
<InputGroup>
<InputGroupInput id="input-button-16" />
<InputGroupAddon align="inline-end">
<InputGroupButton variant="secondary">Button</InputGroupButton>
</InputGroupAddon>
</InputGroup>
<InputGroup>
<InputGroupInput id="input-button-17" />
<InputGroupAddon align="inline-end">
<InputGroupButton size="icon-xs">
<Copy />
</InputGroupButton>
</InputGroupAddon>
</InputGroup>
<InputGroup>
<InputGroupInput id="input-button-18" />
<InputGroupAddon align="inline-end">
<InputGroupButton variant="secondary" size="icon-xs">
<Trash />
</InputGroupButton>
</InputGroupAddon>
</InputGroup>
</Field>
</FieldGroup>
</Example>
);
}

With Tooltip, Dropdown, Popover

import { toast } from "solid-sonner";
import { ChevronDown, Info, Star } from "lucide-solid";
import { ButtonGroup, ButtonGroupText } from "~/components/ui/button-group";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "~/components/ui/dropdown-menu";
import { Field, FieldDescription, FieldGroup, FieldLabel } from "~/components/ui/field";
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupInput,
} from "~/components/ui/input-group";
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from "~/components/ui/popover";
import { Tooltip, TooltipContent, TooltipTrigger } from "~/components/ui/tooltip";
function InputGroupWithTooltip(props: { country: string; setCountry: (value: string) => void }) {
return (
<Example title="With Tooltip, Dropdown, Popover">
<FieldGroup>
<Field>
<FieldLabel for="input-tooltip-20">Tooltip</FieldLabel>
<InputGroup>
<InputGroupInput id="input-tooltip-20" />
<InputGroupAddon align="inline-end">
<Tooltip>
<TooltipTrigger as={InputGroupButton} class="rounded-full" size="icon-xs">
<Info />
</TooltipTrigger>
<TooltipContent>This is content in a tooltip.</TooltipContent>
</Tooltip>
</InputGroupAddon>
</InputGroup>
<FieldDescription>This is a description of the input group.</FieldDescription>
</Field>
<Field>
<FieldLabel for="input-dropdown-21">Dropdown</FieldLabel>
<InputGroup>
<InputGroupInput id="input-dropdown-21" />
<InputGroupAddon>
<DropdownMenu>
<DropdownMenuTrigger
as={InputGroupButton}
class="text-muted-foreground tabular-nums"
>
{props.country} <ChevronDown />
</DropdownMenuTrigger>
<DropdownMenuContent class="min-w-16">
<DropdownMenuItem onSelect={() => props.setCountry("+1")}>+1</DropdownMenuItem>
<DropdownMenuItem onSelect={() => props.setCountry("+44")}>+44</DropdownMenuItem>
<DropdownMenuItem onSelect={() => props.setCountry("+46")}>+46</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</InputGroupAddon>
</InputGroup>
<FieldDescription>This is a description of the input group.</FieldDescription>
</Field>
<Field>
<FieldLabel for="input-secure-19">Popover</FieldLabel>
<InputGroup>
<Popover>
<PopoverTrigger as={InputGroupAddon}>
<InputGroupButton variant="secondary" size="icon-xs">
<Info />
</InputGroupButton>
</PopoverTrigger>
<PopoverContent>
<PopoverHeader>
<PopoverTitle>Your connection is not secure.</PopoverTitle>
<PopoverDescription>
You should not enter any sensitive information on this site.
</PopoverDescription>
</PopoverHeader>
</PopoverContent>
</Popover>
<InputGroupAddon class="pl-1 text-muted-foreground">https://</InputGroupAddon>
<InputGroupInput id="input-secure-19" />
<InputGroupAddon align="inline-end">
<InputGroupButton size="icon-xs" onClick={() => toast("Added to favorites")}>
<Star />
</InputGroupButton>
</InputGroupAddon>
</InputGroup>
<FieldDescription>This is a description of the input group.</FieldDescription>
</Field>
<Field>
<FieldLabel for="url">Button Group</FieldLabel>
<ButtonGroup>
<ButtonGroupText>https://</ButtonGroupText>
<InputGroup>
<InputGroupInput id="url" />
<InputGroupAddon align="inline-end">
<Info />
</InputGroupAddon>
</InputGroup>
<ButtonGroupText>.com</ButtonGroupText>
</ButtonGroup>
<FieldDescription>This is a description of the input group.</FieldDescription>
</Field>
</FieldGroup>
</Example>
);
}

With Kbd

import { Check, Info, Search, Sparkles } from "lucide-solid";
import { Field, FieldDescription, FieldGroup, FieldLabel } from "~/components/ui/field";
import {
InputGroup,
InputGroupAddon,
InputGroupInput,
} from "~/components/ui/input-group";
import { Kbd, KbdGroup } from "~/components/ui/kbd";
import { Spinner } from "~/components/ui/spinner";
function InputGroupWithKbd() {
return (
<Example title="With Kbd">
<FieldGroup>
<Field>
<FieldLabel for="input-kbd-22">Input Group with Kbd</FieldLabel>
<InputGroup>
<InputGroupInput id="input-kbd-22" />
<InputGroupAddon>
<Kbd>⌘K</Kbd>
</InputGroupAddon>
</InputGroup>
<InputGroup>
<InputGroupInput id="input-kbd-23" />
<InputGroupAddon align="inline-end">
<Kbd>⌘K</Kbd>
</InputGroupAddon>
</InputGroup>
<InputGroup>
<InputGroupInput id="input-search-apps-24" placeholder="Search for Apps..." />
<InputGroupAddon align="inline-end">Ask AI</InputGroupAddon>
<InputGroupAddon align="inline-end">
<Kbd>Tab</Kbd>
</InputGroupAddon>
</InputGroup>
<InputGroup>
<InputGroupInput id="input-search-type-25" placeholder="Type to search..." />
<InputGroupAddon align="inline-start">
<Sparkles />
</InputGroupAddon>
<InputGroupAddon align="inline-end">
<KbdGroup>
<Kbd>Ctrl</Kbd>
<Kbd>C</Kbd>
</KbdGroup>
</InputGroupAddon>
</InputGroup>
</Field>
<Field>
<FieldLabel for="input-username-26">Username</FieldLabel>
<InputGroup>
<InputGroupInput id="input-username-26" value="shadcn" />
<InputGroupAddon align="inline-end">
<div class="flex size-4 items-center justify-center rounded-full bg-green-500 dark:bg-green-800">
<Check class="size-3 text-white" />
</div>
</InputGroupAddon>
</InputGroup>
<FieldDescription class="text-green-700">This username is available.</FieldDescription>
</Field>
<InputGroup>
<InputGroupInput id="input-search-docs-27" placeholder="Search documentation..." />
<InputGroupAddon>
<Search />
</InputGroupAddon>
<InputGroupAddon align="inline-end">12 results</InputGroupAddon>
</InputGroup>
<InputGroup data-disabled="true">
<InputGroupInput
id="input-search-disabled-28"
placeholder="Search documentation..."
disabled
/>
<InputGroupAddon>
<Search />
</InputGroupAddon>
<InputGroupAddon align="inline-end">Disabled</InputGroupAddon>
</InputGroup>
<FieldGroup class="grid grid-cols-2 gap-4">
<Field>
<FieldLabel for="input-group-11">First Name</FieldLabel>
<InputGroup>
<InputGroupInput id="input-group-11" placeholder="First Name" />
<InputGroupAddon align="inline-end">
<Info />
</InputGroupAddon>
</InputGroup>
</Field>
<Field>
<FieldLabel for="input-group-12">Last Name</FieldLabel>
<InputGroup>
<InputGroupInput id="input-group-12" placeholder="Last Name" />
<InputGroupAddon align="inline-end">
<Info />
</InputGroupAddon>
</InputGroup>
</Field>
</FieldGroup>
<Field data-disabled="true">
<FieldLabel for="input-group-29">Loading ("data-disabled="true")</FieldLabel>
<InputGroup>
<InputGroupInput id="input-group-29" disabled value="shadcn" />
<InputGroupAddon align="inline-end">
<Spinner />
</InputGroupAddon>
</InputGroup>
<FieldDescription>This is a description of the input group.</FieldDescription>
</Field>
</FieldGroup>
</Example>
);
}

In Card

import { ExternalLink, Mail } from "lucide-solid";
import { Button } from "~/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "~/components/ui/card";
import { Field, FieldGroup, FieldLabel } from "~/components/ui/field";
import {
InputGroup,
InputGroupAddon,
InputGroupInput,
InputGroupText,
InputGroupTextarea,
} from "~/components/ui/input-group";
function InputGroupInCard() {
return (
<Example title="In Card">
<Card class="w-full">
<CardHeader>
<CardTitle>Card with Input Group</CardTitle>
<CardDescription>This is a card with an input group.</CardDescription>
</CardHeader>
<CardContent>
<FieldGroup>
<Field>
<FieldLabel for="email-input">Email Address</FieldLabel>
<InputGroup>
<InputGroupInput id="email-input" type="email" placeholder="you@example.com" />
<InputGroupAddon align="inline-end">
<Mail />
</InputGroupAddon>
</InputGroup>
</Field>
<Field>
<FieldLabel for="website-input">Website URL</FieldLabel>
<InputGroup>
<InputGroupAddon>
<InputGroupText>https://</InputGroupText>
</InputGroupAddon>
<InputGroupInput id="website-input" placeholder="example.com" />
<InputGroupAddon align="inline-end">
<ExternalLink />
</InputGroupAddon>
</InputGroup>
</Field>
<Field>
<FieldLabel for="feedback-textarea">Feedback &amp; Comments</FieldLabel>
<InputGroup>
<InputGroupTextarea
id="feedback-textarea"
placeholder="Share your thoughts..."
class="min-h-[100px]"
/>
<InputGroupAddon align="block-end">
<InputGroupText>0/500 characters</InputGroupText>
</InputGroupAddon>
</InputGroup>
</Field>
</FieldGroup>
</CardContent>
<CardFooter class="justify-end gap-2">
<Button variant="outline">Cancel</Button>
<Button>Submit</Button>
</CardFooter>
</Card>
</Example>
);
}

Textarea

import { ArrowUp, Code, Copy, Info, RefreshCw } from "lucide-solid";
import { Field, FieldDescription, FieldGroup, FieldLabel } from "~/components/ui/field";
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupText,
InputGroupTextarea,
} from "~/components/ui/input-group";
import { Textarea } from "~/components/ui/textarea";
function InputGroupTextareaExamples() {
return (
<Example title="Textarea">
<FieldGroup>
<Field>
<FieldLabel for="textarea-header-footer-12">Default Textarea (No Input Group)</FieldLabel>
<Textarea id="textarea-header-footer-12" placeholder="Enter your text here..." />
</Field>
<Field>
<FieldLabel for="textarea-header-footer-13">Input Group</FieldLabel>
<InputGroup>
<InputGroupTextarea
id="textarea-header-footer-13"
placeholder="Enter your text here..."
/>
</InputGroup>
<FieldDescription>This is a description of the input group.</FieldDescription>
</Field>
<Field data-invalid="true">
<FieldLabel for="textarea-header-footer-14">Invalid</FieldLabel>
<InputGroup>
<InputGroupTextarea
id="textarea-header-footer-14"
placeholder="Enter your text here..."
aria-invalid="true"
/>
</InputGroup>
<FieldDescription>This is a description of the input group.</FieldDescription>
</Field>
<Field data-disabled="true">
<FieldLabel for="textarea-header-footer-15">Disabled</FieldLabel>
<InputGroup>
<InputGroupTextarea
id="textarea-header-footer-15"
placeholder="Enter your text here..."
disabled
/>
</InputGroup>
<FieldDescription>This is a description of the input group.</FieldDescription>
</Field>
<Field>
<FieldLabel for="prompt-31">Addon (block-start)</FieldLabel>
<InputGroup>
<InputGroupTextarea id="prompt-31" />
<InputGroupAddon align="block-start">
<InputGroupText>Ask, Search or Chat...</InputGroupText>
<Info class="ml-auto text-muted-foreground" />
</InputGroupAddon>
</InputGroup>
<FieldDescription>This is a description of the input group.</FieldDescription>
</Field>
<Field>
<FieldLabel for="textarea-header-footer-30">Addon (block-end)</FieldLabel>
<InputGroup>
<InputGroupTextarea
id="textarea-header-footer-30"
placeholder="Enter your text here..."
/>
<InputGroupAddon align="block-end">
<InputGroupText>0/280 characters</InputGroupText>
<InputGroupButton variant="default" size="icon-xs" class="ml-auto rounded-full">
<ArrowUp />
<span class="sr-only">Send</span>
</InputGroupButton>
</InputGroupAddon>
</InputGroup>
</Field>
<Field>
<FieldLabel for="textarea-comment-31">Addon (Buttons)</FieldLabel>
<InputGroup>
<InputGroupTextarea
id="textarea-comment-31"
placeholder="Share your thoughts..."
class="min-h-[120px]"
/>
<InputGroupAddon align="block-end">
<InputGroupButton variant="ghost" class="ml-auto" size="sm">
Cancel
</InputGroupButton>
<InputGroupButton variant="default" size="sm">
Post Comment
</InputGroupButton>
</InputGroupAddon>
</InputGroup>
</Field>
<Field>
<FieldLabel for="textarea-code-32">Code Editor</FieldLabel>
<InputGroup>
<InputGroupTextarea
id="textarea-code-32"
placeholder="console.log('Hello, world!');"
class="min-h-[300px] py-3"
/>
<InputGroupAddon align="block-start" class="border-b">
<InputGroupText class="font-medium font-mono">
<Code />
script.js
</InputGroupText>
<InputGroupButton size="icon-xs" class="ml-auto">
<RefreshCw />
</InputGroupButton>
<InputGroupButton size="icon-xs" variant="ghost">
<Copy />
</InputGroupButton>
</InputGroupAddon>
<InputGroupAddon align="block-end" class="border-t">
<InputGroupText>Line 1, Column 1</InputGroupText>
<InputGroupText class="ml-auto">JavaScript</InputGroupText>
</InputGroupAddon>
</InputGroup>
</Field>
</FieldGroup>
</Example>
);
}

API Reference

InputGroup

The main component that wraps inputs and addons.

PropTypeDefault
classstring
<InputGroup>
<InputGroupInput />
<InputGroupAddon />
</InputGroup>

InputGroupAddon

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

For proper focus navigation, the InputGroupAddon component should be placed after the input. Set the align prop to position the addon.

PropTypeDefault
align"inline-start" | "inline-end" | "block-start" | "block-end""inline-start"
classstring
<InputGroupAddon align="inline-end">
<SearchIcon />
</InputGroupAddon>

For <InputGroupInput />, use the inline-start or inline-end alignment. For <InputGroupTextarea />, use the block-start or block-end alignment.

The InputGroupAddon component can have multiple InputGroupButton components and icons.

<InputGroupAddon>
<InputGroupButton>Button</InputGroupButton>
<InputGroupButton>Button</InputGroupButton>
</InputGroupAddon>

InputGroupButton

Displays buttons within input groups.

PropTypeDefault
size"xs" | "icon-xs" | "sm" | "icon-sm""xs"
variant"default" | "destructive" | "outline" | "secondary" | "ghost" | "link""ghost"
classstring
<InputGroupButton>Button</InputGroupButton>
<InputGroupButton size="icon-xs" aria-label="Copy">
<CopyIcon />
</InputGroupButton>

InputGroupInput

Replacement for <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.

PropTypeDefault
classstring

All other props are passed through to the underlying <Input /> component.

<InputGroup>
<InputGroupInput placeholder="Enter text..." />
<InputGroupAddon>
<SearchIcon />
</InputGroupAddon>
</InputGroup>

InputGroupTextarea

Replacement for <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.

PropTypeDefault
classstring

All other props are passed through to the underlying <Textarea /> component.

<InputGroup>
<InputGroupTextarea placeholder="Enter message..." />
<InputGroupAddon align="block-end">
<InputGroupButton>Send</InputGroupButton>
</InputGroupAddon>
</InputGroup>