PixelBareInput

Unstyled <input> primitive, the native input itself, used as an escape hatch for fully custom field compositions.

  • Native <input> semantics — takes every native input attribute verbatim.
  • Its element is the native <input>, for measurement, focus, or imperative APIs: a ref in React, $el in Vue, the input[pxlBareInput] element in Angular.
  • Zero styling — pair with parent surfaces (PixelInputGroup, PixelFieldset) when building bespoke field widgets.
  • SSR-safe and tree-shakable — no client effects or runtime dependencies.
Status
stable
Category
forms
Since
v1.0.0

API

import { PixelBareInput } from '@pxlkit/ui-kit';

No props of its own.

Also takes the native attributes and event handlers of <input> (InputHTMLAttributes<HTMLInputElement>).

ref points to <input>.

Accessibility

WCAG target: 2.1 AA

  • textbox

Because this primitive is unstyled, callers MUST supply an accessible name via aria-label, aria-labelledby, or an associated <label> element. Visual focus styling is the consumer's responsibility.

Keyboard

KeyActionWhen
TabMoves focus into / out of the input.—
EnterSubmits the surrounding form when present.—

Usage

import { PixelBareInput } from '@pxlkit/ui-kit';

export function Default() {
  return <PixelBareInput placeholder="Type something" />;
}

Examples

Default

import { PixelBareInput } from '@pxlkit/ui-kit';

export function Default() {
  return <PixelBareInput placeholder="Type something" />;
}

Uncontrolled

import { PixelBareInput } from '@pxlkit/ui-kit';

export function Uncontrolled() {
  return <PixelBareInput defaultValue="hello world" aria-label="uncontrolled-input" />;
}

Controlled

import * as React from 'react';
import { PixelBareInput } from '@pxlkit/ui-kit';

export function Controlled() {
  const [value, setValue] = React.useState('');
  return (
    <PixelBareInput
      value={value}
      onChange={(e) => setValue(e.target.value)}
      placeholder="Controlled"
      aria-label="controlled-input"
    />
  );
}

Email

import { PixelBareInput } from '@pxlkit/ui-kit';

export function Email() {
  return <PixelBareInput type="email" placeholder="you@example.com" autoComplete="email" />;
}

Password

import { PixelBareInput } from '@pxlkit/ui-kit';

export function Password() {
  return <PixelBareInput type="password" placeholder="••••••••" autoComplete="current-password" />;
}

Number

import { PixelBareInput } from '@pxlkit/ui-kit';

export function Number() {
  return (
    <PixelBareInput type="number" min={0} max={100} step={1} defaultValue={42} aria-label="number-input" />
  );
}

Disabled

import { PixelBareInput } from '@pxlkit/ui-kit';

export function Disabled() {
  return <PixelBareInput defaultValue="not editable" disabled aria-label="disabled-input" />;
}

Read-only

import { PixelBareInput } from '@pxlkit/ui-kit';

export function ReadOnly() {
  return <PixelBareInput defaultValue="read only" readOnly aria-label="readonly-input" />;
}

Required

import { PixelBareInput } from '@pxlkit/ui-kit';

export function Required() {
  return <PixelBareInput required placeholder="required field" aria-label="required-input" />;
}

With ref

import * as React from 'react';
import { PixelButton, PixelBareInput } from '@pxlkit/ui-kit';

export function WithRef() {
  const ref = React.useRef<HTMLInputElement>(null);
  return (
    <div className="flex items-center gap-2">
      <PixelBareInput ref={ref} placeholder="Focus me via ref" />
      <PixelButton size="sm" onClick={() => ref.current?.focus()}>
        Focus
      </PixelButton>
    </div>
  );
}

Related