Documentation
Input Components
Collect user input with TextField and OutlinedTextField components.
TextField
Material Design filled text field:
<TextField label="Name" /> OutlinedTextField
Material Design outlined text field:
<OutlinedTextField label="Email" /> Two-Way Binding
Use bind:value to sync input with state:
var email = ""
<TextField bind:value={email} label="Email" />
<Text>You typed: {email}</Text> bind:value={email} transpiles to value = email, onValueChange = {{ email = it }}.
Changes automatically update your state variable.
Input Types
Use the type prop to get appropriate keyboards and transformations:
<TextField type="password" label="Password" />
<TextField type="email" label="Email" />
<TextField type="phone" label="Phone" />
<TextField type="number" label="Age" />
<TextField type="url" label="Website" /> | Type | Effect |
|---|---|
password | Hides characters with dots |
email | Email keyboard |
phone | Phone number keyboard |
number | Numeric keyboard |
url | URL keyboard |
Common Props
Label
<TextField label="Username" /> Placeholder
<TextField placeholder="Enter your name" /> Helper Text
<TextField label="Password" helperText="Must be at least 8 characters" /> Error State
var email = ""
val isValid = email.contains("@")
<TextField
bind:value={email}
label="Email"
error={!isValid && email.isNotEmpty()}
helperText={if (!isValid && email.isNotEmpty()) "Invalid email" else ""}
/> Disabled
<TextField label="Username" value="admin" disabled /> Read Only
<TextField label="ID" value={userId} readOnly /> Single Line
<TextField label="Title" singleLine /> Multi-Line
<TextField label="Bio" maxLines={5} /> Leading and Trailing Icons
<TextField
label="Search"
leadingIcon="search"
/>
<TextField
label="Email"
leadingIcon="email"
trailingIcon="check-circle"
/> Character Counter
var bio = ""
<TextField
bind:value={bio}
label="Bio"
maxLength={150}
helperText="{bio.length}/150 characters"
/> Form Validation
var email = ""
var password = ""
val emailValid = email.contains("@")
val passwordValid = password.length >= 8
val formValid = emailValid && passwordValid
<Column gap={16}>
<TextField
bind:value={email}
label="Email"
type="email"
error={!emailValid && email.isNotEmpty()}
helperText={if (!emailValid && email.isNotEmpty()) "Invalid email" else ""}
/>
<TextField
bind:value={password}
label="Password"
type="password"
error={!passwordValid && password.isNotEmpty()}
helperText={if (!passwordValid && password.isNotEmpty()) "At least 8 characters" else ""}
/>
<Button enabled={formValid} onClick={submit} text="Sign Up" />
</Column> Checkbox and Switch
Use bind:checked for boolean inputs:
var agreedToTerms = false
var notificationsEnabled = true
<Row gap={8} verticalAlignment="center">
<Checkbox bind:checked={agreedToTerms} />
<Text>I agree to the terms</Text>
</Row>
<Row gap={8} verticalAlignment="center">
<Text>Notifications</Text>
<Spacer weight={1} />
<Switch bind:checked={notificationsEnabled} />
</Row> Common Patterns
Login Form
var email = ""
var password = ""
suspend fun login() {
val response = $fetch.post(
url = "https://api.example.com/login",
body = mapOf("email" to email, "password" to password)
)
$navigate("/home")
}
<Column gap={16} p={20}>
<Text fontSize={24} fontWeight="bold">Sign In</Text>
<TextField
bind:value={email}
label="Email"
type="email"
leadingIcon="email"
/>
<TextField
bind:value={password}
label="Password"
type="password"
leadingIcon="lock"
/>
<Button onClick={login} text="Sign In" fillMaxWidth />
</Column> Search Bar
var query = ""
<OutlinedTextField
bind:value={query}
placeholder="Search..."
leadingIcon="search"
trailingIcon={if (query.isNotEmpty()) "close" else null}
onTrailingIconClick={() => query = ""}
singleLine
/> Settings Form
var username = "alice"
var bio = ""
var emailNotifications = true
var pushNotifications = false
<Column scrollable p={16} gap={20}>
<Text fontSize={20} fontWeight="bold">Profile Settings</Text>
<TextField
bind:value={username}
label="Username"
leadingIcon="person"
/>
<TextField
bind:value={bio}
label="Bio"
maxLines={4}
helperText="{bio.length}/150"
/>
<Text fontSize={18} fontWeight="medium">Notifications</Text>
<Row verticalAlignment="center">
<Column weight={1}>
<Text>Email Notifications</Text>
<Text fontSize={12} color="secondary">Receive updates via email</Text>
</Column>
<Switch bind:checked={emailNotifications} />
</Row>
<Row verticalAlignment="center">
<Column weight={1}>
<Text>Push Notifications</Text>
<Text fontSize={12} color="secondary">Receive push notifications</Text>
</Column>
<Switch bind:checked={pushNotifications} />
</Row>
<Button text="Save Changes" fillMaxWidth />
</Column> Prop Reference
| Prop | Type | Description |
|---|---|---|
label | String | Field label |
placeholder | String | Placeholder text |
type | String | Input type (password, email, etc.) |
helperText | String | Helper text below field |
error | Boolean | Error state |
disabled | Boolean | Disable input |
readOnly | Boolean | Read-only mode |
singleLine | Boolean | Single line input |
maxLines | Number | Maximum lines for multi-line |
maxLength | Number | Maximum character count |
leadingIcon | String | Icon at start of field |
trailingIcon | String | Icon at end of field |
See Also
- Button Component - Submit forms and trigger actions
- Text Component - Display labels and validation messages
- State Management - Managing form state