For the complete documentation index, see llms.txt. Markdown variants are available by appending .md to any URL or sending an Accept: text/markdown header. An agent skill is available at /.well-known/agent-skills/site-skill.md.
Home

Input Group

Composes an input with prefix and suffix addons — text, icons, or action buttons — with seamlessly shared borders.

https://
USD
import { Copy, DollarSign, Globe, Search } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { InputGroup, InputGroupText } from "@/components/ui/input-group";

export const InputGroupDemo = () => (
    <div className="flex w-full max-w-sm flex-col gap-4">
      {/* Icon prefix */}
      <InputGroup>
        <InputGroupText><Search /></InputGroupText>
        <Input placeholder="Search..." />
      </InputGroup>
      {/* Text prefix */}
      <InputGroup>
        <InputGroupText><Globe /></InputGroupText>
        <InputGroupText className="text-muted-foreground/60">https://</InputGroupText>
        <Input placeholder="example.com" />
      </InputGroup>
      {/* Currency prefix + text suffix */}
      <InputGroup>
        <InputGroupText><DollarSign /></InputGroupText>
        <Input type="number" placeholder="0.00" />
        <InputGroupText>USD</InputGroupText>
      </InputGroup>
      {/* Input + button suffix */}
      <InputGroup>
        <Input defaultValue="https://ing.design/r/button" readOnly />
        <Button variant="outline">
          <Copy />
          Copy
        </Button>
      </InputGroup>
    </div>
  );

Icon prefix

Wrap a lucide icon in InputGroupText to add a decorative icon that labels the field.

import { Search } from "lucide-react";
import { Input } from "@/components/ui/input";
import { InputGroup, InputGroupText } from "@/components/ui/input-group";
 
<InputGroup>
  <InputGroupText>
    <Search />
  </InputGroupText>
  <Input placeholder="Search..." />
</InputGroup>

Text prefix or suffix

Use InputGroupText for static text such as a URL scheme, currency code, or unit label.

<InputGroup>
  <InputGroupText>https://</InputGroupText>
  <Input placeholder="example.com" />
</InputGroup>
 
<InputGroup>
  <Input type="number" placeholder="0.00" />
  <InputGroupText>kg</InputGroupText>
</InputGroup>

Both sides

Prefix and suffix can be combined freely.

import { DollarSign } from "lucide-react";
 
<InputGroup>
  <InputGroupText>
    <DollarSign />
  </InputGroupText>
  <Input type="number" placeholder="0.00" />
  <InputGroupText>USD</InputGroupText>
</InputGroup>

Button suffix

Place a Button as a direct child of InputGroup. The component uses data-slot selectors to strip the button's adjacent border-radius and collapse its left border against the input.

import { Copy } from "lucide-react";
import { Button } from "@/components/ui/button";
 
<InputGroup>
  <Input defaultValue="https://ing.design/r/button" readOnly />
  <Button variant="outline">
    <Copy />
    Copy
  </Button>
</InputGroup>

With Field

InputGroup composes cleanly with the Field component for accessible labels, descriptions, and error messages.

import { Field, FieldLabel, FieldDescription, FieldError, useField } from "@/components/ui/field";
import { Globe } from "lucide-react";
 
function FieldInput(props) {
  const { id, error } = useField();
  return (
    <InputGroup>
      <InputGroupText>
        <Globe />
      </InputGroupText>
      <Input
        id={id}
        aria-invalid={!!error}
        aria-describedby={error ? `${id}-error` : `${id}-description`}
        {...props}
      />
    </InputGroup>
  );
}
 
<Field>
  <FieldLabel>Website</FieldLabel>
  <FieldInput placeholder="example.com" />
  <FieldDescription>Your public website URL.</FieldDescription>
</Field>

Props

InputGroup

All props are forwarded to the underlying <div>. The component adds no required props — place Input, InputGroupText, and Button as direct children.

InputGroupText

PropTypeDefaultDescription
classNamestring—Merged with addon styles. Use px-2.5 to tighten icon-only addons.

Usage

import { Input } from "@/components/ui/input";
import { InputGroup, InputGroupText } from "@/components/ui/input-group";
 
<InputGroup>
  <InputGroupText>$</InputGroupText>
  <Input type="number" placeholder="0.00" />
</InputGroup>

Specs

# Mint — Input Group Specs
 
## Component
- name: input-group
- file: registry/mint/input-group.tsx
- installs to: components/ui/input-group.tsx
- dependencies: none (uses only React and cn utility)
- registryDependencies: input, button
 
## What is it
A layout wrapper that merges an `Input` with one or more addons — static text,
icons, or action `Button`s — into a visually unified field with shared borders
and seamless rounded corners only on the outermost edges. Use it when a field
needs a contextual prefix or suffix (URL scheme, currency symbol, unit label,
copy button). Do not use it as a general flex container — children must carry
`data-slot` attributes for the selectors to work.
 
## Visual identity
Addons use the muted surface (`--muted`) with a matching `--input` border, so
they read as part of the field rather than separate elements. Radius is applied
only to the outermost corners (`rounded-l-md` / `rounded-r-md`), creating a
pill-like group with no internal gaps. Mint's default radius (1.25rem)
keeps the group soft and rounded.
 
## Design tokens
--input: oklch(0.88 0.04 155 / 60%) / oklch(0.32 0.05 155 / 40%)   — addon and input border colour
--muted: oklch(0.96 0.02 155) / oklch(0.2 0.03 155)       — addon background
--muted-foreground: oklch(0.52 0.06 155) / oklch(0.6 0.06 155) — addon text and icon colour
--ring: oklch(0.5 0.14 155) / oklch(0.62 0.15 155)       — focus ring on Input / Button children
--radius: 1.25rem                                 — outermost corner radius (via rounded-l-md / rounded-r-md)
 
## Sub-components
- InputGroup     → flex container; adjusts radius and negative margin on direct Input and Button children via data-slot selectors
- InputGroupText → static addon (text, icon, or both); muted background, input border, first/last corner radius
 
## States
- focus-visible (Input child):  relative + z-10 so the focus ring renders above adjacent addon borders
- focus-visible (Button child): relative + z-10, same stacking behaviour
- No disabled or error state is applied at the group level — handle these on the Input child directly
 
## Conventions
- Children must be direct (not nested) for the data-slot selectors to apply
- For icon-only addons use `className="px-2.5"` on `InputGroupText` to tighten horizontal padding
- SVG icons inside `InputGroupText` auto-size to 16px — do not set a size class unless overriding intentionally
- `InputGroup` does not wire up ARIA — wrap with `Field` + `useField()` to connect label, description, and error
- Sub-components expose `data-slot="input-group"`, `data-slot="input-group-text"` for CSS targeting
- Button children must use `variant="outline"` to match the input border weight visually

Installation

GIN Design Plugin
$ npx shadcn add https://gin-design.vercel.app/input-group