p441z/Components/Input
UI · components/ui/input.tsx

Input

Text field that sits flush with Button.

42 linesGitHub ↗
Install with the shadcn CLI

First time with the kit? Read the install guide

About

Input — h-9 to match Button's default height, so a field and a button sit flush side by side in a row without manual alignment.

`bg-transparent` (not bg-background) lets the input inherit whatever surface it sits on — important inside cards, which may be a different shade than the page.

Focus: the border takes the ring color and a soft 3px halo (ring at 30 %) blooms out on `ease-spring` — it grows a touch past 3px and settles. Still quiet, and it never shifts layout since the ring draws outside the box.

v4 note: `outline-hidden` replaces v3's `outline-none`. In v4, `outline-none` literally sets `outline: none`, which removes the focus indicator in forced-colors mode; `outline-hidden` preserves it.

Source

components/ui/input.tsx · 42 lines
import * as React from "react";

import { cn } from "@/lib/utils";

/**
 * Input — h-9 to match Button's default height, so a field and a button sit
 * flush side by side in a row without manual alignment.
 *
 * `bg-transparent` (not bg-background) lets the input inherit whatever
 * surface it sits on — important inside cards, which may be a different
 * shade than the page.
 *
 * Focus: the border takes the ring color and a soft 3px halo (ring at 30 %)
 * blooms out on `ease-spring` — it grows a touch past 3px and settles. Still
 * quiet, and it never shifts layout since the ring draws outside the box.
 *
 * v4 note: `outline-hidden` replaces v3's `outline-none`. In v4,
 * `outline-none` literally sets `outline: none`, which removes the focus
 * indicator in forced-colors mode; `outline-hidden` preserves it.
 */

export type InputProps = React.InputHTMLAttributes<HTMLInputElement>;

const Input = React.forwardRef<HTMLInputElement, InputProps>(
  ({ className, type, ...props }, ref) => {
    return (
      <input
        type={type}
        className={cn(
          "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-[color,border-color,box-shadow] duration-300 ease-spring file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:border-ring focus-visible:outline-hidden focus-visible:ring-[3px] focus-visible:ring-ring/30 disabled:cursor-not-allowed disabled:opacity-50",
          className
        )}
        ref={ref}
        {...props}
      />
    );
  }
);
Input.displayName = "Input";

export { Input };