SingleChoiceComboBox

fun SingleChoiceComboBox(state: TextFieldState, expanded: Boolean, onExpandedChange: (Boolean) -> Unit, onDismissRequest: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, required: Boolean = false, label: String? = null, placeholder: String? = null, helper: String? = null, leadingContent: @Composable AddonScope.() -> Unit? = null, trailingContent: @Composable AddonScope.() -> Unit? = null, status: FormFieldStatus? = null, statusMessage: String? = null, inputTransformation: InputTransformation? = null, keyboardOptions: KeyboardOptions = KeyboardOptions.Default, onKeyboardAction: KeyboardActionHandler? = null, lineLimits: TextFieldLineLimits = TextFieldLineLimits.Default, onTextLayout: Density.(getResult: () -> TextLayoutResult?) -> Unit? = null, interactionSource: MutableInteractionSource? = null, outputTransformation: OutputTransformation? = null, scrollState: ScrollState = rememberScrollState(), dropdownContent: @Composable SingleChoiceDropdownItemColumnScope.() -> Unit)(source)

A ComboBox component that allows users to select a single option from a dropdown list. It combines a text field with a dropdown menu, providing a searchable interface for selecting options.

Parameters

state

The state of the text field that controls the input value

expanded

Whether the dropdown menu is currently expanded

onExpandedChange

Callback invoked when the expanded state changes

onDismissRequest

Callback invoked when the dropdown menu should be dismissed

modifier

Modifier to be applied to the ComboBox

enabled

Whether the ComboBox is enabled

required

Whether the field is required

label

Optional label text displayed above the ComboBox

placeholder

Optional placeholder text shown when the field is empty

helper

Optional helper text displayed below the ComboBox

leadingContent

Optional composable content displayed at the start of the ComboBox

trailingContent

Optional composable content displayed at the end of the ComboBox, if not provided, a default trailing icon will be used.

status

Optional status of the form field (e.g., error, success)

statusMessage

Optional message associated with the status

inputTransformation

Optional transformation applied to input text

keyboardOptions

Options for the keyboard

onKeyboardAction

Optional handler for keyboard actions

lineLimits

Limits for the number of lines in the text field

onTextLayout

Optional callback for text layout changes

interactionSource

Optional interaction source for the ComboBox

outputTransformation

Optional transformation applied to output text

scrollState

Scroll state for the text field

dropdownContent

Content of the dropdown menu, using SingleChoiceDropdownItemColumnScope

See also

for a version that supports multiple selections

Samples

val state = rememberTextFieldState()
var expanded by remember { mutableStateOf(false) }

SingleChoiceComboBox(
    modifier = Modifier.fillMaxWidth(),
    state = state,
    expanded = expanded,
    onExpandedChange = { expanded = it },
    onDismissRequest = { expanded = false },
    required = true,
    label = "Select a book",
    placeholder = "Choose a book…",
    helper = "Click the selected item again to deselect it",
    dropdownContent = {
        books.forEach { book ->
            val isSelected = book.title == state.text.toString()
            DropdownMenuItem(
                text = { Text(book.title) },
                onClick = {
                    if (isSelected) state.clearText() else state.setTextAndPlaceCursorAtEnd(book.title)
                    expanded = false
                },
                selected = isSelected,
            )
        }
    },
)
val state = rememberTextFieldState()
var expanded by remember { mutableStateOf(false) }
var searchText by remember { mutableStateOf("") }

val filteredBooks by remember(searchText) {
    derivedStateOf {
        if (searchText.isBlank()) {
            books
        } else {
            books.filter { it.title.contains(searchText, ignoreCase = true) }
        }
    }
}

LaunchedEffect(Unit) {
    snapshotFlow { state.text }
        .debounce(300.milliseconds)
        .onEach { searchText = it.toString() }
        .collect()
}

SingleChoiceComboBox(
    modifier = Modifier.fillMaxWidth(),
    state = state,
    expanded = expanded,
    onExpandedChange = { expanded = it },
    onDismissRequest = { expanded = false },
    required = true,
    label = "Search books",
    placeholder = "Type to filter…",
    dropdownContent = {
        filteredBooks.forEach { book ->
            DropdownMenuItem(
                text = { Text(book.title) },
                onClick = {
                    state.setTextAndPlaceCursorAtEnd(book.title)
                    expanded = false
                },
                selected = book.title == state.text.toString(),
            )
        }
    },
)