---
title: Input
description: Inputs capture single-line text, numbers, emails, and other native input types with Radiant focus styles.
---

import { meta as InputMeta, Default, WithInputGroup } from '@/content/stories/input';
import Canvas from '@/components/component-docs/canvas';
import Demo from '@/components/component-docs/demo';

export const config = {
	dependencies: {
		components: [Canvas, Demo],
		scripts: [
			'../../../components/component-docs/demo.script.tsx',
			'../../../components/component-docs/canvas.script.tsx',
			'../../../components/component-docs/controls.script.tsx',
		],
	},
};


# Input

<p class="docs-lede">Inputs capture single-line text, numbers, emails, and other native input types with Radiant sizing and focus styles.</p>

## Try it

<Demo of={Default} meta={InputMeta} />

## Usage

Wrap inputs in `RuiField` for labels and validation. Set `type` and `placeholder` as needed.

```tsx
import { RuiInput } from '@ecopages/radiant-ui/input';
import { RuiField } from '@ecopages/radiant-ui/field';
import { RuiLabel } from '@ecopages/radiant-ui/label';

<RuiField name="email">
  <RuiLabel>Email</RuiLabel>
  <RuiInput type="email" placeholder="you@example.com" />
</RuiField>
```

## Choose the right type

<p>Use `email`, `url`, and `tel` to trigger appropriate mobile keyboards. Use `password` for credential fields.</p>

## Marked for Field discovery

<p>`RuiInput` sets `data-rui-control` so `RuiField` can wire labels, validation, and ARIA. Prefer it over a bare `<input>` inside forms.</p>

## Input masks

<p>Pass a `mask` pattern for structured entry like phone numbers or credit card segments.</p>

## Input groups

<p>Use `RuiInputGroup` to add leading prefixes, trailing icons, or inline buttons around `RuiInput`. See the [Input Group](/docs/forms/input-group) page for the full API.</p>

<Canvas of={WithInputGroup} meta={InputMeta} />

```tsx
import { RuiField } from '@ecopages/radiant-ui/field';
import { RuiInput } from '@ecopages/radiant-ui/input';
import {
  RuiInputGroup,
  RuiInputGroupAddon,
  RuiInputGroupText,
} from '@ecopages/radiant-ui/input-group';
import { RuiLabel } from '@ecopages/radiant-ui/label';

<RuiField name="url">
  <RuiLabel>Website URL</RuiLabel>
  <RuiInputGroup>
    <RuiInputGroupAddon>
      <RuiInputGroupText>https://</RuiInputGroupText>
    </RuiInputGroupAddon>
    <RuiInput placeholder="example.com" />
  </RuiInputGroup>
</RuiField>
```

## Theming

`RuiInput` consumes **semantic surface + status roles**, never Tailwind palette steps:

| State / part | CSS roles |
| --- | --- |
| Base | `border`, `background`, `on-background` |
| Focus | `focus-ring` |
| Invalid (`aria-invalid`) | `error` border |
| Disabled | `opacity-disabled` |

Geometry comes from control tokens: `--size-control-md` height, `--radius-control` corner, `--space-control-x` inline padding, the same tokens `RuiButton` uses, so form rows align. Override colors at the theme layer, not in component CSS.

## Accessibility

- Every input needs a visible label; placeholders are not substitutes.
- Disabled inputs should explain why editing is unavailable.
- Use `type` attributes that match the expected data format.

## API

`RuiInput` is a presentational JSX view over a native `<input>`, no custom element. It sets `data-rui-control` so `RuiField` can wire labels, validation, and ARIA.

### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `string` | | Controlled value. |
| `type` | `string` | `text` | Native input type (`email`, `password`, `tel`, …). |
| `placeholder` | `string` | | Placeholder text. |
| `disabled` | `boolean` | `false` | Disabled state. |
| `name` | `string` | | Form field name. |
| `id` | `string` | | Input id (auto-wired by `RuiField`). |
| `aria-label` | `string` | | Accessible name when there is no visible label. |
| `mask` | `string` | | [IMask](https://imask.js.org/guide.html#masked-pattern) pattern; `0` digit, `a` letter, `*` any char, `{text}` fixed. |
| `on:input` / `on:change` / `on:blur` | `(e: Event) => void` | | Event handlers. |
| Native `<input>` attributes | | | `required`, `autocomplete`, `pattern`, `min`, `max`, `readonly`, and other unprefixed native attributes type-check and render, except `mask` (peeled) and `inputmode` (the view sets `numeric` when `mask` is set, and omits it otherwise). |

### CSS classes

Public classes on the rendered element (documented via `@cssclass`):

| Class | Description |
| --- | --- |
| `.rui-input` | Input root; control-height, rounded, bordered surface. |

### Theme roles

| Part | CSS variables consumed |
| --- | --- |
| Base | `--border`, `--background`, `--on-background` |
| Focus ring | `--focus-ring` |
| Invalid | `--error` |
| Geometry | `--size-control-md`, `--radius-control`, `--space-control-x` |
