Compose Unstyled 2.0 is out! Check the official announcement blog ->

Text Fields

Text input fields for standard, ghost, search, multiline, and read-only states.

Use text fields for editable text input, inline search, and compact form controls.

View on GitHub
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.composables.ui.components.Text
import com.composables.ui.components.TextField
import com.composables.ui.theme.colors
import com.composables.ui.theme.mutedColor
import com.composeunstyled.LocalTextStyle
import com.composeunstyled.theme.Theme

@Composable
fun DefaultTextFieldExample() {
    val state = rememberTextFieldState()

    TextField(
        state = state,
        modifier = Modifier.fillMaxWidth(),
        accessibilityLabel = "Email",
        placeholder = { Text("[email protected]") },
    )
}

Installation

implementation("com.composables:ui:0.1.0")

Examples

View on GitHub
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.input.clearText
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.composables.icons.lucide.Lucide
import com.composables.icons.lucide.Search
import com.composables.icons.lucide.X
import com.composables.ui.components.ButtonSize
import com.composables.ui.components.ButtonStyle
import com.composables.ui.components.Icon
import com.composables.ui.components.IconButton
import com.composables.ui.components.Text
import com.composables.ui.components.TextField
import com.composables.ui.theme.colors
import com.composables.ui.theme.mutedColor
import com.composeunstyled.theme.Theme

@Composable
fun SearchTextFieldExample() {
    val state = rememberTextFieldState()

    TextField(
        state = state,
        modifier = Modifier.fillMaxWidth(),
        accessibilityLabel = "Search",
        placeholder = { Text("Search...") },
        leading = {
            Icon(
                imageVector = Lucide.Search,
                contentDescription = null,
                modifier = Modifier.size(16.dp),
                tint = Theme[colors][mutedColor],
            )
        },
        trailing = {
            AnimatedVisibility(
                visible = state.text.isNotEmpty(),
                enter = fadeIn(), exit = fadeOut()
            ) {
                IconButton(
                    onClick = { state.clearText() },
                    modifier = Modifier.size(32.dp),
                    style = ButtonStyle.Ghost,
                    buttonSize = ButtonSize.Small,
                ) {
                    Icon(
                        imageVector = Lucide.X,
                        contentDescription = "Clear search",
                        modifier = Modifier.size(14.dp),
                        tint = Theme[colors][mutedColor],
                    )
                }
            }
        },
    )
}

Ghost

View on GitHub
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.composables.ui.components.Text
import com.composables.ui.components.TextField
import com.composables.ui.components.TextFieldStyle

@Composable
fun GhostTextFieldExample() {
    val state = rememberTextFieldState()

    TextField(
        state = state,
        modifier = Modifier.fillMaxWidth(),
        placeholder = { Text("Type your name...") },
        style = TextFieldStyle.Ghost,
    )
}

Multiline

View on GitHub
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.composables.ui.components.Text
import com.composables.ui.components.TextField

@Composable
fun MultilineTextFieldExample() {
    val state = rememberTextFieldState()

    TextField(
        state = state,
        modifier = Modifier.fillMaxWidth(),
        accessibilityLabel = "Feedback",
        placeholder = { Text("Tell us what could be better...") },
        contentPadding = PaddingValues(12.dp),
        lineLimits = TextFieldLineLimits.MultiLine(
            minHeightInLines = 4,
            maxHeightInLines = 4,
        ),
    )
}

Disabled

View on GitHub
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.composables.icons.lucide.Lock
import com.composables.icons.lucide.Lucide
import com.composables.ui.components.Icon
import com.composables.ui.components.Text
import com.composables.ui.components.TextField
import com.composables.ui.theme.colors
import com.composables.ui.theme.mutedColor
import com.composeunstyled.LocalTextStyle
import com.composeunstyled.theme.Theme

@Composable
fun DisabledTextFieldExample() {
    val state = rememberTextFieldState("[email protected]")

    TextField(
        state = state,
        modifier = Modifier.fillMaxWidth(),
        enabled = false,
        accessibilityLabel = "Organization email",
        leading = {
            Icon(
                imageVector = Lucide.Lock,
                contentDescription = null,
                modifier = Modifier.size(16.dp),
                tint = Theme[colors][mutedColor],
            )
        },
    )
}

Read-only

View on GitHub
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.composables.icons.lucide.KeyRound
import com.composables.icons.lucide.Lucide
import com.composables.ui.components.Icon
import com.composables.ui.components.Text
import com.composables.ui.components.TextField
import com.composables.ui.theme.colors
import com.composables.ui.theme.mutedColor
import com.composeunstyled.LocalTextStyle
import com.composeunstyled.theme.Theme

@Composable
fun ReadOnlyTextFieldExample() {
    val state = rememberTextFieldState("proj_1K9xF4vQm2")

    TextField(
        state = state,
        modifier = Modifier.fillMaxWidth(),
        readOnly = true,
        accessibilityLabel = "Project ID",
        leading = {
            Icon(
                imageVector = Lucide.KeyRound,
                contentDescription = null,
                modifier = Modifier.size(16.dp),
                tint = Theme[colors][mutedColor],
            )
        },
    )
}

API Reference

TextField

A styled text input field.

@Composable
fun TextField(
    state: TextFieldState,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    readOnly: Boolean = false,
    accessibilityLabel: String? = null,
    placeholder: (@Composable () -> Unit)? = null,
    leading: (@Composable () -> Unit)? = null,
    trailing: (@Composable () -> Unit)? = null,
    style: TextFieldStyle = TextFieldStyle.Default,
    shape: Shape = Theme[shapes][fieldShape],
    backgroundColor: Color = textFieldBackgroundColorFor(style),
    contentColor: Color = Theme[colors][onFieldColor],
    placeholderColor: Color = Theme[colors][mutedColor],
    borderColor: Color = textFieldBorderColorFor(style),
    contentPadding: PaddingValues = PaddingValues(horizontal = 12.dp),
    cursorBrush: Brush = SolidColor(contentColor),
    selectionColors: TextSelectionColors = Theme[textSelectionColors][defaultTextSelectionColors],
    textStyle: TextStyle = LocalTextStyle.current.merge(TextFieldInputTextStyle),
    textAlign: TextAlign = TextAlign.Unspecified,
    lineHeight: TextUnit = TextUnit.Unspecified,
    fontSize: TextUnit = textStyle.fontSize,
    letterSpacing: TextUnit = textStyle.letterSpacing,
    fontWeight: FontWeight? = textStyle.fontWeight,
    fontFamily: FontFamily? = textStyle.fontFamily,
    textDecoration: TextDecoration? = textStyle.textDecoration,
    lineLimits: TextFieldLineLimits = TextFieldLineLimits.SingleLine,
    inputTransformation: InputTransformation? = null,
    outputTransformation: OutputTransformation? = null,
    onTextLayout: (Density.(getResult: () -> TextLayoutResult?) -> Unit)? = null,
    onKeyboardAction: KeyboardActionHandler? = null,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    scrollState: ScrollState = rememberScrollState(),
)
Parameter Type Description
state TextFieldState State object that holds and edits the text field value.
modifier Modifier Modifier applied to the text field.
enabled Boolean Whether the text field can be interacted with.
readOnly Boolean Whether the text field can receive focus without allowing text edits.
accessibilityLabel String? Accessible label announced for the text field.
placeholder (@Composable () -> Unit)? Content displayed when the text field is empty.
leading (@Composable () -> Unit)? Content displayed before the editable text.
trailing (@Composable () -> Unit)? Content displayed after the editable text.
style TextFieldStyle Visual style used by the text field.
shape Shape Shape used for the text field container and focus ring.
backgroundColor Color Background color used by the text field container.
contentColor Color Color used for input text and field content.
placeholderColor Color Color used for placeholder content.
borderColor Color Border color drawn around the text field when specified.
contentPadding PaddingValues Padding applied around the text field content.
cursorBrush Brush Brush used to draw the text cursor.
selectionColors TextSelectionColors Colors used for text selection handles and highlight.
textStyle TextStyle Text style used by the editable text.
textAlign TextAlign Text alignment used by the editable text.
lineHeight TextUnit Line height used by the editable text.
fontSize TextUnit Font size used by the editable text.
letterSpacing TextUnit Letter spacing used by the editable text.
fontWeight FontWeight? Font weight used by the editable text.
fontFamily FontFamily? Font family used by the editable text.
textDecoration TextDecoration? Text decoration used by the editable text.
lineLimits TextFieldLineLimits Single-line or multiline limits used by the text field.
inputTransformation InputTransformation? Transformation applied to input edits before they are committed.
outputTransformation OutputTransformation? Transformation applied to displayed text.
onTextLayout (Density.(getResult: () -> TextLayoutResult?) -> Unit)? Called with the latest text layout result.
onKeyboardAction KeyboardActionHandler? Called when the keyboard action is triggered.
keyboardOptions KeyboardOptions Keyboard configuration for the text field.
interactionSource MutableInteractionSource Interaction source used for focus state.
scrollState ScrollState Scroll state used by the editable text.

TextFieldStyle

Visual style variants for TextField.

@kotlin.jvm.JvmInline
value class TextFieldStyle internal constructor(@Suppress("unused") private val value: Int)
Value Description
Default Uses the default text field style.
Filled Uses the filled text field container.
Ghost Uses a transparent text field container.