Skip to main content
On this pageOverview

Input

Overview

An accessible text input that links a label and description to the input element via ARIA attributes. Input is a view-only component with no Model or update function. It provides three attribute groups — input, label, and description — that you spread onto your own elements to get correct accessibility wiring.

See it in an app

Check out how Input is wired up in a real Foldkit app.

Examples

Basic

Pass an id, an onInput handler, and a toView callback. The callback receives attribute groups for three elements: label (linked via for), input (with ARIA attributes), and description (linked via aria-describedby).

As it appears on your government-issued ID.
// Pseudocode — Input is view-only. The value lives in your own Model as a
// string. Replace model.name and UpdatedName with your own field and Message.
import { Ui } from 'foldkit'

import { Class, div, input, label, span } from './html'

Ui.Input.view({
  id: 'full-name',
  value: model.name, // your Model field
  onInput: value => UpdatedName({ value }), // your Message
  placeholder: 'Enter your full name',
  toView: attributes =>
    div(
      [Class('flex flex-col gap-1.5')],
      [
        label([...attributes.label, Class('text-sm font-medium')], ['Name']),
        input([
          ...attributes.input,
          Class('w-full rounded-lg border border-gray-300 px-3 py-2'),
        ]),
        span(
          [...attributes.description, Class('text-sm text-gray-500')],
          ['As it appears on your government-issued ID.'],
        ),
      ],
    ),
})

Disabled

Set isDisabled: true to disable the input. Unlike Button, Input uses the native disabled attribute in addition to aria-disabled, so the browser prevents interaction entirely.

This input is disabled.
// Pseudocode — Input is view-only. Disabled inputs display a fixed value
// and ignore onInput events.
import { Ui } from 'foldkit'

import { Class, input, label, span } from './html'

Ui.Input.view({
  id: 'email-disabled',
  isDisabled: true,
  value: 'ada@lovelace.dev',
  toView: attributes =>
    div(
      [Class('flex flex-col gap-1.5')],
      [
        label([...attributes.label, Class('text-sm font-medium')], ['Email']),
        input([
          ...attributes.input,
          Class(
            'w-full rounded-lg border px-3 py-2 data-[disabled]:opacity-50',
          ),
        ]),
        span(
          [...attributes.description, Class('text-sm text-gray-500')],
          ['Contact your admin to update.'],
        ),
      ],
    ),
})

Styling

Input is headless — your toView callback controls all markup and styling. Use the data attributes below to style different states. For validation, set isInvalid: true and style with data-[invalid] in your CSS.

AttributeCondition
data-disabledPresent when isDisabled is true.
data-invalidPresent when isInvalid is true.

Keyboard Interaction

Input uses the native <input> element, so all keyboard interaction is handled by the browser.

KeyDescription
TabMoves focus to or away from the input.

Accessibility

The three attribute groups wire up ARIA relationships automatically. The label group includes for pointing to the input id. The description group includes an id that the input references via aria-describedby. You can access this description ID directly with Input.descriptionId(id) if you need to reference it outside the toView callback.

When isInvalid is true, aria-invalid="true" is set on the input element so screen readers announce the error state.

API Reference

ViewConfig

Configuration object passed to Input.view().

NameTypeDefaultDescription
idstring-Unique ID for the input element. Used to link the label and description via ARIA attributes.
toView(attributes: InputAttributes) => Html-Callback that receives attribute groups for the input, label, and description elements.
onInput(value: string) => Message-Function that maps the current input value to a Message on each input event.
valuestring-The current value of the input.
isDisabledbooleanfalseWhether the input is disabled. Sets both the native disabled attribute and aria-disabled.
isInvalidbooleanfalseWhether the input is in an invalid state. Sets aria-invalid and adds a data-invalid attribute for styling.
isAutofocusbooleanfalseWhether the input receives focus when the page loads.
namestring-The form field name for native form submission.
typestring'text'The HTML input type (text, email, password, number, etc.).
placeholderstring-Placeholder text shown when the input is empty.

InputAttributes

Attribute groups provided to the toView callback.

NameTypeDefaultDescription
inputReadonlyArray<Attribute<Message>>-Spread onto the <input> element. Includes id, type, value, ARIA attributes, and event handlers.
labelReadonlyArray<Attribute<Message>>-Spread onto the <label> element. Includes a for attribute linking to the input id.
descriptionReadonlyArray<Attribute<Message>>-Spread onto a description element. Includes an id that the input references via aria-describedby.

Stay in the update loop.

New releases, patterns, and the occasional deep dive.


Built with Foldkit.

© 2026 Devin Jameson