Text Field
A polished text input component featuring floating labels, smooth animations, validation states, and icons.
Import
import PrettyUI
Basic Usage
@State private var email = ""
PTextField("Email", text: $email)
Variants
Three visual variants are available:
// Outlined - bordered (default)
PTextField("Email", text: $email)
.variant(.outlined)
// Filled - background color
PTextField("Search", text: $query)
.variant(.filled)
// Underlined - bottom border only
PTextField("Name", text: $name)
.variant(.underlined)
| Variant | Style | Best For |
|---|---|---|
.outlined | Border | Forms, default use |
.filled | Background | Search bars, compact forms |
.underlined | Bottom line | Minimal, elegant forms |
Sizes
Three sizes are available:
PTextField("Small", text: $text).size(.sm) // 48pt height
PTextField("Medium", text: $text).size(.md) // 56pt height (default)
PTextField("Large", text: $text).size(.lg) // 64pt height
Icons
Add leading and/or trailing icons:
// Leading icon
PTextField("Email", text: $email)
.leadingIcon("envelope")
// Trailing icon
PTextField("Website", text: $website)
.trailingIcon("arrow.up.right")
// Both
PTextField("Search", text: $query)
.leadingIcon("magnifyingglass")
.trailingIcon("mic.fill")
Secure Text (Password)
Create password fields with visibility toggle:
PTextField("Password", text: $password)
.secure()
.leadingIcon("lock")
The field automatically shows an eye icon to toggle visibility.
Floating Label
By default, PTextField uses a floating label that animates up when focused or filled:
// Enable (default)
PTextField("Email", text: $email)
.floatingLabel(true)
// Disable for static placeholder
PTextField("Enter your name", text: $name)
.floatingLabel(false)
Clear Button
Show a clear button when text is present:
PTextField("Search", text: $query)
.clearButton() // Enabled by default
.clearButton(false) // Disable
Validation States
Error State
PTextField("Email", text: $email)
.leadingIcon("envelope")
.error(emailError) // Pass nil to clear
// Example with validation
.error(isValidEmail(email) ? nil : "Please enter a valid email")
Success State
PTextField("Username", text: $username)
.leadingIcon("person")
.success("Username is available!")
Helper Text
PTextField("Email", text: $email)
.helper("We'll never share your email")
Character Limit
Show a character counter with limit:
PTextField("Bio", text: $bio)
.maxCharacters(100)
The counter turns red when over the limit.
Keyboard Configuration (iOS)
PTextField("Email", text: $email)
.keyboard(.emailAddress)
.autocapitalization(.never)
PTextField("Phone", text: $phone)
.keyboard(.phonePad)
PTextField("Amount", text: $amount)
.keyboard(.decimalPad)
Submit Handling
Handle keyboard submit action:
PTextField("Search", text: $query)
.submitLabel(.search)
.onSubmit {
performSearch()
}
Available submit labels: .done, .go, .search, .send, .next, .continue
Disabled State
PTextField("Email", text: .constant("john@example.com"))
.disabled()
Custom Colors
Override the default colors:
// Custom focus color
PTextField("Email", text: $email)
.focusColor(.purple)
// Custom background
PTextField("Search", text: $query)
.backgroundColor(Color.gray.opacity(0.1))
// All custom colors
PTextField("Custom", text: $text)
.colors(
focus: .green,
background: Color.green.opacity(0.1),
foreground: .green,
placeholder: Color.green.opacity(0.5)
)
Search Field
PrettyUI includes a pre-configured search field:
@State private var searchQuery = ""
PSearchField("Search wallets...", text: $searchQuery) {
performSearch()
}
This is equivalent to:
PTextField("Search", text: $query)
.variant(.filled)
.leadingIcon("magnifyingglass")
.floatingLabel(false)
.clearButton()
.radius(.full)
Labeled Text Field
For forms with static labels above the field:
PLabeledTextField(
"Email Address",
placeholder: "john@example.com",
text: $email,
isRequired: true
)
Real-World Examples
Login Form
VStack(spacing: 16) {
PTextField("Email", text: $email)
.leadingIcon("envelope")
.keyboard(.emailAddress)
.autocapitalization(.never)
.error(emailError)
PTextField("Password", text: $password)
.secure()
.leadingIcon("lock")
.error(passwordError)
PButton("Sign In") {
login()
}
.variant(.primary)
.fullWidth()
.loading(isLoading)
}
Profile Form
VStack(spacing: 20) {
PLabeledTextField("Full Name", text: $name, isRequired: true)
PLabeledTextField("Email", text: $email, isRequired: true)
.keyboard(.emailAddress)
PTextField("Bio", text: $bio)
.maxCharacters(150)
.helper("Tell us about yourself")
}
Search with Suggestions
VStack {
PSearchField("Search products...", text: $query) {
search()
}
if !query.isEmpty {
ForEach(suggestions) { suggestion in
Text(suggestion.name)
}
}
}
API Reference
Initializer
public init(_ label: String, text: Binding<String>)
Modifiers
| Modifier | Type | Description |
|---|---|---|
.variant(_:) | PTextFieldVariant | Visual style |
.size(_:) | PTextFieldSize | Field size |
.radius(_:) | RadiusSize | Corner radius |
.secure(_:) | Bool | Password mode |
.floatingLabel(_:) | Bool | Floating label animation |
.clearButton(_:) | Bool | Show clear button |
.maxCharacters(_:) | Int | Character limit |
.leadingIcon(_:) | String | SF Symbol name |
.trailingIcon(_:) | String | SF Symbol name |
.error(_:) | String? | Error message |
.success(_:) | String? | Success message |
.helper(_:) | String? | Helper text |
.disabled(_:) | Bool | Disable field |
.keyboard(_:) | UIKeyboardType | Keyboard type (iOS) |
.autocapitalization(_:) | TextInputAutocap... | Auto-caps (iOS) |
.submitLabel(_:) | SubmitLabel | Return key label |
.onSubmit(_:) | () -> Void | Submit action |
.focusColor(_:) | Color | Focus ring color |
.backgroundColor(_:) | Color | Background color |
.foregroundColor(_:) | Color | Text color |
.placeholderColor(_:) | Color | Placeholder color |
Enums
PTextFieldVariant
.outlined— Bordered (default).filled— Background color.underlined— Bottom line only
PTextFieldSize
.sm— Small (48pt).md— Medium (56pt, default).lg— Large (64pt)
Helper Components
PSearchField
PSearchField(_ placeholder: String, text: Binding<String>, onSubmit: (() -> Void)?)
Pre-configured search field with pill shape and magnifying glass icon.
PLabeledTextField
PLabeledTextField(
_ label: String,
placeholder: String = "",
text: Binding<String>,
isRequired: Bool = false
)
Text field with a static label above (non-floating).
Accessibility
PTextField automatically:
- Announces the label and current value for VoiceOver
- Indicates error and success states
- Shows character count for limited fields
- Respects reduced motion preferences