HextaUI

Input: Controlled

onValueChange hands you the string directly, so there’s no event.target.value to unwrap. onChange still works too.

18/32

"use client"

import * as React from "react"

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

const limit = 32

export function InputControlled() {
  const [value, setValue] = React.useState("Quarterly planning")

  return (
    <div className="flex w-full max-w-sm flex-col gap-2">
      <Label htmlFor="input-controlled">Project name</Label>
      <Input
        id="input-controlled"
        value={value}
        maxLength={limit}
        onValueChange={setValue}
        aria-describedby="input-controlled-count"
      />
      <p
        id="input-controlled-count"
        className="text-end text-sm text-muted-foreground tabular-nums"
      >
        {value.length}/{limit}
      </p>
    </div>
  )
}

This adds the example as components/examples/input/controlled.tsx, together with the Input component and the HextaUI theme tokens it needs.

pnpm dlx shadcn@latest add https://hextaui.com/r/input-controlled.json

To add only the component, follow the Input installation.

Props in this example

The Input props this example sets, from the API reference.

PropTypeDefault
value
string | number | string[]–
onValueChangeCalled with the new value on every change.
(value: string, details) => void–

Every prop is in the Input API reference.

See them all, with keyboard support and accessibility notes, on the Input page.