Skip to content
All Taste components

Forms

Input group

Inputs that carry their unit or address around the value: a currency, a domain, a weight.

inline prefix · inline suffix · attached add-on

₹INR
.sketchxflow.com
Letters, numbers and hyphens.
kg
%
import { cn } from "@/lib/utils";

interface InputGroupProps extends React.InputHTMLAttributes<HTMLInputElement> {
  leading?: React.ReactNode;
  trailing?: React.ReactNode;
  /** "inline" sits inside the field; "addon" is an attached grey segment. */
  look?: "inline" | "addon";
}

export function InputGroup({ leading, trailing, look = "inline", className, ...props }: InputGroupProps) {
  const addon = "flex shrink-0 items-center whitespace-nowrap bg-surface px-3 text-sm text-fg-muted";
  const inline = "flex shrink-0 items-center whitespace-nowrap text-sm text-fg-subtle";
  return (
    <div className="flex h-9 w-full min-w-0 items-stretch overflow-hidden rounded border border-border-strong bg-bg transition focus-within:border-primary focus-within:ring-[3px] focus-within:ring-primary/20">
      {leading && <span className={look === "addon" ? cn(addon, "border-r border-border") : cn(inline, "pl-3")}>{leading}</span>}
      <input
        className={cn(
          "min-w-0 flex-1 bg-transparent px-3 text-sm text-fg outline-none placeholder:text-fg-subtle",
          look === "inline" && leading && "pl-2",
          look === "inline" && trailing && "pr-2",
          className,
        )}
        {...props}
      />
      {trailing && <span className={look === "addon" ? cn(addon, "border-l border-border") : cn(inline, "pr-3")}>{trailing}</span>}
    </div>
  );
}

// <InputGroup aria-label="Advance amount" leading="₹" trailing="INR" inputMode="decimal" />
// <InputGroup aria-label="Site address" trailing=".sketchxflow.com" look="addon" />
// <InputGroup aria-label="Parcel weight" trailing="kg" className="text-right tabular-nums" />

The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.