Input
A versatile Input component that provides form-friendly input fields with integrated labels, error handling, and optional left/right sections. Built with accessibility and customization in mind.
Props
| Name | Type | Default | Description |
|---|---|---|---|
label | string | — | Label text displayed above the input. |
errors | `string[] | string | ReactNode` |
required | boolean | false | Shows a required indicator (asterisk) next to the label. |
leftSection | ReactNode | — | Content displayed on the left side inside the input. |
rightSection | ReactNode | — | Content displayed on the right side inside the input. |
labelProps | ComponentPropsWithoutRef<"label"> | — | Props passed to the label element. |
labelPosition | `“x" | "y”` | "y" |
...rest | ComponentPropsWithoutRef<"input"> | — | Any native <input> props are forwarded. |
Note The component automatically applies number pattern validation for type="number" inputs.
Usage
Basic Input
The most basic usage includes a label and placeholder.
import { Input } from "@kousta-ui/components";export default function Example() {return <Input label="Email" placeholder="you@example.com" type="email" />;}
Input with Errors
Pass an array of strings to the errors prop to display validation messages. The component will automatically apply error styling.
import { Input } from "@kousta-ui/components";export default function Example() {return (<Inputlabel="Email"placeholder="you@example.com"defaultValue="not-an-email"errors={["Please enter a valid email"]}/>);}
Input with Sections (Prefix/Suffix)
Use leftSection and rightSection to add prefixes, suffixes, icons, or buttons inside the input.
import { Input } from "@kousta-ui/components";export default function Example() {return (<Inputlabel="Amount"placeholder="0.00"type="number"leftSection={<span style={{ padding: "0 8px", opacity: 0.7 }}>$</span>}rightSection={<span style={{ padding: "0 8px", opacity: 0.7 }}>USD</span>}/>);}
Password Input with Show/Hide
You can use the rightSection to create a toggle for password visibility.
import React, { useState } from "react";import { Input } from "@kousta-ui/components";export default function Example() {const [visible, setVisible] = useState(false);return (<Inputlabel="Password"placeholder="Enter password"type={visible ? "text" : "password"}rightSection={<buttontype="button"onClick={() => setVisible((v) => !v)}style={{border: "none",background: "transparent",cursor: "pointer",padding: "0 8px",}}aria-label={visible ? "Hide password" : "Show password"}>{visible ? "🙈" : "👁️"}</button>}required/>);}
Horizontal Label Layout
Set labelPosition="x" to align the label and input horizontally. You may need to provide a minWidth to the label via labelProps for alignment.
import { Input } from "@kousta-ui/components";export default function Example() {return (<Inputlabel="Username"placeholder="john_doe"labelPosition="x"labelProps={{ style: { minWidth: 100 } }}/>);}
Disabled Input
Pass the native disabled prop to disable interaction and apply disabled styles.
import { Input } from "@kousta-ui/components";export default function Example() {return (<Inputlabel="Read-only Field"placeholder="Cannot edit"disableddefaultValue="Some read-only value"/>);}
Accessibility
- Semantics: Renders a proper
<label>element linked to the input viahtmlFor. - Error states: Errors are announced to screen readers via the
data-errorattribute. - Required fields: Visual indicator (asterisk) and semantic
requiredattribute. - Keyboard navigation: Full keyboard support inherited from native input.
Tip Always provide descriptive labels and error messages for screen reader users.
Styles & customization
Runtime classes
kui-input-container: The main wrapper for the label, input, and error message.kui-input-inner: The direct wrapper around the input field and its sections.kui-input: The<input>element itself.kui-input-label: The<label>element.kui-input-error-message: The<span>that displays the error message.
Tokens used by the default styles
- Colors:
--kui-neutral-*,--kui-primary-*,--kui-danger-* - Spacing:
--kui-spacing-2xs,--kui-spacing-xs,--kui-spacing-sm - Typography:
--kui-text-base,--kui-text-sm - Rounding:
--kui-rounded
Types (reference)
import { ComponentPropsWithoutRef, ReactNode } from "react";
type LabelPositionBase = "x" | "y";
export type InputProps = ComponentPropsWithoutRef<"input"> & {
label?: string;
labelProps?: ComponentPropsWithoutRef<"label">;
errors?: string[] | string | ReactNode;
required?: boolean;
leftSection?: ReactNode;
rightSection?: ReactNode;
labelPosition?: LabelPositionBase;
};Component Props Provider
You can set default input behavior for a subtree using ComponentPropsProvider. This is especially useful to standardize label layout, icons/sections, or label props.
import { ComponentPropsProvider, Input } from "@kousta-ui/components";
export default function Example() {
return (
<ComponentPropsProvider
input={{
labelPosition: "y",
labelProps: { style: { fontWeight: 600 } },
}}
>
<Input label="Email" placeholder="you@example.com" />
<Input label="Password" type="password" />
</ComponentPropsProvider>
);
}