Mosmox UI
Current version
GitHubnpmjs.com
Forms & Inputs

Input

Text-entry control with validation, icons, read-only states, and character limits

The Input component is a text-entry control for forms, search fields, settings, and other places where a user enters or reviews a single-line value. It wraps a native <input> while adding a consistent label, description, validation message, icon slots, loading and disabled states, clear actions, visual variants, and character-limit feedback.

The component preserves native input behavior and forwards native input attributes, so browser features such as type, name, autoComplete, placeholder, required, readOnly, maxLength, and form participation work as expected.

Installation

Import Input from the UI package. Use icons from @mosmox-ui/icons for consistent framework visuals.

import { MagnifyingGlass as Search } from '@mosmox-ui/icons';
import { Input } from '@mosmox/ui';

Basic usage

<Input label="Project name" placeholder="Enter a project name" />

Use required when the field must contain a value. The component adds an asterisk to the label and forwards the native required attribute to the input.

<Input label="Email address" type="email" required placeholder="[email protected]" />

Content and value management

The component supports both uncontrolled and controlled input patterns.

Use defaultValue when the component should manage its own value:

<Input label="Workspace" defaultValue="Design system" />

Use value and onChange when the parent owns the value:

const [query, setQuery] = useState('');

<Input
  label="Search"
  value={query}
  onChange={(event) => setQuery(event.target.value)}
  placeholder="Search projects"
/>

onChange receives the native React change event. Native attributes such as id, name, type, autoComplete, inputMode, pattern, form, and tabIndex are forwarded to the underlying input.

Labels and field messaging

label renders an associated <label> and is connected to the input through its generated or supplied id. description adds supporting text below the label. error renders an error message and changes the field border and focus colors to the danger token.

<Input
  label="Username"
  description="Use 3–24 characters."
  error="This username is already in use."
  value="maria"
  onChange={() => {}}
/>

The component combines the description and error element IDs in aria-describedby, so assistive technology can read the available field guidance.

Variants

The variant property controls the field surface treatment.

<Input label="Outline" variant="outline" placeholder="Outline field" />
<Input label="Filled" variant="filled" placeholder="Filled field" />
  • outline is the default and displays a bordered surface.
  • filled uses the control-filled background token and removes the visible border.

Sizes

The size property controls minimum height, padding, and input typography.

<Input label="Default" size="default" placeholder="Default size" />
<Input label="Small" size="sm" placeholder="Small size" />
<Input label="Extra small" size="xs" placeholder="Extra-small size" />

default is the standard 40px control. sm and xs are intended for compact forms, filters, toolbars, and dense layouts.

Icons and text adornments

Use leadingIcon for an icon before the value and trailingIcon for an icon after it. Use prefix and suffix for text or other non-icon content, such as a currency symbol, unit, or URL fragment. The component reserves consistent dimensions and spacing for all adornments.

import { Calendar, MagnifyingGlass as Search } from '@mosmox-ui/icons';

<Input label="Search" leadingIcon={<Search size={16} />} placeholder="Search" />
<Input label="Start date" trailingIcon={<Calendar size={16} />} placeholder="Select a date" />
<Input label="Price" prefix="$" suffix="USD" placeholder="0.00" />

Icons are visual decorations by default. If an icon conveys information that is not also present in the label or text, provide an accessible explanation through the surrounding field content.

prefix and suffix are visual adornments and are marked as decorative. Use the label or description to communicate their meaning to assistive technology.

Clear action

Set clearable to show a clear button when the field contains a value. onClear runs when the user activates that button.

const [search, setSearch] = useState('Roadmap');

<Input
  label="Search"
  value={search}
  onChange={(event) => setSearch(event.target.value)}
  clearable
  onClear={() => setSearch('')}
/>

The clear action is hidden when the value is empty, while the input is disabled or loading, or when the input is read-only. While the clear action is visible, it takes precedence over trailingIcon.

For a controlled input, the parent must update value in onClear:

<Input
  label="Search"
  value={query}
  onChange={(event) => setQuery(event.target.value)}
  clearable
  onClear={() => setQuery('')}
/>

Read-only values

Use the native readOnly attribute when a value should be displayed but not edited. The component shows a lock icon at the trailing edge to make the non-editable state clear.

<Input label="Account ID" value="acct_2048" readOnly />

Read-only fields remain focusable and can be selected or copied. They are different from disabled fields, which are unavailable for interaction and are excluded from normal form submission.

Character limits

Pass maxLength to limit the number of characters accepted by the native input. When maxLength is present, the component automatically renders a counter below the field on the right in the form current / maximum.

<Input
  label="Short description"
  placeholder="Describe the project"
  maxLength={120}
/>

The browser prevents additional input after the limit is reached. The counter updates as the value changes and works with both controlled and uncontrolled inputs.

Loading and disabled states

Use loading while the value or surrounding operation is being resolved. Loading prevents editing and shows a loader. Use disabled when the field is unavailable.

<Input label="Loading value" value="Loading…" loading readOnly />
<Input label="Unavailable" value="Unavailable value" disabled readOnly />

loading and disabled are forwarded to the native input as non-editable states. The visual treatment uses the component's disabled opacity and cursor styles.

Full width

Set fullWidth when the field should fill its parent container.

<Input fullWidth label="Full-width field" placeholder="Uses the available width" />

The field has a minimum width of 100px so it remains usable in compact layouts. Use fullWidth when the input should fit the available width of a narrow parent, such as a compact dialog or grid column.

Validation states

Pass an error string when validation fails. The presence of a non-empty error activates the error border and error focus treatment.

<Input
  label="Password"
  type="password"
  error="Password must contain at least 12 characters."
/>

For custom validation logic, keep the validation state in the parent and pass the current message to error.

Accessibility

The component keeps native input semantics and connects the field content for assistive technology:

  • label is associated with the input through htmlFor and id;
  • description and error are referenced through aria-describedby;
  • error sets aria-invalid unless an explicit aria-invalid value is provided;
  • required is forwarded to the native input;
  • readOnly uses the native read-only behavior and adds a visual lock cue;
  • the character counter uses a polite live region so updates can be announced without interrupting the user;
  • loading and disabled fields cannot be edited;
  • native keyboard, focus, selection, form, and browser validation behavior is preserved.

Do not rely on placeholder text as the only field label. Use label for the field name and description for supporting instructions.

Styling model

Input styling is split between shared theme tokens and component behavior. Shared values such as colors, typography, radius, spacing, icon size, and control gaps come from the theme token layer. Input-specific layout and state rules remain in Input.css.

Global theme values can be customized with ConfigProvider:

import { ConfigProvider, Input } from '@mosmox/ui';

<ConfigProvider
  theme={{
    colors: {
      controlBorder: '#C7D2FE',
      controlFilled: '#F8FAFC',
      controlIcon: '#667085',
      dangerText: '#B42318',
      placeholder: '#98A2B3',
    },
    radius: '6px',
    typography: { fontWeightMedium: 500 },
  }}
>
  <Input label="Themed input" placeholder="Uses shared tokens" />
</ConfigProvider>

API Reference

Input-specific properties

PropertyTypeDefaultDescription
labelstring—Associated field label.
descriptionstring—Supporting text displayed below the label.
errorstring—Validation message; also activates the invalid visual state.
variantInputVariantoutlineoutline or filled.
sizeInputSizedefaultdefault, sm, or xs.
leadingIconReactNode—Content rendered before the input value.
trailingIconReactNode—Content rendered after the input value. Hidden while the clear action is visible.
prefixReactNode—Decorative text or content before the input value, such as $ or https://.
suffixReactNode—Decorative text or content after the input value, such as kg or USD.
clearablebooleanfalseShows a clear action when a non-empty value can be edited.
onClear() => void—Called when the clear action is activated.
loadingbooleanfalsePrevents editing and shows a loading indicator.
fullWidthbooleanfalseExpands the field to the available container width.
inputClassNamestring—Additional class name applied to the native input.
classNamestring—Additional class name applied to the field wrapper.

Native input properties

Input accepts the native InputHTMLAttributes<HTMLInputElement> properties except for the native size attribute, which is replaced by the component's visual size property.

PropertyTypeDefaultDescription
value`stringnumberreadonly string[]`
defaultValue`stringnumberreadonly string[]`
onChangeChangeEventHandler<HTMLInputElement>—Called when the value changes.
maxLengthnumber—Maximum number of characters. Enables the current / maximum counter.
readOnlybooleanfalsePrevents editing while keeping the field focusable and selectable.
disabledbooleanfalseDisables interaction with the native input.
requiredbooleanfalseMarks the field as required for native form validation.
typestringtextNative input type such as text, email, password, or search.
placeholderstring—Placeholder shown when the value is empty.
namestring—Form submission name.
idstringgeneratedInput ID used to associate the label and messages.
autoCompletestring—Browser autocomplete hint.
aria-labelstring—Accessible name when a visible label is not used.
aria-describedbystringgeneratedAdditional description IDs; component message IDs are appended.
aria-invalid`boolean'true''false'`

All other supported native input properties and event handlers are forwarded to the underlying <input> element.