Skip to content

Input

A single-line text field for logins, search bars, and checkout forms — with the neobrutalist thick-border and hard-shadow treatment.

import {
  Field,
  FieldDescription,

The input captures a single line of text — names, emails, search queries. Built on the Base UI Input component, a thin wrapper over the native <input>, and dressed in the neobrutalist recipe: thick border, hard shadow, and a high-contrast focus outline.

Reach for it when:

  • Auth and signup forms — email, username, and password fields paired with Field and FieldLabel.
  • Search bars — inline with a Button, or with icons via InputGroup.
  • Checkout and settings pages — addresses, card numbers, and profile fields laid out in a FieldGroup.

Installation

pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/input.json
npx shadcn@latest add https://neobrutalism.com/r/base/input.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/base/input.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/base/input.json

Install the following dependencies:

pnpm add @base-ui/react
npm install @base-ui/react
yarn add @base-ui/react
bun add @base-ui/react

Copy and paste the following code into your project.

components/ui/input.tsx
import * as React from "react"

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

function Input({ className, type, ...props }: React.ComponentProps<"input">) {
  return (
    <input
      type={type}
      data-slot="input"
      className={cn(
        "h-8 w-full min-w-0 rounded border-2 bg-input px-3 py-2 text-sm shadow-sm transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive",
        className
      )}
      {...props}
    />
  )
}

export { Input }

Update the import paths to match your project setup.

Usage

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

Examples

Basic

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

export function InputBasic() {

Field

Use Field, FieldLabel, and FieldDescription to create an input with a label and description.

import {
  Field,
  FieldDescription,

Field Group

Use FieldGroup to show multiple Field blocks and to build forms.

import { Button } from "@/components/ui/button"
import {
  Field,

Disabled

Use the disabled prop to disable the input. To style the disabled state, add the data-disabled attribute to the Field component.

import {
  Field,
  FieldDescription,

Invalid

Use the aria-invalid prop to mark the input as invalid. To style the invalid state, add the data-invalid attribute to the Field component.

import {
  Field,
  FieldDescription,

File

Use the type="file" prop to create a file input.

import {
  Field,
  FieldDescription,

Inline

Use Field with orientation="horizontal" to create an inline input. Pair with Button to create a search input with a button.

import { Button } from "@/components/ui/button"
import { Field } from "@/components/ui/field"
import { Input } from "@/components/ui/input"

Grid

Use a grid layout to place multiple inputs side by side.

import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"

Required

Use the required attribute to indicate required inputs.

import {
  Field,
  FieldDescription,

Badge

Use Badge in the label to highlight a recommended field.

import { Badge } from "@/components/ui/badge"
import { Field, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"

Input Group

To add icons, text, or buttons inside an input, use the InputGroup component. See the Input Group component for more examples.

import { InfoIcon } from "lucide-react"

import { Field, FieldLabel } from "@/components/ui/field"

Button Group

To add buttons to an input, use the ButtonGroup component. See the Button Group component for more examples.

import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
import { Field, FieldLabel } from "@/components/ui/field"

Form

A full form example with multiple inputs, a select, and a button.

import { Button } from "@/components/ui/button"
import {
  Field,

RTL

To enable RTL support in Neobrutalism.com, see the RTL configuration guide.

"use client"

import * as React from "react"

Accessibility

Input renders a native <input>, so keyboard editing, focus, and form submission need no ARIA wiring. What's left is on you:

  • Label every input. Pair it with FieldLabel (or a <label htmlFor>) — a placeholder is not a label; it disappears on type and isn't reliably announced.
  • Associate error text. Set aria-invalid on the input and point aria-describedby at the id of your FieldError or FieldDescription so screen readers read the message with the field.
  • Pick the right type and autocomplete. type="email" plus autocomplete="email" gets the correct mobile keyboard and autofill.