Available from v1.0.0
TextInput
TextInput is a themed text input component with title, helper text, error handling, icons, and multiple state styles.
Platform availability: iOS 17.0+
When to use:
- Use TextInput when collecting single-line user input such as names, emails, or passwords with support for validation feedback.
- Consider using TextArea for multi-line input, or DatePicker for date selection.
It includes the following features:
- Title label above the text field.
- Helper text label below the text field.
- Error message display with error styling.
- Leading and trailing icon support.
- Password visibility toggle.
- State-based styling (normal, focus, editing, error, disabled, read-only).
- Customizable padding, border, and corner radius.
Import
import BackbaseDesignSystem
Visual reference
Default |
Error |
Password |
Custom Trailing Icon |
|
|
API reference
TextInput
Properties
|
Property |
Type |
Description |
|---|---|---|
|
textField |
UITextField |
The text field component for user input |
|
helperLabel |
UILabel |
The helper label below the text field |
|
errorLabel |
UILabel |
The error label for displaying errors |
|
errorImage |
UIImage? |
The error image displayed in error state |
|
titleLabel |
UILabel |
The title label above the text field |
|
normalStyle |
Style<TextInput>? |
The style for normal state |
|
focusStyle |
Style<TextInput>? |
The style for focused state |
|
editingStyle |
Style<TextInput>? |
The style for editing state |
|
errorStyle |
Style<TextInput>? |
The style for error state |
|
disableStyle |
Style<TextInput>? |
The style for disabled state |
|
readOnlyStyle |
Style<TextInput>? |
The style for read-only state |
|
cornerRadius |
CornerRadiusTypes |
The corner radius of the text input |
|
border |
BorderOptions? |
The border options |
|
leftViewOffset |
CGVector |
The left view offset |
|
rightViewOffset |
CGVector |
The right view offset |
|
textFieldPaddings |
UIEdgeInsets |
The padding inside the text field |
|
showPasswordVisibilityAccessory |
Bool |
The flag to show password visibility toggle |
|
placeholderTextColor |
UIColor |
The placeholder text color |
|
isUserInteractionEnabled |
Bool |
The flag indicating whether the input is enabled |
Initializers
init(frame:accessibilityLabel:)
Initializes a TextInput with an accessibility label.
|
Parameter |
Type |
Description |
|---|---|---|
|
frame |
CGRect |
The frame rectangle. Defaults to .zero |
|
accessibilityLabel |
String? |
The accessibility label for the text field |
Methods
setError(errorMessage:)
Sets the error message and applies error styling.
|
Parameter |
Type |
Description |
|---|---|---|
|
errorMessage |
String |
The error message to display |
clearError()
Clears the error message and restores normal styling.
setReadyOnly(_:)
Sets the read-only state.
|
Parameter |
Type |
Description |
|---|---|---|
|
isReadOnly |
Bool |
Whether the input is read-only |
setTrailingViewImage(_:for:mode:accessibilityLabel:)
Sets the trailing (right) view image.
|
Parameter |
Type |
Description |
|---|---|---|
|
image |
UIImage? |
The image to set |
|
state |
UIControl.State |
The control state |
|
mode |
UITextField.ViewMode |
The view mode. Defaults to .always |
|
accessibilityLabel |
String? |
The accessibility label |
setTrailingViewImage(_:for:mode:accessibilityLabel:trailingButtonAction:)
Sets the trailing view image with an action.
|
Parameter |
Type |
Description |
|---|---|---|
|
image |
UIImage? |
The image to set |
|
state |
UIControl.State |
The control state |
|
mode |
UITextField.ViewMode |
The view mode. Defaults to .always |
|
accessibilityLabel |
String? |
The accessibility label |
|
trailingButtonAction |
(UITextField) -> Void |
The action on tap |
setLeadingViewImage(_:for:mode:accessibilityLabel:)
Sets the leading (left) view image.
|
Parameter |
Type |
Description |
|---|---|---|
|
image |
UIImage? |
The image to set |
|
state |
UIControl.State |
The control state |
|
mode |
UITextField.ViewMode |
The view mode. Defaults to .always |
|
accessibilityLabel |
String? |
The accessibility label |
setPasswordVisibilityButtonAccessibilityLabel(_:)
Sets the accessibility label for the password visibility button.
|
Parameter |
Type |
Description |
|---|---|---|
|
accessibilityLabel |
String |
The accessibility label |
Configuration
|
Property |
Type |
Default |
|---|---|---|
|
cornerRadius |
CornerRadiusTypes |
.none |
|
border |
BorderOptions? |
nil |
|
textFieldPaddings |
UIEdgeInsets |
.zero |
|
showPasswordVisibilityAccessory |
Bool |
false |
cornerRadius
The cornerRadius property controls the corner rounding of the text input container. Valid values include .none, .sm, .md, .lg, and .max().
let textInput = TextInput(accessibilityLabel: "Email")
textInput.cornerRadius = .md
textFieldPaddings
The textFieldPaddings property sets the internal padding of the text field content.
let textInput = TextInput(accessibilityLabel: "Email")
textInput.textFieldPaddings = UIEdgeInsets(
top: DesignSystem.shared.sizer.md,
left: DesignSystem.shared.sizer.sm,
bottom: DesignSystem.shared.sizer.md,
right: DesignSystem.shared.sizer.sm
)
showPasswordVisibilityAccessory
The showPasswordVisibilityAccessory property determines whether a toggle button appears for showing/hiding password text.
let textInput = TextInput(accessibilityLabel: "Password")
textInput.showPasswordVisibilityAccessory = true
Usage
Basic usage
Create a text input with accessibility label:
let textInput = TextInput(accessibilityLabel: "Email address")
textInput.titleLabel.text = "Email"
textInput.textField.placeholder = "Enter your email"
With helper text
Add helper text below the input:
let textInput = TextInput(accessibilityLabel: "Username")
textInput.titleLabel.text = "Username"
textInput.helperLabel.text = "Must be at least 3 characters"
Password input
Create a password input with visibility toggle:
let input = TextInput(accessibilityLabel: "Password")
input.showPasswordVisibilityAccessory = true
input.setPasswordVisibilityButtonAccessibilityLabel("Toggle password visibility")
Custom trailing icon with action
Add a custom trailing icon with tap action:
textInput.setTrailingViewImage(
DesignSystem.Assets.icExpandMore,
for: .normal,
accessibilityLabel: "Show options"
) { textField in
// Handle tap action
}
Custom leading icon
Add a leading icon:
let style: Style<TextInput> = { input in
input.textField.leftView = UIImageView(image: UIImage(systemName: "magnifyingglass")?.withRenderingMode(.alwaysTemplate))
input.textField.leftView?.tintColor = .gray
input.textField.leftViewMode = .always
}
style(input)
States and variants
Normal state
The default state when the text input is interactive but not focused.
Visual characteristics:
- Default background color
- Default border color
- Placeholder text visible when empty
let textInput = TextInput(accessibilityLabel: "Email")
// Normal state is applied by default
Focus state
Active when the user taps into the text field.
Visual characteristics:
- Brand-colored border
- Cursor visible
// Focus state is applied automatically when the text field becomes first responder
textInput.textField.becomeFirstResponder()
Error state
Displayed when validation fails.
Visual characteristics:
- Danger-colored border
- Error label visible with error message
- Optional error icon
textInput.setError(errorMessage: "Invalid email format")
Disabled state
Applied when the input is not interactive.
Visual characteristics:
- Muted background color
- Reduced opacity text
- No user interaction
textInput.isUserInteractionEnabled = false
Read-only state
Displays content that cannot be edited.
Visual characteristics:
- Distinct background styling
- Text visible but not editable
textInput.setReadOnly(true)
Customization
Styling
|
Style |
Description |
|---|---|
|
DesignSystem.shared.styles.textInput |
Default text input style |
|
DesignSystem.shared.styles.passwordTextInput |
Password input style |
|
DesignSystem.shared.styles.readOnlyTextInput |
Read-only input style |
State-based styles
Configure styles for different states:
DesignSystem.shared.styles.textInput = DesignSystem.shared.styles.textInput <> { input in
// Customize disabled state
if let disabledStyle = input.disableStyle {
input.disableStyle = disabledStyle <> {
$0.textField.backgroundColor = .purple
$0.textField.textColor = .white
}
}
// Customize focus state
if let focusStyle = input.focusStyle {
input.focusStyle = focusStyle <> {
$0.textField.backgroundColor = .gray
$0.textField.textColor = .green
let borderOptions = DesignSystem.BorderOptions(
color: Theme.colors.border.brand.cgColor,
width: 2
)
$0.border = borderOptions
}
}
// Customize font
input.textField.font = DesignSystem.shared.fonts.preferredFont(.caption1, .regular)
// Customize text alignment
input.textField.textAlignment = .center
// Customize corner radius
input.cornerRadius = .max()
// Customize error label
input.errorLabel.textColor = .systemPink
input.errorLabel.font = DesignSystem.shared.fonts.preferredFont(.footnote, .regular)
// Customize paddings
input.textFieldPaddings = UIEdgeInsets(
top: DesignSystem.shared.sizer.md,
left: DesignSystem.shared.sizer.sm,
bottom: DesignSystem.shared.sizer.md,
right: DesignSystem.shared.sizer.sm
)
}
Custom trailing icon
Change the password visibility icon by adding an asset with the same name to your main .xcassets:
// Add an asset named `ic_visibility` to your app's .xcassets
// The change will be reflected automatically
Error handling
Display and clear error messages:
let textInput = TextInput(accessibilityLabel: "Email")
// Set error with image
textInput.errorImage = UIImage(named: DesignSystem.Assets.icError, in: .design)
textInput.setError(errorMessage: "Invalid email format")
// Clear error
textInput.clearError()
Accessibility
The TextInput component is built with accessibility in mind. See the information below for supported behaviors and configuration options to ensure a fully accessible experience for all users.
Accessibility configuration
|
Property |
Description |
Type |
|---|---|---|
|
accessibilityLabel |
The accessible label for the text field |
String? |
|
accessibilityIdentifier |
The identifier for UI testing |
String? |
Best practices
- Set a descriptive accessibilityLabel that describes the input purpose
- The error icon has a built-in accessibility label
- Helper and title labels are accessibility elements
- All labels support Dynamic Type
Localization
Override the following strings to customize accessibility text:
"DesignSystem.inputText.accessibility.errorIcon" = "Error";
Dependencies
- External dependencies: None
- Internal dependencies:
- IconView: Used for error icon display
Design tokens
Component styling is applied automatically through the design system's theming infrastructure.
JSON tokens
Tokens are defined in defaultTokens.json, which is integrated in the bundle of the framework, and can be customized by providing your own theme JSON file.
Token groups used by TextInput:
- color/input/default: Default state colors
- color/input/focused: Focused state colors
- color/input/error: Error state colors
- color/input/disabled: Disabled state colors
Default state tokens:
|
Token |
JSON Path |
Default Value |
|---|---|---|
|
Background |
theme.color.input.default.background |
{theme.color.background.surface-1} |
|
Border |
theme.color.input.default.border |
{theme.color.border.default} |
|
Value |
theme.color.input.default.value |
{theme.color.foreground.default} |
|
Placeholder |
theme.color.input.default.placeholder |
{theme.color.foreground.support} |
Focused state tokens:
|
Token |
JSON Path |
Default Value |
|---|---|---|
|
Background |
theme.color.input.focused.background |
{theme.color.background.surface-1} |
|
Border |
theme.color.input.focused.border |
{theme.color.border.brand} |
|
Value |
theme.color.input.focused.value |
{theme.color.foreground.default} |
Error state tokens:
|
Token |
JSON Path |
Default Value |
|---|---|---|
|
Background |
theme.color.input.error.background |
{theme.color.background.surface-1} |
|
Border |
theme.color.input.error.border |
{theme.color.border.danger} |
|
Value |
theme.color.input.error.value |
{theme.color.foreground.default} |
Disabled state tokens:
|
Token |
JSON Path |
Default Value |
|---|---|---|
|
Background |
theme.color.input.disabled.background |
{theme.color.background.disabled} |
|
Border |
theme.color.input.disabled.border |
{theme.color.border.default} |
|
Value |
theme.color.input.disabled.value |
{theme.color.foreground.support} |
Dimension tokens:
|
Token |
JSON Path |
Default Value |
|---|---|---|
|
Corner Radius |
theme.radius.input.default |
8 |
|
Height |
theme.height.input.md |
44 |
|
Padding X |
theme.padding-x.input.md |
16 |
|
Padding Y |
theme.padding-y.input.md |
8 |
|
Border Width |
theme.border-width.input.default |
1 |
Semantic tokens
|
Token |
API Reference |
Description |
|---|---|---|
|
Typography |
DesignSystem.shared.fonts.preferredFont(.body, .regular) |
Input text font |
|
Typography |
DesignSystem.shared.fonts.preferredFont(.caption1, .regular) |
Helper and error text font |
|
Typography |
DesignSystem.shared.fonts.preferredFont(.footnote, .regular) |
Title label font |
|
Spacing |
DesignSystem.shared.sizer.md |
Medium spacing |
|
Spacing |
DesignSystem.shared.sizer.sm |
Small spacing |
|
Styles |
DesignSystem.shared.styles.textInput |
Default text input style |
|
Styles |
DesignSystem.shared.styles.passwordTextInput |
Password input style |
|
Styles |
DesignSystem.shared.styles.readOnlyTextInput |
Read-only input style |
See also
- TextArea - Multi-line text input component