142 lines · 3.9 KB
import { forwardRef, useId } from "react";
import { cn } from "~/utils/cn";

const CONTROL =
  "w-full rounded-md border border-gray-700 bg-gray-900/80 px-3 text-sm text-gray-100 placeholder:text-gray-600 focus:border-accent-500 focus:ring-1 focus:ring-accent-500 focus:outline-none disabled:opacity-60";

type FieldShellProps = {
  label: string;
  hint?: string;
  error?: string | null;
  id: string;
  children: React.ReactNode;
};

function FieldShell({ label, hint, error, id, children }: FieldShellProps) {
  return (
    <div className="space-y-1.5">
      <label htmlFor={id} className="block text-sm font-medium text-gray-300">
        {label}
      </label>
      {children}
      {hint && !error && <p className="text-xs text-gray-500">{hint}</p>}
      {error && (
        <p id={`${id}-error`} role="alert" className="text-xs text-red-400">
          {error}
        </p>
      )}
    </div>
  );
}

type InputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "id"> & {
  label: string;
  hint?: string;
  error?: string | null;
};

export const TextField = forwardRef<HTMLInputElement, InputProps>(function TextField(
  { label, hint, error, className, ...rest },
  ref,