---
title: Text Field
description: A themable component to build text fields with the styling of your choice. Supports placeholders, leading and trailing slots out of the box along with accessibility labels (visual or not).
---

```compose id="textfield-demo" height=400
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import com.composables.icons.lucide.Eye
import com.composables.icons.lucide.EyeOff
import com.composables.icons.lucide.Lucide
import com.composeunstyled.*

COMPOSE {
    var email = rememberTextFieldState()
    var password = rememberTextFieldState()
    var showPassword by remember { mutableStateOf(false) }

    Box(
        modifier = Modifier.fillMaxSize()
            .padding(horizontal = 16.dp)
            .padding(top = 16.dp),
        contentAlignment = Alignment.Center
    ) {
        Box(
            modifier = Modifier
                .widthIn(max = 500.dp)
                .shadow(8.dp, RoundedCornerShape(16.dp))
                .background(Color.White, RoundedCornerShape(16.dp))
                .padding(24.dp),
            contentAlignment = Alignment.Center
        ) {
            Column(
                verticalArrangement = Arrangement.spacedBy(16.dp),
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                TextField(
                    state = email,
                    modifier = Modifier.fillMaxWidth(),
                    singleLine = true,
                    keyboardOptions = KeyboardOptions(
                        keyboardType = KeyboardType.Email
                    ),
                ) {
                    Text("Email", modifier = Modifier.padding(bottom = 8.dp), fontWeight = FontWeight.SemiBold)
                    TextInput(
                        Modifier
                            .fillMaxWidth()
                            .border(1.dp, Color(0xFFBDBDBD), RoundedCornerShape(8.dp))
                            .background(Color.White, RoundedCornerShape(8.dp))
                            .padding(horizontal = 16.dp, vertical = 12.dp),
                        placeholder = { Text("email@example.com", color = Color.Black.copy(0.6f)) },
                    )
                }

                TextField(
                    state = password,
                    modifier = Modifier.fillMaxWidth(),
                    singleLine = true,
                    visualTransformation = if (showPassword) VisualTransformation.None else PasswordVisualTransformation()
                ) {
                    Text("Password", modifier = Modifier.padding(bottom = 8.dp), fontWeight = FontWeight.SemiBold)
                    TextInput(
                        modifier = Modifier
                            .fillMaxWidth()
                            .border(1.dp, Color(0xFFBDBDBD), RoundedCornerShape(8.dp))
                            .background(Color.White, RoundedCornerShape(8.dp))
                            .padding(vertical = 4.dp)
                            .padding(start = 16.dp, end = 4.dp),
                        placeholder = { Text("8-12 characters", color = Color.Black.copy(0.6f)) },
                        trailing = {
                            Button(
                                onClick = { showPassword = !showPassword },
                                backgroundColor = Color.Transparent,
                                contentPadding = PaddingValues(4.dp),
                                shape = RoundedCornerShape(4.dp)
                            ) {
                                Icon(
                                    imageVector = if (showPassword) Lucide.EyeOff else Lucide.Eye,
                                    contentDescription = if (showPassword) "Hide password" else "Show password",
                                    tint = Color(0xFF757575)
                                )
                            }
                        }
                    )
                }

                Button(
                    onClick = { /* TODO */ },
                    modifier = Modifier.fillMaxWidth(),
                    backgroundColor = Color(0xFF8E44AD),
                    contentColor = Color.White,
                    contentPadding = PaddingValues(12.dp),
                    shape = RoundedCornerShape(8.dp)
                ) {
                    Text("Submit", fontWeight = FontWeight.Medium)
                }
            }
        }
    }
}
```

## Basic Example

To create a text field, use the `TextField` component with `TextFieldState` and use the `TextInput()` component within its content scope.

The `TextField` itself groups together every part of the text field in order to make sense for screen reader technology.

Other than the `TextInput` which handles the part of the text field the user can enter text at, it can contain elements
such as `Text` for a visual label.

```kotlin
val state = remember { TextFieldState() }

TextField(
    state = state,
    singleLine = true
) {
    TextInput()
}
```

## Styling

Every component in Compose Unstyled is renderless. They handle all UX pattern logic, internal state, accessibility (
according to ARIA standards), and keyboard interactions for you, but they do not render any UI to the screen.

This is by design so that you can style your components exactly to your needs.

Most of the time, styling is done using `Modifiers` of your choice. However, sometimes this is not enough due to the
order of the `Modifier`s affecting the visual outcome.

For such cases we provide specific styling parameters.

## Code Examples

### Consistent typography through your app

It is recommended to use the provided `LocalTextStyle` in order to maintain consistent text styling across your app.

If you need to override a text style for specific cases, you can either override a specific parameter via the `Text`
modifier or pass an entire different style via the `style` parameter:

```kotlin
val state = remember { TextFieldState() }

CompositionLocalProvider(LocalTextStyle provides TextStyle(fontSize = 18.sp, fontWeight = FontWeight.Medium)) {
    Column {
        // this text field will use the provided Text Style
        TextField(
            state = state,
        ) {
            // the provided text style will be used in the text input
            TextInput()
        }
        Text("So will this text")

        Text("This text is also styled, but slightly modified", letterSpacing = 2.sp)

        Text("This text is completely different", style = TextStyle())
    }
}
```

### Specifying Input Type

You can specify the input type for the `TextField` using the `keyboardOptions` parameter. For example, to specify an
email input type:

```kotlin
val state = remember { TextFieldState() }

TextField(
    state = state,
    modifier = Modifier.fillMaxWidth(),
    keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email)
) {
    TextInput(
        placeholder = { Text("Email") }
    )
}
```

### Adding a Trailing Icon

You can add a trailing icon to the `TextField` to provide additional functionality, such as toggling password
visibility:

```kotlin
val state = remember { TextFieldState() }
var showPassword by remember { mutableStateOf(false) }

TextField(
    state = state,
) {
    TextInput(
        placeholder = { Text("Password") },
        trailing = {
            Button(
                onClick = { showPassword = !showPassword },
                backgroundColor = Color.Transparent,
                contentPadding = PaddingValues(4.dp),
                shape = RoundedCornerShape(4.dp)
            ) {
                Icon(
                    imageVector = if (showPassword) EyeOff else Eye,
                    contentDescription = if (showPassword) "Hide password" else "Show password",
                    tint = Color(0xFF757575)
                )
            }
        }
    )
}
```

### Handling Password Input

To handle password input, you can use the `visualTransformation` parameter to obscure the text:

```kotlin
val state = remember { TextFieldState() }
var showPassword by remember { mutableStateOf(false) }

TextField(
    state = state,
    visualTransformation = if (showPassword) VisualTransformation.None else PasswordVisualTransformation(),
) {
    TextInput(
        placeholder = { Text("Password") },
        trailing = {
            Button(
                onClick = { showPassword = !showPassword },
                backgroundColor = Color.Transparent,
                contentPadding = PaddingValues(4.dp),
                shape = RoundedCornerShape(4.dp)
            ) {
                Icon(
                    imageVector = if (showPassword) EyeOff else Eye,
                    contentDescription = if (showPassword) "Hide password" else "Show password",
                    tint = Color(0xFF757575)
                )
            }
        }
    )
}
```

### Adding an Invisible Label

You can add an invisible label to your text field for accessibility purposes.

This is particularly useful when you want to provide context for screen readers without showing a visual label:

```kotlin
val state = remember { TextFieldState() }

TextField(
    state = state,
) {
    TextInput(
        label = "Email address", // This label is only visible to screen readers
        placeholder = { Text("Enter your email") }
    )
}
```

## Component API

### TextField

| Parameter              | Description                                     |
|------------------------|-------------------------------------------------|
| `state`                | The `TextFieldState` that manages the text field's content. |
| `modifier`             | Modifier to be applied to the text field.       |
| `editable`             | Whether the text field is editable.             |
| `cursorBrush`          | The brush to use for the cursor.                |
| `textStyle`            | Style to apply to the text.                     |
| `textAlign`            | Alignment of the text.                          |
| `lineHeight`           | Height of each line of text.                    |
| `fontSize`             | Size of the font.                               |
| `letterSpacing`        | Spacing between letters.                        |
| `fontWeight`           | Weight of the font.                             |
| `fontFamily`           | Family of the font.                             |
| `singleLine`           | Whether the text field is single line.          |
| `minLines`             | Minimum number of lines to display.             |
| `maxLines`             | Maximum number of lines to display.             |
| `onKeyboardAction`     | Handler for keyboard actions.                   |
| `keyboardOptions`      | Options for the keyboard.                       |
| `visualTransformation` | Visual transformation for the text.             |
| `interactionSource`    | Interaction source for the text field.          |
| `scrollState`          | Scroll state for the text field.                |
| `textColor`            | Color of the text.                              |
| `content`              | Content composable that defines the text field's appearance. |

### TextFieldScope.TextInput

| Parameter              | Description                                     |
|------------------------|-------------------------------------------------|
| `modifier`             | Modifier to be applied to the text input.       |
| `shape`                | Shape of the text input.                        |
| `backgroundColor`      | Background color of the text input.             |
| `contentPadding`       | Padding values for the content.                 |
| `contentColor`         | Color of the text content.                      |
| `label`                | Accessibility label for the text input.         |
| `placeholder`          | Placeholder composable when the field is empty. |
| `leading`              | Leading composable to display.                  |
| `trailing`             | Trailing composable to display.                 |
| `verticalAlignment`    | Vertical alignment of the content.              |

## Icons and other icons

You can find the icons used in our examples and many other icons at [composeicons.com](https://composeicons.com).
