Docs
Input

Input

Displays a form input field or a component that looks like an input field.

Installation

Copy and paste the following code into your project.

import { forwardRef, useId } from "react"
import { cva, type VariantProps } from "class-variance-authority"
 
import { cn } from "@/lib/utils"
 
const inputVariants = cva(
  "border flex border-gray-alpha-400 overflow-hidden bg-background-100 relative focus-within:shadow-input-ring transition-shadow duration-150",
  {
    variants: {
      size: {
        small: "h-8 text-sm rounded-md [--icon-size:14px]",
        medium: "h-10 text-sm rounded-md [--icon-size:16px]",
        large: "h-12 text-base rounded-lg [--icon-size:18px]",
      },
    },
    defaultVariants: {
      size: "medium",
    },
  }
)
 
export interface InputProps
  extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size" | "prefix">,
    VariantProps<typeof inputVariants> {
  prefix?: string | React.ReactNode
  suffix?: string | React.ReactNode
  prefixStyling?: boolean
  suffixStyling?: boolean
  label?: string
}
 
const TextBox = ({
  prefixStyling,
  children,
}: {
  prefixStyling: boolean
  children: React.ReactNode
}) => {
  return (
    <span
      className={cn(
        "flex shrink-0 items-center px-3 text-gray-700 [&>svg]:h-[var(--icon-size)] [&>svg]:w-[var(--icon-size)]",
        prefixStyling && "bg-background-200"
      )}
    >
      {children}
    </span>
  )
}
 
const Input = forwardRef<HTMLInputElement, InputProps>(
  (
    {
      className,
      type,
      size,
      label,
      suffix,
      prefix,
      prefixStyling = true,
      suffixStyling = true,
      ...props
    },
    ref
  ) => {
    const id = useId()
 
    const input = (
      <div className={cn(inputVariants({ size, className }))}>
        {prefix && (
          <span
            className={cn(
              "flex shrink-0 items-center px-3 text-gray-700 [&>svg]:h-[var(--icon-size)] [&>svg]:w-[var(--icon-size)]",
              prefixStyling && "bg-background-200"
            )}
          >
            {prefix}
          </span>
        )}
        <input
          id={id}
          type={type}
          className={cn(
            "bg-transparent outline-none placeholder:text-gray-700 disabled:cursor-not-allowed disabled:bg-background-200 disabled:text-gray-700 disabled:placeholder:text-gray-500",
            ((prefix && prefixStyling) || !prefix) && "pl-3",
            ((suffix && suffixStyling) || !suffix) && "pr-3"
          )}
          ref={ref}
          {...props}
        />
        {suffix && (
          <span
            className={cn(
              "flex shrink-0 items-center px-3 text-gray-700 [&>svg]:h-[var(--icon-size)] [&>svg]:w-[var(--icon-size)]",
              suffixStyling && "bg-background-200"
            )}
          >
            {suffix}
          </span>
        )}
      </div>
    )
 
    if (!label) return input
 
    return (
      <label htmlFor={id}>
        <div className="mb-2 text-xs text-gray-900">{label}</div>
        {input}
      </label>
    )
  }
)
Input.displayName = "Input"
 
export { Input }

Update the import paths to match your project setup.

Usage

import { Input } from "@/components/ui/input"
<Input />

Prefix

https://.com
vercel/

Disabled

With Button

With Label