VibeUI
ComponentsDocs
VibeUI

Components with taste, that you own. Copy the source, retint the tokens, keep every line.

Library

  • All components
  • Signature pieces
  • Text effects
  • Footers

Docs

  • Introduction
  • Installation
  • Theming
  • CLI

Project

  • GitHub
  • Agents and MCP
  • Issues
  • MIT license
© 2026 VibeUI · MIT licensed
  1. Components
  2. Forms
  3. Input

Input

Text input, textarea, label and Field wrapper sharing one focus language.

FormsServer-safe2 exports

We’ll only use this for receipts.

That name is taken.

Install

bash
npx @agents-npm-packages/vibeui add input --dir ./src/components/ui

Import

tsx
import { Label, Field } from "@/components/ui/input"

API

Generated from the component's TypeScript types, so it always matches the source. * marks a required prop.

<Label>

also accepts every LabelHTMLAttributes<HTMLLabelElement> attribute

No props of its own: it forwards native attributes to the element.

<Field>

also accepts every HTMLAttributes<HTMLDivElement> attribute

PropTypeDefaultDescription
children*ReactNode—Content rendered inside the component.
labelstring—Visible label.
hintstring—Secondary text shown beneath.
errorstring—Error message; also styles the field as invalid.

Source

src/components/ui/input.tsx
import * as React from "react";
import { cn } from "@/lib/utils";

/** Text input, textarea, label and Field wrapper sharing one focus language. */
const fieldBase =
  "w-full rounded-sm border border-line-strong bg-surface text-sm text-ink shadow-quiet placeholder:text-faint transition-[border-color,box-shadow] duration-150 hover:border-faint focus-visible:border-accent focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-pastel-rose-ink aria-invalid:ring-pastel-rose-ink/20";

export const Input = React.forwardRef<
  HTMLInputElement,
  React.InputHTMLAttributes<HTMLInputElement>
>(({ className, type = "text", ...props }, ref) => (
  <input
    ref={ref}
    type={type}
    className={cn(fieldBase, "h-10 px-3", className)}
    {...props}
  />
));
Input.displayName = "Input";

export const Textarea = React.forwardRef<
  HTMLTextAreaElement,
  React.TextareaHTMLAttributes<HTMLTextAreaElement>
>(({ className, ...props }, ref) => (
  <textarea
    ref={ref}
    className={cn(fieldBase, "min-h-24 resize-y px-3 py-2.5 leading-relaxed", className)}
    {...props}
  />
));
Textarea.displayName = "Textarea";

export function Label({
  className,
  ...props
}: React.LabelHTMLAttributes<HTMLLabelElement>) {
  return (
    <label
      className={cn("mb-1.5 block text-[13px] font-medium text-ink-soft", className)}
      {...props}
    />
  );
}

export function Field({
  className,
  label,
  hint,
  error,
  children,
  ...props
}: Omit<React.HTMLAttributes<HTMLDivElement>, "children"> & {
  label?: string;
  hint?: string;
  error?: string;
  children: React.ReactNode;
}) {
  return (
    <div className={cn("flex flex-col", className)} {...props}>
      {label ? <Label>{label}</Label> : null}
      {children}
      {error ? (
        <p className="mt-1.5 text-xs text-pastel-rose-ink">{error}</p>
      ) : hint ? (
        <p className="mt-1.5 text-xs text-muted">{hint}</p>
      ) : null}
    </div>
  );
}

Exports Label and 1 more. Peer dependencies: clsx, tailwind-merge.

PreviousFile DropNextNumber Field