We'll never share your email

import { Input } from "@photon-ai/kumo-solid";

export function InputBasicDemo() {
  return (
    <Input
      label="Email"
      placeholder="you@example.com"
      description="We'll never share your email"
    />
  );
}

Installation

Barrel

import { Input } from "@photon-ai/kumo-solid";

Granular

import { Input } from "@photon-ai/kumo-solid/components/input";

Usage

Use the label prop to enable the built-in Field wrapper with label, description, and error support.

import { Input } from "@photon-ai/kumo-solid";

export default function Example() {
  return (
    <Input
      label="Email"
      placeholder="you@example.com"
      description="We'll never share your email"
    />
  );
}

Bare Input (Custom Layouts)

For custom form layouts, use Input without label. Must provide aria-label or aria-labelledby for accessibility.

import { Input } from "@photon-ai/kumo-solid";

export default function Example() {
  return <Input placeholder="Search..." aria-label="Search products" />;
}

Examples

With Label and Description

The label prop enables the built-in Field wrapper with automatic vertical layout (label above input).

3-20 characters, alphanumeric only

import { Input } from "@photon-ai/kumo-solid";

export function InputWithLabelDemo() {
  return (
    <Input
      label="Username"
      placeholder="Choose a username"
      description="3-20 characters, alphanumeric only"
    />
  );
}

With Error (String)

Pass error as a string for simple error messages. Error styling is automatically applied when the error prop is truthy.

Please enter a valid email address
import { Input } from "@photon-ai/kumo-solid";

export function InputErrorStringDemo() {
  return (
    <Input
      label="Email"
      placeholder="you@example.com"
      value="invalid-email"
      error="Please enter a valid email address"
    />
  );
}

With Error (Validation Object)

Pass error as an object with message and match for HTML5 validation. Error shows when field validity matches.

import { Input } from "@photon-ai/kumo-solid";

export function InputErrorObjectDemo() {
  return (
    <Input
      label="Password"
      type="password"
      value="short"
      error={{
        message: "Password must be at least 8 characters",
        match: "tooShort",
      }}
      minLength={8}
    />
  );
}

Input Sizes

Four sizes available: xs, sm, base (default), lg.

import { Input } from "@photon-ai/kumo-solid";

export function InputSizesDemo() {
  return (
    <div class="flex flex-col gap-4">
      <Input size="xs" label="Extra Small" placeholder="Extra small input" />
      <Input size="sm" label="Small" placeholder="Small input" />
      <Input label="Base" placeholder="Base input (default)" />
      <Input size="lg" label="Large" placeholder="Large input" />
    </div>
  );
}

Disabled

import { Input } from "@photon-ai/kumo-solid";

export function InputDisabledDemo() {
  return <Input label="Disabled field" placeholder="Cannot edit" disabled />;
}

Optional Field

Set required={false} to show “(optional)” text after the label.

import { Input } from "@photon-ai/kumo-solid";

export function InputOptionalFieldDemo() {
  return (
    <Input
      label="Phone Number"
      required={false}
      placeholder="+1 (555) 000-0000"
    />
  );
}

With Label Tooltip

Use labelTooltip to add an info icon with additional context on hover.

import { Input } from "@photon-ai/kumo-solid";

export function InputLabelTooltipDemo() {
  return (
    <Input
      label="API Key"
      labelTooltip="Find this in your dashboard under Settings > API Keys"
      placeholder="sk_live_..."
    />
  );
}

Rich Label

The label prop accepts JSX.Element for rich formatting.

import { Input } from "@photon-ai/kumo-solid";

export function InputRichLabelDemo() {
  return (
    <Input
      label={
        <span>
          Email for <strong>billing</strong>
        </span>
      }
      required
      placeholder="billing@company.com"
      type="email"
    />
  );
}

Controlled with onInput

Solid’s native onInput handler receives the input event as the user types. Read e.currentTarget.value to get the current value.

Uses e.currentTarget.value

import { createSignal } from "solid-js";
import { Input } from "@photon-ai/kumo-solid";

/** Controlled input using Solid's native `onInput` event. */
export function InputControlledOnInputDemo() {
  const [value, setValue] = createSignal("");
  return (
    <Input
      label="With onInput"
      placeholder="Type something..."
      description={value() ? `Value: ${value()}` : "Uses e.currentTarget.value"}
      value={value()}
      onInput={(event) => setValue(event.currentTarget.value)}
    />
  );
}

Controlled with onValueChange

onValueChange is a convenience handler from Base UI that gives you the string value directly — no event unwrapping needed. This is the same pattern used by Select, Combobox, and Radio.Group.

Receives the value directly

import { createSignal } from "solid-js";
import { Input } from "@photon-ai/kumo-solid";

/** Controlled input using `onValueChange` (Base UI convenience — gives you the string directly). */
export function InputControlledOnValueChangeDemo() {
  const [value, setValue] = createSignal("");
  return (
    <Input
      label="With onValueChange"
      placeholder="Type something..."
      description={
        value() ? `Value: ${value()}` : "Receives the value directly"
      }
      value={value()}
      onValueChange={(v) => setValue(v)}
    />
  );
}

Bare Input (No Label)

Input without label renders as a bare input. Must provide aria-label for accessibility.

import { Input } from "@photon-ai/kumo-solid";

export function InputBareDemo() {
  return <Input placeholder="Search..." aria-label="Search products" />;
}

Error Without Label

Error messages and descriptions render even without a visible label — use aria-label to keep the input accessible.

Please enter a valid hostname
Path must start with /
import { Input } from "@photon-ai/kumo-solid";

/** Input without a visible label, showing error and description via `aria-label`. */
export function InputErrorWithoutLabelDemo() {
  return (
    <div class="flex flex-col gap-4">
      <Input
        aria-label="Hostname"
        placeholder="example.com"
        value="not a host"
        error="Please enter a valid hostname"
      />
      <Input
        aria-label="Path"
        placeholder="/api/v1/users"
        value="missing-slash"
        error={{ message: "Path must start with /", match: true }}
      />
    </div>
  );
}

Input Types

Supports all HTML input types: text, email, password, number, tel, url, etc.

import { Input } from "@photon-ai/kumo-solid";

export function InputTypesDemo() {
  return (
    <div class="flex flex-col gap-4">
      <Input type="email" label="Email" placeholder="you@example.com" />
      <Input type="password" label="Password" placeholder="••••••••" />
      <Input type="number" label="Age" placeholder="18" />
      <Input type="tel" label="Phone" placeholder="+1 (555) 000-0000" />
    </div>
  );
}

Password Manager Overlays

Set passwordManagerIgnore on non-credential inputs that password managers might incorrectly classify as login fields.

import { Input } from "@photon-ai/kumo-solid";

/** Side-by-side comparison: Keeper shows its icon on the default input but not the ignored one. */
export function InputPasswordManagerIgnoreDemo() {
  return (
    <div class="flex flex-col gap-4">
      <Input
        label="API Key (default)"
        type="password"
        placeholder="sk_live_..."
      />
      <Input
        label="API Key (passwordManagerIgnore)"
        type="password"
        placeholder="sk_live_..."
        passwordManagerIgnore
      />
    </div>
  );
}

API Reference

Input accepts all standard HTML input attributes plus the following:

PropTypeDefaultDescription
labelJSX.Element-Label content for the input (enables Field wrapper) - can be a string or any JSX content
labelTooltipJSX.Element-Tooltip content to display next to the label via an info icon
descriptionJSX.Element-Helper text displayed below the input
errorstring | object-Error message or validation error object
passwordManagerIgnoreboolean-Suppress browser extension password manager overlays on non-credential inputs.
size"xs" | "sm" | "base" | "lg""base"Input size. - `"xs"` — Extra small for compact UIs - `"sm"` — Small for secondary fields - `"base"` — Default size - `"lg"` — Large for prominent fields
variant"default" | "error""default"Visual variant. - `"default"` — Standard input - `"error"` — Error state for validation failures

Validation Error Types

When using error as an object, the match property corresponds to HTML5 ValidityState values:

MatchDescription
valueMissingRequired field is empty
typeMismatchValue doesn’t match type (e.g., invalid email)
patternMismatchValue doesn’t match pattern attribute
tooShortValue shorter than minLength
tooLongValue longer than maxLength
rangeUnderflowValue less than min
rangeOverflowValue greater than max
trueAlways show error (for server-side validation)

Accessibility

Label Requirement

Inputs require an accessible name via one of:

  • label prop (recommended)
  • placeholder + aria-label for bare inputs
  • aria-labelledby for custom label association

Missing accessible names trigger console warnings in development.

Error Association

Error messages are automatically associated with the input via ARIA attributes for screen reader announcement.