Back to Design System

Input

Pixexid’s base text input provides consistent spacing, focus rings, and placeholder styles that align with the semantic token system. All native HTML input features are supported and composable with icons or buttons.

Overview

Use for

  • Forms, filters, search fields, and in-panel editors.
  • Embedding icons or buttons using relative containers.
  • Inline forms when paired with smaller button variants.

Avoid for

  • Multi-line content—use `Textarea` instead.
  • Selection lists—use `Select` or `Combobox` (Command) patterns.
  • Password visibility toggles without descriptive labels.

States & patterns

Baseline field

Works with `Label` for accessible name/ID pairing. Placeholder text inherits semantic `text-neutral-strong` token.

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

export function EmailField() {
  return (
    <div className="space-y-2">
      <Label htmlFor="email">Email</Label>
      <Input id="email" type="email" placeholder="you@pixexid.com" />
    </div>
  )
}

Input with leading icon

Add icons using a relative wrapper. Increase left padding to prevent overlap.

import { Input } from "@/components/ui/input"
import { IconSearch } from "@tabler/icons-react"

export function SearchInput() {
  return (
    <div className="relative">
      <IconSearch className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-neutral-strong" />
      <Input className="pl-9" placeholder="Search projects" />
    </div>
  )
}

Validation feedback

Use semantic text colors and `aria-invalid` to ensure assistive technologies announce state.

Enter a valid email address.

import { useState } from "react"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Button } from "@/components/ui/button"

export function SubscribeForm() {
  const [email, setEmail] = useState("")
  const isValid = email.includes("@");

  return (
    <form className="space-y-3">
      <Label htmlFor="newsletter">Join the newsletter</Label>
      <Input
        id="newsletter"
        type="email"
        value={email}
        onChange={(event) => setEmail(event.target.value)}
        aria-invalid={!isValid}
        aria-describedby="newsletter-description"
        placeholder="you@pixexid.com"
      />
      <p id="newsletter-description" className="text-xs text-neutral-strong">
        We send product updates once a week.
      </p>
      <Button type="submit" disabled={!isValid}>
        Subscribe
      </Button>
    </form>
  )
}

Props

PropTypeDefaultDescription
typeReact.ComponentProps<'input'>['type']'text'Standard HTML input types including email, password, number, etc.
classNamestringMerge-friendly override for spacing or layout while retaining baseline styles.
...restReact.ComponentProps<'input'>All native attributes (value, onChange, aria-*, autoComplete, etc.) are forwarded.

Accessibility

Keyboard

  • Tab moves in and out of fields.
  • Honor native input keyboard handling (arrows for `type="number"`, etc.).
  • Set `autoComplete` and `inputMode` for mobile-friendly keyboards.

Guidelines

  • Always pair with a visible `<Label>` or `aria-label`.
  • Provide helper/error text in `aria-describedby` for screen readers.
  • Avoid placeholder-only labelling; placeholders should hint formatting, not primary labels.