Default
import { PixelInput } from '@pxlkit/ui-kit';
export function Default() {
return (
<PixelInput
label="Username"
placeholder="hero@pxlkit.xyz"
hint="Your retro alias"
/>
);
}Single-line text input with label, hint, error message, tone/size/surface variants, prefix/suffix slots, joinable addons, clearable button, char counter, and loading state.
value + onChange (React), v-model (Vue), [(value)] or forms (Angular) — or uncontrolled with defaultValue.prefix/suffix slots plus outside-shell addonLeft/addonRight for joined groups.clearable × button, loading spinner, and showCount character counter.tone, size, and surface follow the kit-wide design tokens.aria-invalid + aria-describedby with hint/error text.import { PixelInput } from '@pxlkit/ui-kit';| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | Floating label rendered above the input shell. |
hint | string | — | Helper text shown below the field. Hidden when error is set. |
error | string | — | Error message shown below the field; flips visual state to invalid. |
tone | 'green' | 'cyan' | 'gold' | 'red' | 'purple' | 'pink' | 'neutral' | 'neutral' | Visual tone for focus ring + border emphasis. Default: 'neutral'. |
size | 'sm' | 'md' | 'lg' | 'md' | Field height token. Default: 'md'. |
surface | 'pixel' | 'linear' | — | Surface variant. Inherits from PxlKitSurfaceProvider when omitted. |
icon | React.ReactNode | — | Legacy left-icon slot, rendered inside the input shell. Equivalent to prefix. |
prefix | React.ReactNode | — | Content rendered INSIDE the input shell on the left (icon or short text). |
suffix | React.ReactNode | — | Content rendered INSIDE the input shell on the right (icon or short text). |
addonLeft | React.ReactNode | — | Element rendered OUTSIDE the input shell and joined to its left edge (e.g. button/select). |
addonRight | React.ReactNode | — | Element rendered OUTSIDE the input shell and joined to its right edge. |
clearable | boolean | — | When true, shows a clear (×) button while the value is non-empty. |
onClear | () => void | — | Callback fired when the clear button is clicked. |
showCount | boolean | { max?: number } | — | Render a character counter under the input. true shows N; { max } shows N/max. |
loading | boolean | — | When true, replaces the suffix with a spinner and disables the input. |
Also takes the native attributes and event handlers of <input> (InputHTMLAttributes<HTMLInputElement>).
ref points to <input>.
WCAG target: 2.1 AA
textboxSets aria-invalid when error is provided and links the hint/error text it shows via aria-describedby, after any ids you pass (none while neither shows). The clear button has tabindex="-1" so keyboard users edit the value directly instead of tabbing through it.
| Key | Action | When |
|---|---|---|
| Tab | Move focus into / out of the input. | — |
| Enter | Submit the surrounding form (native browser behavior). | — |
import { PixelInput } from '@pxlkit/ui-kit';
export function Default() {
return (
<PixelInput
label="Username"
placeholder="hero@pxlkit.xyz"
hint="Your retro alias"
/>
);
}import { PixelInput } from '@pxlkit/ui-kit';
export function Default() {
return (
<PixelInput
label="Username"
placeholder="hero@pxlkit.xyz"
hint="Your retro alias"
/>
);
}import { useState } from 'react';
import { PixelInput } from '@pxlkit/ui-kit';
export function Controlled() {
const [value, setValue] = useState('');
return (
<PixelInput
label="Email"
type="email"
placeholder="hero@pxlkit.xyz"
value={value}
onChange={(e) => setValue(e.target.value)}
tone="cyan"
/>
);
}import { PixelInput } from '@pxlkit/ui-kit';
export function Uncontrolled() {
return (
<PixelInput
label="Display name"
defaultValue="Pixel Hero"
hint="Edit me — uncontrolled"
/>
);
}import { PixelInput } from '@pxlkit/ui-kit';
export function Tones() {
return (
<div className="flex flex-col gap-3">
<PixelInput label="Neutral" tone="neutral" defaultValue="neutral" />
<PixelInput label="Cyan" tone="cyan" defaultValue="cyan" />
<PixelInput label="Green" tone="green" defaultValue="green" />
<PixelInput label="Gold" tone="gold" defaultValue="gold" />
<PixelInput label="Purple" tone="purple" defaultValue="purple" />
<PixelInput label="Pink" tone="pink" defaultValue="pink" />
</div>
);
}import { PixelInput } from '@pxlkit/ui-kit';
export function Sizes() {
return (
<div className="flex flex-col gap-3">
<PixelInput label="Small" size="sm" placeholder="sm" />
<PixelInput label="Medium" size="md" placeholder="md" />
<PixelInput label="Large" size="lg" placeholder="lg" />
</div>
);
}import { PixelInput } from '@pxlkit/ui-kit';
export function Surfaces() {
return (
<div className="flex flex-col gap-3">
<PixelInput label="Pixel" surface="pixel" placeholder="pixel surface" />
<PixelInput label="Linear" surface="linear" placeholder="linear surface" />
</div>
);
}import { PixelInput } from '@pxlkit/ui-kit';
export function WithPrefixSuffix() {
return (
<div className="flex flex-col gap-3">
<PixelInput
label="Amount"
prefix={<span className="text-xs">$</span>}
suffix={<span className="text-xs">USD</span>}
defaultValue="42"
/>
<PixelInput
label="Search"
prefix={<span aria-hidden>?</span>}
placeholder="Find anything"
/>
</div>
);
}import { PixelInput } from '@pxlkit/ui-kit';
export function WithAddons() {
return (
<PixelInput
label="Website"
addonLeft={<span className="text-xs">https://</span>}
addonRight={<span className="text-xs">.xyz</span>}
defaultValue="pxlkit"
/>
);
}import { useState } from 'react';
import { PixelInput } from '@pxlkit/ui-kit';
export function Clearable() {
const [value, setValue] = useState('clear me');
return (
<PixelInput
label="Clearable"
clearable
value={value}
onChange={(e) => setValue(e.target.value)}
onClear={() => setValue('')}
/>
);
}import { PixelInput } from '@pxlkit/ui-kit';
export function Loading() {
return (
<PixelInput
label="Verifying handle"
defaultValue="pxlhero"
loading
/>
);
}import { PixelInput } from '@pxlkit/ui-kit';
export function Disabled() {
return (
<PixelInput
label="Disabled"
defaultValue="cannot edit"
disabled
/>
);
}import { PixelInput } from '@pxlkit/ui-kit';
export function WithError() {
return (
<PixelInput
label="Email"
defaultValue="not-an-email"
error="Please enter a valid email address"
tone="red"
/>
);
}import { useState } from 'react';
import { PixelInput } from '@pxlkit/ui-kit';
export function WithCharCount() {
const [value, setValue] = useState('Hello');
return (
<PixelInput
label="Bio"
value={value}
onChange={(e) => setValue(e.target.value)}
showCount={{ max: 80 }}
hint="Keep it short"
/>
);
}