Input group
A single-field form with the submit button inset, its corners concentric with the field.
Installation
$ pnpm dlx shadcn@latest add @ssntl/input-groupUsage
import { InputGroup, InputGroupButton, InputGroupInput } from "@/components/ui/input-group"
<InputGroup>
<InputGroupInput aria-label="Search" placeholder="Orders, clients…" />
<InputGroupButton aria-label="Search"><Search /></InputGroupButton>
</InputGroup>- Nested corners: the field is a pill with 4px padding around a 48px pill button, so both curves share one center.
- For single-field forms only: search, newsletter, a prompt.
- The icon-only button needs an aria-label; the input needs one too when there is no visible label.
Code
import * as React from "react"
import { cn } from "@/lib/utils"
import { Button } from "@/registry/ssntl/ui/button"
// A single-field form (search, newsletter, prompt) with the submit button set
// inside the field. Nested corners: a pill with 4px padding around a 48px pill
// button, so both curves share one center (outer = inner + padding).
function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="input-group"
className={cn(
"flex w-full min-w-0 items-center gap-1 rounded-full border border-input bg-card p-1 pl-5",
"transition-[border-color] duration-(--duration-fast) ease-out hover:border-muted-foreground",
"focus-within:border-foreground has-[input:focus-visible]:outline-2 has-[input:focus-visible]:outline-offset-2 has-[input:focus-visible]:outline-ring",
"has-aria-invalid:border-destructive",
className
)}
{...props}
/>
)
}
function InputGroupInput({
className,
...props
}: React.ComponentProps<"input">) {
return (
<input
data-slot="input-group-input"
className={cn(
"h-12 min-w-0 flex-1 bg-transparent text-body text-foreground outline-none placeholder:text-muted-foreground",
className
)}
{...props}
/>
)
}
function InputGroupButton({
size = "icon",
className,
...props
}: React.ComponentProps<typeof Button>) {
return (
<Button
data-slot="input-group-button"
size={size}
className={cn("shrink-0", className)}
{...props}
/>
)
}
export { InputGroup, InputGroupButton, InputGroupInput }