Skip to content
Nana UI

Forms & Inputs

Input

A text input with label, helper text, validation, prefix/suffix and clear support.

View .md Download

The input ships for all three targets. Pick the tab for your project — the CLI detects which you are on and serves the matching implementation.

npx @nana-tec/ui add input

Lands as src/components/ui/input/input.tsx, styled with Tailwind classes that resolve to the design tokens. Requires Tailwind v4.

import { Input } from "@/components/ui/input";
export function Example() {
const [email, setEmail] = useState("");
return (
<Input
label="Email"
type="email"
required
value={email}
onChange={(event) => setEmail(event.target.value)}
helperText="We never share it."
/>
);
}

errorMessage replaces helperText and wires up aria-invalid and aria-describedby. prefix and suffix take nodes for icons or units. The label is associated automatically — pass your own id to override the generated one.

Classes you pass to the React and Svelte components are merged with tailwind-merge, so an override wins rather than fighting. See Using Tailwind.

Slot an icon (or any content) into the prefix / suffix slots.

The React and Svelte props, read from the components’ own types:

Input

PropTypeDefault
sizeInputSize'md'
labelReactNode
helperTextReactNode
errorMessageReactNode
prefixReactNode
suffixReactNode

Also accepts Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix'>.

The attribute names, events and CSS hooks below are the Web Components reference.

Properties

PropertyAttributeTypeDefaultDescription
autocompleteautocompleteHTMLInputElement['autocomplete']'off'
clearableclearablebooleanfalse
disableddisabledbooleanfalse
errorMessageerror-messagestring''
helperTexthelper-textstring''
inputIdinputId——
inputModeinputmodestring''Which virtual keyboard to raise on touch devices. Distinct from type: type="text" inputmode="decimal" keeps free-form input while still opening a numeric pad, which is what amount and phone fields want. inputMode is also a global HTMLElement property, so this deliberately overrides it: on the host it is inert (the host is not editable), and the value only does anything once forwarded to the inner <input> below.
invalidinvalidbooleanfalse
labellabelstring''
loadingloadingbooleanfalse
maxmaxstring | undefined—Upper bound for type="number" / type="date" and friends.
maxlengthmaxlengthnumber | undefined—
minminstring | undefined—Lower bound for type="number" / type="date" and friends.
minlengthminlengthnumber | undefined—
namenamestring''
patternpatternstring | undefined—Regular expression the value must match, per native constraint validation.
placeholderplaceholderstring''
readonlyreadonlybooleanfalse
requiredrequiredbooleanfalse
sizesize'xs' | 'sm' | 'md' | 'lg''md'
stepstepstring | undefined—Granularity of the accepted value; any disables stepping.
typetypeHTMLInputElement['type']'text'
valuevaluestring''

Events

EventDescription
nana-inputFired on every keystroke (detail.value)
nana-changeFired when the value is committed (detail.value)
nana-clearFired when the clear button or Escape empties the field
nana-focusFired when the field gains focus
nana-blurFired when the field loses focus

Slots

SlotDescription
prefixContent before the field, in a fixed-width zone
suffixContent after the field, in a fixed-width zone

CSS parts

PartDescription
::part(wrapper)The bordered field container
::part(input)The native <input> element

CSS custom properties

PropertyDescription
--nana-input-bgField background colour
--nana-input-colorInput text colour
--nana-input-radiusField corner radius
--nana-input-heightField height (defaults to the size preset)
--nana-input-affix-insetGap from the border to a slotted prefix/suffix
--nana-input-affix-gapGap between a slotted prefix/suffix and the text
--nana-input-affix-zoneReserved width for a slotted prefix/suffix
--nana-input-affix-icon-sizeSize applied to a slotted icon, svg or img
VariableDescription
--nana-input-bgField background colour
--nana-input-colorInput text colour
--nana-input-radiusField corner radius
PartDescription
wrapperThe bordered field container
inputThe native <input> element
  • Keyboard accessible
  • Screen-reader labels
  • Focus-visible states
  • ARIA roles and states
  • WCAG 2.2 AA contrast
Explore Input interactively Every state, prop, and edge case — with live controls — in Storybook.
View in Storybook