Skip to main content
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

value
String
required
The current text value
onValueChange
(String) -> Unit
required
Callback when the text changes
modifier
Modifier
default:"Modifier"
Modifier to be applied to the text field
enabled
Boolean
default:"true"
Whether the text field is enabled and can receive input
readOnly
Boolean
default:"false"
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.)
singleLine
Boolean
default:"false"
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
isError
Boolean
default:"false"
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

Build docs developers (and LLMs) love