Start native apps faster with the Composables CLI ->
Class

KeyboardOptions

Defines keyboard configuration options for TextFields.

RegistrationFormSample

/**
 * A complete profile registration screen sample. Shows how to handle standard name entries, login
 * emails, physical mailing address lines, secure password visibility eye-icon togglers, and natural
 * language biography summaries.
 */
@Sampled
@Composable
fun RegistrationFormSample() {
    val nameState = rememberTextFieldState()
    val emailState = rememberTextFieldState()
    val passwordState = rememberTextFieldState()
    var isPasswordVisible by remember { mutableStateOf(false) }
    val urlState = rememberTextFieldState()
    val addressState = rememberTextFieldState()
    val biographyState = rememberTextFieldState()

    Column(
        verticalArrangement = Arrangement.spacedBy(12.dp),
        modifier = Modifier.padding(16.dp).fillMaxWidth(),
    ) {
        // 1. PersonName Input (Auto-Capitalizes Words)
        OutlinedTextField(
            state = nameState,
            label = { Text("Full Name") },
            keyboardOptions =
                KeyboardOptions(
                    keyboardType = KeyboardType.PersonName,
                    capitalization = KeyboardCapitalization.Words,
                    imeAction = ImeAction.Next, // Soft keyboard automatically moves focus on Next
                ),
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )

        // 2. Email Input (Restricted layout showing '@' and '.', auto-capitalization disabled)
        OutlinedTextField(
            state = emailState,
            label = { Text("Email") },
            keyboardOptions =
                KeyboardOptions(
                    keyboardType = KeyboardType.Email,
                    capitalization = KeyboardCapitalization.None,
                    imeAction = ImeAction.Next,
                ),
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )

        // 3. Password Input with Eye-Icon Toggle (masked vs visible password layouts,
        // capitalizations disabled)
        Row(verticalAlignment = Alignment.CenterVertically) {
            OutlinedSecureTextField(
                state = passwordState,
                label = { Text("Password") },
                textObfuscationMode =
                    if (isPasswordVisible) TextObfuscationMode.Visible
                    else TextObfuscationMode.System,
                keyboardOptions =
                    KeyboardOptions(
                        keyboardType =
                            if (isPasswordVisible) KeyboardType.PasswordVisible
                            else KeyboardType.Password,
                        capitalization = KeyboardCapitalization.None,
                        imeAction = ImeAction.Next,
                    ),
                modifier = Modifier.weight(0.7f),
            )
            Spacer(Modifier.width(8.dp))
            TextButton(
                onClick = { isPasswordVisible = !isPasswordVisible },
                modifier = Modifier.weight(0.3f),
            ) {
                Text(if (isPasswordVisible) "Hide" else "Show")
            }
        }

        // 4. Uri Input (Prominent '/' and '.com' keys, auto-capitalization disabled)
        OutlinedTextField(
            state = urlState,
            label = { Text("Homepage URL") },
            keyboardOptions =
                KeyboardOptions(
                    keyboardType = KeyboardType.Uri,
                    capitalization = KeyboardCapitalization.None,
                    imeAction = ImeAction.Next,
                ),
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )

        // 5. PostalAddress Input (Auto-Capitalizes Words, prompts standard shipping keys)
        OutlinedTextField(
            state = addressState,
            label = { Text("Shipping Address") },
            keyboardOptions =
                KeyboardOptions(
                    keyboardType = KeyboardType.PostalAddress,
                    capitalization = KeyboardCapitalization.Words,
                    imeAction = ImeAction.Next,
                ),
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )

        // 6. Free-Text Biography Input (Auto-Capitalizes Sentences, multi-line active)
        OutlinedTextField(
            state = biographyState,
            label = { Text("Biography") },
            keyboardOptions =
                KeyboardOptions(
                    keyboardType = KeyboardType.Text,
                    capitalization = KeyboardCapitalization.Sentences,
                    imeAction =
                        ImeAction.Done, // Soft keyboard automatically dismisses keyboard on Done
                ),
            modifier = Modifier.fillMaxWidth(),
        )
    }
}

/**
 * A register cashier checkout panel sample. Shows how to build secure cashier PIN rows, automatic
 * dollar currency amounts input formatters, integer item quantities, customer phone dialers, and
 * capitalized promo voucher entry lines.
 */

CheckoutRegisterFormSample

@Sampled
@Composable
fun CheckoutRegisterFormSample() {
    val cashierPinState = rememberTextFieldState()
    val qtyState = rememberTextFieldState()
    val phoneState = rememberTextFieldState()
    val couponState = rememberTextFieldState()
    val balanceOffsetState = rememberTextFieldState()

    val pinLength = 4

    Column(
        verticalArrangement = Arrangement.spacedBy(12.dp),
        modifier = Modifier.padding(16.dp).fillMaxWidth(),
    ) {
        // 1. NumberPassword PIN Entry (Masked secure numeric pad (0-9))
        OutlinedSecureTextField(
            state = cashierPinState,
            label = { Text("Enter Cashier PIN (OTP)") },
            keyboardOptions =
                KeyboardOptions(
                    keyboardType = KeyboardType.NumberPassword,
                    imeAction = ImeAction.Next,
                ),
            inputTransformation =
                InputTransformation.byValue { _, proposed -> proposed.filter { it.isDigit() } }
                    .maxLength(pinLength),
            modifier = Modifier.fillMaxWidth(),
        )

        // 2. Number Plain Integer Input (Pure numeric key entry for quantities)
        OutlinedTextField(
            state = qtyState,
            label = { Text("Item Quantity Count") },
            keyboardOptions =
                KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Next),
            inputTransformation =
                InputTransformation.byValue { _, proposed -> proposed.filter { it.isDigit() } },
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )

        // 4. Phone Contact Entry (Displays telephony dialer keyboard with '+', '*', '#')
        OutlinedTextField(
            state = phoneState,
            label = { Text("Customer Loyalty Phone Number") },
            keyboardOptions =
                KeyboardOptions(keyboardType = KeyboardType.Phone, imeAction = ImeAction.Next),
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )

        // 5. Ascii / KeyboardCapitalization.Characters (Uppercase restricted ASCII promo vouchers)
        OutlinedTextField(
            state = couponState,
            label = { Text("Promo Coupon Code") },
            inputTransformation = InputTransformation.allCaps(Locale.current),
            keyboardOptions =
                KeyboardOptions(
                    keyboardType = KeyboardType.Ascii,
                    capitalization = KeyboardCapitalization.Characters,
                    autoCorrectEnabled = false,
                    imeAction = ImeAction.Next,
                ),
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )

        // 6. DecimalSigned Shared Offset Balance Adjustments (Allows decimal coordinates and
        // negative/positive signs)
        OutlinedTextField(
            state = balanceOffsetState,
            label = { Text("Add Balance Offset (Debits/Credits)") },
            keyboardOptions =
                KeyboardOptions(
                    keyboardType = KeyboardType.DecimalSigned,
                    imeAction = ImeAction.Done,
                ),
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )
    }
}

/**
 * An alarm clock, timer, and calendar event scheduler card sample. Shows how to handle geographic
 * date selectors, preset time clocks, and combined scheduling timestamps.
 */

DateTimeSchedulerFormSample

@Sampled
@Composable
fun DateTimeSchedulerFormSample() {
    val birthState = rememberTextFieldState()
    val timerState = rememberTextFieldState()
    val meetingState = rememberTextFieldState()

    Column(
        verticalArrangement = Arrangement.spacedBy(12.dp),
        modifier = Modifier.padding(16.dp).fillMaxWidth(),
    ) {
        // 1. Date Input (Prompt numeric layout tailored for dates containing '/' or '-')
        OutlinedTextField(
            state = birthState,
            label = { Text("Birthdate (YYYY/MM/DD)") },
            keyboardOptions =
                KeyboardOptions(keyboardType = KeyboardType.Date, imeAction = ImeAction.Next),
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )

        // 2. Time Input (Prompt numeric layout tailored for times containing ':')
        OutlinedTextField(
            state = timerState,
            label = { Text("Timer Preset Clock (HH:MM)") },
            keyboardOptions =
                KeyboardOptions(keyboardType = KeyboardType.Time, imeAction = ImeAction.Next),
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )

        // 3. DateTime Input (Prompts clock-calendar layout option)
        OutlinedTextField(
            state = meetingState,
            label = { Text("Combined Meeting Timestamp (YYYY/MM/DD HH:MM)") },
            keyboardOptions =
                KeyboardOptions(keyboardType = KeyboardType.DateTime, imeAction = ImeAction.Done),
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )
    }
}

/**
 * Demonstrates search filters, phonetic translation entries, and specialty masked numeric keypads.
 */

SpecialtyInputsFormSample

@Sampled
@Composable
fun SpecialtyInputsFormSample() {
    val filterState = rememberTextFieldState()
    val phoneticState = rememberTextFieldState()
    val maskedCoordsState = rememberTextFieldState()
    val maskedBalanceState = rememberTextFieldState()
    val maskedPasskeyState = rememberTextFieldState()

    Column(
        verticalArrangement = Arrangement.spacedBy(12.dp),
        modifier = Modifier.padding(16.dp).fillMaxWidth(),
    ) {
        // 1. Filter Input (Optimized list filtering, auto-capitalization/suggestions disabled)
        OutlinedTextField(
            state = filterState,
            label = { Text("Search Query") },
            keyboardOptions =
                KeyboardOptions(
                    keyboardType = KeyboardType.Filter,
                    capitalization = KeyboardCapitalization.None,
                    imeAction = ImeAction.Next,
                ),
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )

        // 2. Phonetic Input (For phonetic readings/pronunciations, e.g. phonetic names in contacts)
        OutlinedTextField(
            state = phoneticState,
            label = { Text("Phonetic Name") },
            keyboardOptions =
                KeyboardOptions(keyboardType = KeyboardType.Phonetic, imeAction = ImeAction.Next),
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )

        // 3. DecimalPassword Input (Masked numeric pad showing decimal separators)
        OutlinedSecureTextField(
            state = maskedCoordsState,
            label = { Text("Secure Decimal Value") },
            keyboardOptions =
                KeyboardOptions(
                    keyboardType = KeyboardType.DecimalPassword,
                    imeAction = ImeAction.Next,
                ),
            modifier = Modifier.fillMaxWidth(),
        )

        // 4. NumberPasswordSigned Input (Masked numeric pad showing positive/negative signs)
        OutlinedSecureTextField(
            state = maskedBalanceState,
            label = { Text("Secure Signed Value") },
            keyboardOptions =
                KeyboardOptions(
                    keyboardType = KeyboardType.NumberPasswordSigned,
                    imeAction = ImeAction.Next,
                ),
            modifier = Modifier.fillMaxWidth(),
        )

        // 5. DecimalPasswordSigned Input (Masked numeric pad showing both decimals and signs)
        OutlinedSecureTextField(
            state = maskedPasskeyState,
            label = { Text("Secure Decimal Signed Value") },
            keyboardOptions =
                KeyboardOptions(
                    keyboardType = KeyboardType.DecimalPasswordSigned,
                    imeAction = ImeAction.Done,
                ),
            modifier = Modifier.fillMaxWidth(),
        )
    }
}

PinCodeEntryRowSample

@Sampled
@Composable
fun PinCodeEntryRowSample() {
    val pinState = rememberTextFieldState()
    val pinLength = 4

    BasicSecureTextField(
        state = pinState,
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.NumberPassword),
        inputTransformation =
            InputTransformation.byValue { _, proposed -> proposed.filter { it.isDigit() } }
                .maxLength(pinLength),
        decorator = { innerTextField ->
            Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                repeat(pinLength) { index ->
                    val char = pinState.text.getOrNull(index)
                    Box(
                        modifier =
                            Modifier.size(48.dp)
                                .border(
                                    1.dp,
                                    if (pinState.text.length == index) Color.Blue else Color.Gray,
                                    RoundedCornerShape(8.dp),
                                ),
                        contentAlignment = Alignment.Center,
                    ) {
                        if (char != null) {
                            Text("●")
                        }
                    }
                }
            }
        },
    )
}

/**
 * Decimal input fields for entering coordinates. Prompts soft keyboards to show a decimal point
 * key.
 */

DecimalInputSample

@Sampled
@Composable
fun DecimalInputSample() {
    val latitudeState = rememberTextFieldState("37.7749")
    val longitudeState = rememberTextFieldState("-122.4194")

    Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
        OutlinedTextField(
            state = latitudeState,
            label = { Text("Latitude") },
            keyboardOptions =
                KeyboardOptions(keyboardType = KeyboardType.Decimal, imeAction = ImeAction.Next),
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )

        OutlinedTextField(
            state = longitudeState,
            label = { Text("Longitude") },
            keyboardOptions =
                KeyboardOptions(keyboardType = KeyboardType.Decimal, imeAction = ImeAction.Done),
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )
    }
}

/**
 * An integer item count settings field. Shows error validation warning text when non-digits or
 * invalid counts are inputted.
 */

ItemCountSettingsSample

@Sampled
@Composable
fun ItemCountSettingsSample() {
    val countState = rememberTextFieldState("100")
    val isError by remember {
        derivedStateOf {
            val parsed = countState.text.toString().toIntOrNull()
            parsed == null || parsed <= 0
        }
    }

    Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
        OutlinedTextField(
            state = countState,
            label = { Text("List Item Display Count") },
            isError = isError,
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
            lineLimits = TextFieldLineLimits.SingleLine,
            modifier = Modifier.fillMaxWidth(),
        )
        if (isError) {
            Text("Value must be a positive integer", color = Color.Red)
        }
    }
}