Input
The single-line text control for short_text, email, phone, url and number fields.
A styled <input> bound to a field. Field renders it for short_text, email, phone, url and number; import it directly when you compose a field by hand.
Preview
Usage
// kibble/forms/newsletter.ts
import { defineForm } from 'kibbleforms/schema';
export const newsletter = defineForm({
slug: 'newsletter',
name: 'Newsletter',
pages: [{ fields: [{ key: 'email', type: 'email', label: 'Work email', placeholder: '[email protected]', autocomplete: 'email', required: true }] }],
});
// Rendered by <Form> automatically, or by hand:
import { Form, Field, Input, Submit } from 'kibbleforms';
<Form schema={newsletter} client={kibble}>
<Field name="email" /> {/* label + help + <Input /> + error */}
<Submit />
</Form>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
name |
string |
required | The field key. |
type |
string |
by field type | Overrides the HTML type: email→email, phone→tel, url→url, number→text (with inputMode="decimal", or numeric when integer: true), otherwise text. |
className |
string |
control classes | Merged onto the <input>. |
…<input> attributes |
Everything except name, value, onChange (those come from the field). placeholder defaults to the schema's placeholder. |
Renders <input data-kb="input">. For a hidden field, Input renders HiddenInput (<input type="hidden" data-kb="hidden">) instead.
autocomplete comes from the schema's autocomplete, else a default: email for email fields, tel for phone, url for url, and name / given-name / family-name / organization when a short_text key looks like one. Values are normalized on submit (trimmed, emails lower-cased, phones to E.164, URLs given https://), so the input itself never reformats what the visitor types.
Variants and states
const fields = [
{ key: 'name', type: 'short_text', label: 'Full name', help: 'As it appears on your badge.', autocomplete: 'name', required: true },
{ key: 'website', type: 'url', label: 'Website', placeholder: 'acme.com', defaultValue: 'https://acme.com' },
{ key: 'seats', type: 'number', label: 'Seats', integer: true, min: 1, max: 500, required: true },
];
- Required: the label gets the required indicator and the input
aria-required. - With help:
helprenders below the label and is linked viaaria-describedby. - Prefilled:
defaultValue,prefill: { query }(from the URL) orinitialValuesonForm. - Error: after a failed submit,
aria-invalid="true"turns the border red andFieldErrorappears. Format errors (bad email, bad URL) also show on blur; "required" waits for submit. - Disabled: pass
disabledwhen composing; the control dims and ignores input.
Customization
- Reads
--kb-bg,--kb-fg,--kb-border,--kb-ring(focus ring, 25 % alpha),--kb-error(invalid border),--kb-muted-fg(placeholder),--kb-radius. classNameoverrides resolve by utility:className="h-12 text-base"replacesmin-h-10 text-[15px];className="rounded-none"replacesrounded-kb.- CSS hook:
[data-kibble] [data-kb="input"], plus[aria-invalid="true"]for the error state. classNames={{ input: '…' }}onFormorKibbleProviderstyles Input, Textarea, Select and DatePicker together; they share one set of control classes.
Accessibility
Labelled by its Label through htmlFor; help and error text are in aria-describedby; aria-required and aria-invalid reflect state; inputMode gives phones the right keyboard for number fields. Enter submits (or advances a multi-step form).
Related
Field, Textarea, Label, Help, FieldError, Schema: field types