Lumo UI provides two TextField variants: a filled TextField with a background and an OutlinedTextField with a border. Both support labels, placeholders, icons, and validation states.
Import
import com.nomanr.lumo.ui.components.textfield.TextField
import com.nomanr.lumo.ui.components.textfield.OutlinedTextField
TextField (Filled)
A text field with a filled background, suitable for forms and input areas.
Component Signature
@Composable
fun TextField(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = AppTheme.typography.input,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
singleLine: Boolean = false,
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
minLines: Int = 1,
visualTransformation: VisualTransformation = VisualTransformation.None,
onTextLayout: (TextLayoutResult) -> Unit = {},
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
placeholder: @Composable (() -> Unit)? = null,
prefix: @Composable (() -> Unit)? = null,
suffix: @Composable (() -> Unit)? = null,
label: @Composable (() -> Unit)? = null,
leadingIcon: @Composable (() -> Unit)? = null,
trailingIcon: @Composable (() -> Unit)? = null,
supportingText: @Composable (() -> Unit)? = null,
isError: Boolean = false,
shape: Shape = TextFieldDefaults.Shape,
colors: TextFieldColors = TextFieldDefaults.colors(),
cursorBrush: Brush = SolidColor(colors.cursorColor(isError).value),
)
Source: TextField.kt:46-122
OutlinedTextField
A text field with an outlined border, providing a lighter visual weight.
Component Signature
@Composable
fun OutlinedTextField(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = AppTheme.typography.input,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
singleLine: Boolean = false,
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
minLines: Int = 1,
visualTransformation: VisualTransformation = VisualTransformation.None,
onTextLayout: (TextLayoutResult) -> Unit = {},
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
placeholder: @Composable (() -> Unit)? = null,
prefix: @Composable (() -> Unit)? = null,
suffix: @Composable (() -> Unit)? = null,
label: @Composable (() -> Unit)? = null,
leadingIcon: @Composable (() -> Unit)? = null,
trailingIcon: @Composable (() -> Unit)? = null,
supportingText: @Composable (() -> Unit)? = null,
isError: Boolean = false,
shape: Shape = OutlinedTextFieldDefaults.Shape,
colors: TextFieldColors = OutlinedTextFieldDefaults.colors(),
cursorBrush: Brush = SolidColor(colors.cursorColor(isError).value),
)
Source: OutlinedTextField.kt:46-120
Parameters
Callback when the text changes
modifier
Modifier
default:"Modifier"
Modifier to be applied to the text field
Whether the text field is enabled and can receive input
Whether the text field is read-only (displays but cannot be edited)
textStyle
TextStyle
default:"AppTheme.typography.input"
Style for the input text
keyboardOptions
KeyboardOptions
default:"KeyboardOptions.Default"
Software keyboard options (keyboard type, IME action, etc.)
Whether the text field is single line
maxLines
Int
default:"Int.MAX_VALUE (or 1 if singleLine)"
Maximum number of lines for the text field
visualTransformation
VisualTransformation
default:"VisualTransformation.None"
Transforms the visual representation (e.g., PasswordVisualTransformation)
placeholder
@Composable (() -> Unit)?
default:"null"
Placeholder text displayed when field is empty
label
@Composable (() -> Unit)?
default:"null"
Label displayed above the text field
leadingIcon
@Composable (() -> Unit)?
default:"null"
Icon displayed at the start of the text field
trailingIcon
@Composable (() -> Unit)?
default:"null"
Icon displayed at the end of the text field
prefix
@Composable (() -> Unit)?
default:"null"
Text displayed before the input text
suffix
@Composable (() -> Unit)?
default:"null"
Text displayed after the input text
supportingText
@Composable (() -> Unit)?
default:"null"
Helper or error text displayed below the text field
Whether the text field should display in error state
Examples
Basic TextField
var text by remember { mutableStateOf("") }
TextField(
value = text,
onValueChange = { text = it },
placeholder = { Text("Enter your name") }
)
TextField with Label and Icons
var email by remember { mutableStateOf("") }
TextField(
value = email,
onValueChange = { email = it },
label = { Text("Email") },
leadingIcon = {
Icon(imageVector = Icons.Default.Email, contentDescription = "Email")
},
placeholder = { Text("[email protected]") },
singleLine = true,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email)
)
Outlined TextField with Validation
var password by remember { mutableStateOf("") }
val isPasswordError = password.length < 8 && password.isNotEmpty()
OutlinedTextField(
value = password,
onValueChange = { password = it },
label = { Text("Password") },
isError = isPasswordError,
supportingText = {
if (isPasswordError) {
Text("Password must be at least 8 characters")
}
},
visualTransformation = PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
singleLine = true
)
TextField with Prefix and Suffix
var amount by remember { mutableStateOf("") }
TextField(
value = amount,
onValueChange = { amount = it },
label = { Text("Amount") },
prefix = { Text("$") },
suffix = { Text("USD") },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
singleLine = true
)
Multi-line TextField
var notes by remember { mutableStateOf("") }
TextField(
value = notes,
onValueChange = { notes = it },
label = { Text("Notes") },
placeholder = { Text("Enter your notes here...") },
minLines = 3,
maxLines = 5,
modifier = Modifier.fillMaxWidth()
)
Read-only TextField
TextField(
value = "This cannot be edited",
onValueChange = {},
readOnly = true,
label = { Text("Read-only Field") }
)
TextFieldValue Support
Both TextField and OutlinedTextField also support TextFieldValue for more control over selection and composition:
var textFieldValue by remember { mutableStateOf(TextFieldValue("")) }
TextField(
value = textFieldValue,
onValueChange = { textFieldValue = it },
placeholder = { Text("Type here") }
)
Styling
TextField Defaults
From TextFieldDefaults (TextField.kt:204-206):
- Min Height: 56.dp
- Shape: RoundedCornerShape(8.dp)
- Background:
AppTheme.colors.surface (filled)
- Border: Transparent (no visible border)
OutlinedTextField Defaults
From OutlinedTextFieldDefaults (OutlinedTextField.kt:202-204):
- Min Height: 56.dp
- Shape: RoundedCornerShape(8.dp)
- Background: Transparent
- Border: 1.dp (unfocused), 2.dp (focused)
- Border Colors: Secondary (unfocused), Primary (focused)
Color Customization
Both variants use TextFieldColors which provides extensive color customization for different states:
TextField(
value = text,
onValueChange = { text = it },
colors = TextFieldDefaults.colors(
focusedTextColor = Color.Black,
unfocusedTextColor = Color.Gray,
focusedContainerColor = Color.White,
focusedOutlineColor = Color.Blue,
cursorColor = Color.Blue,
errorCursorColor = Color.Red
)
)
Accessibility
- Text fields automatically handle focus and keyboard interactions
- Support for screen readers through semantic properties
- Error states clearly indicated with color changes
- Labels provide context for screen readers
- Minimum height ensures adequate touch targets
Source Reference
- Filled TextField:
com.nomanr.lumo.ui.components.textfield.TextField.kt
- Outlined TextField:
com.nomanr.lumo.ui.components.textfield.OutlinedTextField.kt