Forms
Field
Wires a label, hint and error message to a form control.
Import
import { Field } from '@the_viveksingh/vivek-ui'Label, hint and error
Field derives every id and ARIA relationship from one place. aria-describedby points at the error when there is one and the hint when there is not, because a screen-reader user needs the reason their input was rejected, not the tip.
We will never share it.
That is not an email address.
<Field label="Email" help="We will never share it." required>
<Input type="email" autoComplete="email" />
</Field>
<Field label="Email" error="That is not an email address.">
<Input type="email" defaultValue="not-an-email" />
</Field>Works with any control
Markdown is not supported.
<Field label="Bio" help="Markdown is not supported.">
<Textarea rows={3} />
</Field>
<Field label="Role">
<Select placeholder="Choose one" options={[
{ value: 'dev', label: 'Developer' },
{ value: 'des', label: 'Designer' },
]} />
</Field>Props
Generated from the package's own type declarations, so this table cannot drift from the code.
| Prop | Type | Default | Description |
|---|---|---|---|
label | ReactNode | — | Visible label, wired to the control with `htmlFor`. |
help | ReactNode | — | Hint text, wired via `aria-describedby`. |
error | ReactNode | — | Error text. When set, the control gets `aria-invalid` and the message replaces the hint in `aria-describedby`, so a screen reader hears the problem, not the tip. |
required | boolean | — | Marks the label and sets `required` on the control. |
size | 'sm' | 'md' | — | — |
id | string | — | Explicit id for the control. One is generated when omitted. |
children required | ReactNode | — | Exactly one form control: `Input`, `Textarea`, `Select`, and so on. |
Every remaining prop is spread onto the root element, so all standard HTML and ARIA attributes work. className and style are merged with the library's own, never replaced, and the ref forwards to the root DOM node.
Rendering
Field declares 'use client' because it needs state, effects or event handlers. Importing it into a Server Component creates a client boundary at this component — everything above it stays on the server.