Componentform
Input Group
Input with prefix icon slot, suffix slot, and inner action button; dashed focus ring and animated underline sweep.
Preview
Live Preview
Email
Installation
Tokens guide →Add to your project via CLI (zero dependencies, code you own):
npx bigbullui add input-groupOr install the full npm package:
npm install bigbulluiUsage
import { InputGroup } from "@/components/ui/input-group";
<InputGroup placeholder="Search tickets" prefix={<SearchIcon />} suffix={<ClearButton />} />Source code
input-group.tsxZero dependencies (only React + utils). Copy and paste directly into your project:
"use client";
import * as React from "react";
import { cn } from "./lib/utils";
export type InputGroupProps = {
children?: React.ReactNode;
className?: string;
placeholder?: string;
};
const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
({ children, className, placeholder }, ref) => {
return (
<div
ref={ref}
className={cn(
"relative flex h-10 w-full rounded-md border border-input bg-background px-3 py-1.5 placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-input transition-colors",
"motion-reduce:transition-none",
className
)}
>
<div className="absolute left-0 inset-y-0 pl-2 flex items-center pointer-events-none">
{/* Prefix slot */}
</div>
<div className="flex-1 flex flex-col">
{children}
<input
type="text"
placeholder={placeholder}
className={cn(
"flex-1 rounded-none bg-transparent outline-none placeholder:text-muted-foreground",
"motion-reduce:transition-none"
)}
/>
</div>
{/* Suffix slot */}
<div className="absolute right-0 inset-y-0 pr-2 flex items-center pointer-events-none">
{/* Action button slot */}
</div>
{/* Focus ring underline */}
<div
className={cn(
"absolute inset-0 pointer-events-none outline-none",
"after:content-[''] after:absolute after:-inset-0 after:rounded-md after:bg-ring after:scale-x-0 after:origin-left after:transition-transform duration-200",
"after:motion-reduce:scale-x-0 after:motion-reduce:transition-none",
"hover:after:scale-x-100",
"focus-visible:after:scale-x-100 focus-visible:after:outline-none",
"motion-reduce:transition-none"
)}
/>
</div>
);
}
);
InputGroup.displayName = "InputGroup";
export { InputGroup };
Props
| Prop | Type | Description |
|---|---|---|
| prefix | ReactNode | Leading slot content. |
| suffix | ReactNode | Trailing slot content. |
| placeholder | string | Input placeholder. |