Skip to main content
In progress

TextInput

A TextInput is a single-line field that allows users to enter short, structured information such as names, email addresses or titles.

Code example
import { TextInput } from '@yleisradio/yds-components-react';

<TextInput label="Label" placeholder="Placeholder"/>

Why to use

TextInput allows users to enter short, structured information quickly and accurately. It supports validation, helper text, and clear feedback, helping users understand what is expected and complete tasks efficiently. Use TextInput whenever a concise textual value is required as part of a form, dialog, or inline interaction.

When to use

Use TextInput when users need to enter short, single-line information that benefits from clarity, validation, or guidance.

Do
  • Use TextInput for short, single-line input (e.g., “Etunimi”, “Sähköposti”).
  • Use it when input follows clear rules or formats.
  • Use it in forms, dialogs, inline edits, and search fields.
  • Use it when the value fits naturally on one line and should be easy to scan.
Don’t
  • Don’t use TextInput for multi-line input — use TextArea.
  • Don’t use it for choosing from predefined options — use Select or Combobox.
  • Don’t use it for long or unstructured free-form text.
  • Don’t use it when input purpose is unclear or hidden.

Content Guidelines

TextInput content should clearly communicate what information is required and how to provide it, without unnecessary cognitive effort.

Do
  • Use short, descriptive labels (e.g., “Sähköposti”, “Otsikko”).
  • Use placeholder text only as an example, not as instructions.
  • Add concise helper text for extra context (esim. “3–16 merkkiä”).
  • Write specific error messages that explain how to fix the problem. (e.g.,“Syötä voimassa oleva sähköpostiosoite”).
  • Keep terminology and phrasing consistent across similar fields.
Don’t
  • Don’t use placeholder text instead of a label.
  • Don’t repeat the label text inside the placeholder.
  • Don’t use vague or generic labels (e.g., “Teksti”, “Arvo”).
  • Don’t include long explanations in labels or descriptions.
  • Don’t rely on placeholder text alone — it disappears when typing starts.

Anatomy

TextInput anatomy

  1. Label – Describes the purpose of the field.
  2. Start icon – Decorative or contextual symbol.
  3. Description – Provides additional guidance below the field.
  4. Placeholder – Example or hint text inside the field.
  5. Input field – Area where users enter text.
  6. End icon – Decorative or functional symbol, e.g., visibility toggle.
  7. Optional field indicator – Shows that the field is not required to fill.

Key Props

Use the following props to customize the TextInput component to fit your needs.

type

Supported HTML input types. Invalid values fall back to text.

ValueExampleDescription
text
Generic free-form text.
email
Email address pattern (may trigger native validation/UI).
password
Obscures characters for secrets.
number
Numeric value (spinner / numeric keyboard).
tel
Telephone number (phone keypad on mobile).
search
Search field styling (enables native clear in some browsers).
Code example
<TextInput label="Email" id="email" type="email" placeholder="name@example.com" />
<TextInput label="Password" id="pwd" type="password" />
<TextInput label="Search" id="search" type="search" placeholder="Search" />

label

info

Label can be visually hidden but must remain readable for screen readers.

TypeExampleDescription
string
Provides a clear purpose for the field.
Code example
<TextInput label="Username" id="username" />

description

Helper guidance placed below the field.

TypeExampleDescription
string

3–16 characters

Provides additional guidance below the field.
Code example
<TextInput label="Username" id="username" description="3–16 characters" placeholder="Enter username" />

success

TypeExampleDescription
boolean
Indicates successful validation.
Code example
<TextInput label="Email" id="email-input" type="email" success />

errorMessage

TypeExampleDescription
string
Displays a validation error below the field. Sets aria-invalid.
Code example
<TextInput label="Email" id="email-error" type="email" errorMessage="Invalid email" />

isDisabled

Non-interactive, dimmed styling.

TypeExampleDescription
boolean
Temporarily prevents user interaction.
Code example
<TextInput label="Disabled input" id="disabled-input" isDisabled />

isRequired

TypeExampleDescription
boolean
Marks field mandatory for submission.
Code example
<TextInput label="First name" id="name" isRequired />

showLoadingIndicator

Shows a spinner inside the input (left side) while async work occurs (e.g. validating, fetching suggestions).

TypeExampleDescription
boolean
Renders spinner and adjusts padding.
Code example
<TextInput label="Search" id="search-loading" showLoadingIndicator value="Searching" />

Icons

Decorative or actionable icons. Provide meaningful ariaLabel for interactive ones.

PropsExampleDescription
iconBefore
Static or clickable icon before text.
icon
Static or clickable icon after text.
Code example
import { Eye, Search } from '@yleisradio/yds-icons-react';

<TextInput
label="Search"
id="search-x"
type="search"
iconBefore={{ componentFn: Search, ariaLabel: 'Search icon' }}
/>

<TextInput
label="Password"
id="pwd"
type="password"
icon={{ componentFn: Eye, ariaLabel: 'Toggle password visibility', onClick: () => {} }}
/>

autocomplete

Pass through native browser autocomplete hint (e.g. email, username, current-password).

PropExampleDescription
autocomplete
Helps browsers suggest stored values / show suitable keyboard.
Code example
<TextInput label="Email" id="email-ac" type="email" autocomplete="email" />

See MDN Autocomplete attribute for all possible values.

Behavior

  • The label is always associated with the input and appears above it.
  • The input shows a visible focus state when focused.
  • Validation feedback is shown using success or error states.
  • Error messages appear below the input and describe how to resolve the issue.
  • Disabled inputs remain visible but cannot be edited.
  • Placeholder text disappears once the user starts typing.
  • Icons may be decorative or interactive; interactive icons must be operable and accessible.
  • Supports both controlled and uncontrolled usage.

Accessibility

  • Every TextInput must have a visible or programmatically associated label.
  • Interactive icons (such as password visibility toggles) must include a descriptive aria-label.
    (WCAG 3.3.2 — Labels or Instructions)
  • Ensure full keyboard accessibility — users should be able to navigate using Tab, Shift+Tab, and activate controls with Enter.
    (WCAG 2.1.1 — Keyboard)

Implementation examples

Phone number

How to use placeholder, description and optional label in TextInput.

Enter phone number in international format

Code example
import { TextInput } from '@yleisradio/yds-components-react';
<TextInput label="Phone number" labelOptions={{ optionalLabel: '(Optional)' }} placeholder="+358" description="Enter phone number in international format" type="tel" />

With error

Error state provides a clear indication that went wrong and error message tells how to fix it.

Code example
import { TextInput } from '@yleisradio/yds-components-react';
<TextInput label="Email" value="Invalid value" type="email" errorMessage="Please enter a valid email address" />

API Reference

Props

The TextInput component accepts all standard HTML <input> attributes in addition to the following props:

PropTypeRequiredDefaultDescription
labelstringYes
labelOptionsFormElementLabelPropsNo{}
idstringNo
valuestringNo
onChangeReact.ChangeEventHandler<HTMLInputElement>No
placeholderstringNo
descriptionstringNo
errorMessagestringNo
autocompletestringNo
type'text' | 'email' | 'password' | 'number' | 'tel' | 'search'No'text'
successbooleanNofalse
isRequiredbooleanNofalse
isDisabledbooleanNofalse
childrenReactNodeNo
iconInputIconPropsNo
submitButtonReactNodeNo
iconBeforeInputIconPropsNo
iconClearInputIconPropsNo
showLoadingIndicatorbooleanNofalse

Type Definitions

export type InputIconProps = {
componentFn: (props: SVGProps<SVGSVGElement>) => JSX.Element;
ariaLabel: string;
onClick?: () => void;
props?: ButtonHTMLAttributes<HTMLButtonElement>;
};

export type TextInputDSProps = {
label: string;
labelOptions?: FormElementLabelProps;
id?: string;
value?: string;
onChange?: React.ChangeEventHandler<HTMLInputElement>;
placeholder?: string;
description?: string;
errorMessage?: string;
autocomplete?: string;
type?: 'text' | 'email' | 'password' | 'number' | 'tel' | 'search';
success?: boolean;
isRequired?: boolean;
isDisabled?: boolean;
children?: ReactNode;
icon?: InputIconProps;
submitButton?: ReactNode;
iconBefore?: InputIconProps;
iconClear?: InputIconProps;
showLoadingIndicator?: boolean;
};

export type TextInputProps = InputHTMLAttributes<HTMLInputElement> & TextInputDSProps;