Package-level declarations

Dropdowns

Dropdown allow users to select an option from a dropdown.

They typically appear in forms and dialogs. Dropdown is an interactive element that allows users to select an option from a list of choices presented in a collapsible menu. It saves space on the interface by concealing the options until the user interacts with the component.

Textfield Items & Groups

The minimal usage of the component is :

  • The value of your textfield

  • The callback when the user exit the dismiss the dropdown without selecting a value.

  • A value to indicate if the dropdown should be shown or not.

  • A value

private val options = listOf("Option 1", "Option 2", "Option 3", "Option 4", "Option 5")
private var expanded by remember { mutableStateOf(false) }
private var selectedOptionText by remember { mutableStateOf(options[0]) }
Dropdown(
value = selectedOptionsText,
label = "label",
onDismissRequest = {
expanded = false
},
expanded = expanded,
onExpandedChange = {
expanded = !expanded
},
) {
options.forEach { selectionOption ->
DropdownMenuItem(
onClick = {
selectedOptionText = selectionOption
expanded = false
},
) {
Text(text = selectionOption)
}
}
}

Multi selection

Like single selection, the selection system is handled by the developer. It enables you to have a multi selection dropdown logics that don't force you into using a specific model but your own.

Here's an example of a multi selection dropdown that you could use in your project:

// Your data source from your state model
private val DropdownStubData = persistentListOf(
"To Kill a Mockingbird", "War and Peace", "The Idiot",
"A Picture of Dorian Gray", "1984", "Pride and Prejudice",
)
private val multiSelectionFilter by remember { mutableStateOf(DropdownStubData) }

private var selectedItems by remember {
mutableStateOf(listOf("To Kill a Mockingbird", "War and Peace"))
}
private val multiSelectedValues by remember(selectedItems.size) {
derivedStateOf {
val suffix = if (selectedItems.size 1) ", +${selectedItems.size - 1}" else ""
selectedItems.firstOrNull().orEmpty() + suffix
}
}

SelectTextField(
value = multiSelectedValues,
// ...
) {
multiSelectionFilter.forEach { book ->
// This should be part of your model otherwise it's a huge work that done on
// each items but we're simplifying things since it's an example here.
val isSelected = book in selectedItems
DropdownMenuItem(
text = {
Text(
text = book,
style = if (isSelected) {
SparkTheme.typography.body1.highlight
} else {
SparkTheme.typography.body1
},
)
},
onClick = {
selectedItems = if (book in selectedItems) {
selectedItems - book
} else {
selectedItems + book
}
// Here we want to have the dropdown to stay expanded when we multiSelect but
// you could use the line below if in the case you want to have the same behaviour
// as the single selection.
// expanded = false
},
)
}
}

Item groups

Dropdowns items can be grouped, you'll need to provide a label on it though. You can sort them like you want and the logic to show or not the group on sort is up to you.

Here's an example of a grouped dropdown that you could use in your project:

private val singleSelectionFilter by remember { mutableStateOf(DropdownStubData) }

private var singleSelected by remember { mutableStateOf("") }

Dropdown(
value = singleSelected,
// ...
) {
singleSelectionFilter.forEach { (groupName, books) ->
DropdownMenuGroupItem(
title = { Text(groupName) }, // You can customize the style of the label here
) {
books.forEach { book ->
DropdownMenuItem(
text = { Text(book) },
onClick = {
singleSelected = book
expanded = false
},
)
}
}
}
}

Textfields

Textfields allow users to enter text into a UI. They typically appear in forms and dialogs.

The minimal usage of the component is the value of your textfield and the callback to be called when the user type a new character but you can configure your textfield much more.

import java.awt.TextField

TextField(
value = "Input",
label = { Text("Label") },
placeholder = { Text("Placeholder") },
leadingContent = {
Icon(
imageVector = Icons.Filled.ArrowDropDown,
contentDescription = null
)
},
onValueChange = { newValue -> }
)

Prefix/Suffix

TextField(
value = "Input",
label = { Text("Label") },
placeholder = { Text("Placeholder") },
leadingContent = {
// Prefix
Text("Prefix", modifier = Modifier.padding(start = 16.dp))
},
trailingContent = {
// Suffix
Text("Suffix", modifier = Modifier.padding(end = 16.dp))
},
onValueChange = { newValue -> }
)

MultilineTextFields

MultilineTextFields allow users to enter text into a UI. They typically appear in forms and dialogs. The multiline varaint can show a character counter and a clear value icon button.

The minimal usage of the component is the value of your textfield and the callback to be called when the user type a new character but you can configure your textfield much more.

MultilineTextField(
value = "Input",
label = { Text("Label") },
placeholder = { Text("Placeholder") },
leadingIcon = {
Icon(
imageVector = Icons.Filled.ArrowDropDown,
contentDescription = null
)
},
onValueChange = { newValue -> }
)

Prefix/Suffix

MultilineTextField(
value = "Input",
label = { Text("Label") },
placeholder = { Text("Placeholder") },
leadingIcon = {
// Prefix
Text("Prefix", modifier = Modifier.padding(start = 16.dp))
},
leadingIcon = {
// Suffix
Text("Suffix", modifier = Modifier.padding(end = 16.dp))
},
onValueChange = { newValue -> }
)

Types

Link copied to clipboard
abstract class AddonScope

Scope that provide pre-made addons for leading and trailing contents of TextField.

Link copied to clipboard
data class TextFieldCharacterCounter(val count: Int, val maxCharacter: Int)
Link copied to clipboard

State of a TextField that's used to change the highlight color to either Success, Alert or Error.

Functions

Link copied to clipboard
fun Dropdown(value: String, expanded: Boolean, onClick: () -> Unit, onClickLabel: String, modifier: Modifier = Modifier, enabled: Boolean = true, required: Boolean = false, label: String? = null, placeholder: String? = null, helper: String? = null, leadingContent: @Composable AddonScope.() -> Unit? = null, state: TextFieldState? = null, stateMessage: String? = null, visualTransformation: VisualTransformation = VisualTransformation.None, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() })

Outlined text input to get an input value from a list of elements selectable through a custom container (BottomSheet / Dialog / Screen) by the user.

fun Dropdown(value: String, 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, state: TextFieldState? = null, stateMessage: String? = null, visualTransformation: VisualTransformation = VisualTransformation.None, properties: PopupProperties = PopupProperties(focusable = true, dismissOnClickOutside = true), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, dropdownContent: @Composable ColumnScope.() -> Unit)

Outlined text input to get an input value from a list of elements selectable through a DropdownMenu by the user.

Link copied to clipboard
fun MultilineTextField(value: TextFieldValue, onValueChange: (TextFieldValue) -> Unit, onCancelClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, readOnly: Boolean = false, required: Boolean = false, label: String? = null, placeholder: String? = null, helper: String? = null, counter: TextFieldCharacterCounter? = null, leadingContent: @Composable AddonScope.() -> Unit? = null, state: TextFieldState? = null, stateMessage: String? = null, visualTransformation: VisualTransformation = VisualTransformation.None, keyboardOptions: KeyboardOptions = KeyboardOptions.Default.copy(capitalization = KeyboardCapitalization.Sentences), keyboardActions: KeyboardActions = KeyboardActions.Default, maxLines: Int = Int.MAX_VALUE, minLines: Int = 1, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() })
fun MultilineTextField(value: String, onValueChange: (String) -> Unit, onCancelClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, readOnly: Boolean = false, required: Boolean = false, label: String? = null, placeholder: String? = null, helper: String? = null, counter: TextFieldCharacterCounter? = null, leadingContent: @Composable AddonScope.() -> Unit? = null, state: TextFieldState? = null, stateMessage: String? = null, visualTransformation: VisualTransformation = VisualTransformation.None, keyboardOptions: KeyboardOptions = KeyboardOptions.Default.copy(capitalization = KeyboardCapitalization.Sentences), keyboardActions: KeyboardActions = KeyboardActions.Default, maxLines: Int = Int.MAX_VALUE, minLines: Int = 1, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() })

Outlined text input to get an input value from the user. Which can scroll its content when value takes more place than the available width. We can also set the amount of maximum lines it can expand before overscrolling.

Link copied to clipboard
fun SelectTextField(value: TextFieldValue, onValueChange: (TextFieldValue) -> Unit, expanded: Boolean, onExpandedChange: (Boolean) -> Unit, onDismissRequest: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, readOnly: Boolean = false, required: Boolean = false, label: String? = null, placeholder: String? = null, helper: String? = null, leadingContent: @Composable AddonScope.() -> Unit? = null, state: TextFieldState? = null, stateMessage: String? = null, visualTransformation: VisualTransformation = VisualTransformation.None, keyboardOptions: KeyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Sentences), keyboardActions: KeyboardActions = KeyboardActions.Default, properties: PopupProperties = PopupProperties(focusable = readOnly, dismissOnClickOutside = readOnly), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, dropdownContent: @Composable ColumnScope.() -> Unit)
fun SelectTextField(value: String, onValueChange: (String) -> Unit, expanded: Boolean, onExpandedChange: (Boolean) -> Unit, onDismissRequest: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, readOnly: Boolean = false, required: Boolean = false, label: String? = null, placeholder: String? = null, helper: String? = null, leadingContent: @Composable AddonScope.() -> Unit? = null, state: TextFieldState? = null, stateMessage: String? = null, visualTransformation: VisualTransformation = VisualTransformation.None, keyboardOptions: KeyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Sentences), keyboardActions: KeyboardActions = KeyboardActions.Default, properties: PopupProperties = PopupProperties(focusable = readOnly, dismissOnClickOutside = readOnly), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, dropdownContent: @Composable ColumnScope.() -> Unit)

Outlined text input to get an input value from a list of elements selectable through a dropdown by the user.

Link copied to clipboard
fun SparkSelectTrailingIcon(expanded: Boolean, modifier: Modifier = Modifier)

Default trailing icon for Exposed Dropdown Menu.

Link copied to clipboard
fun TextField(value: TextFieldValue, onValueChange: (TextFieldValue) -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, readOnly: Boolean = false, required: Boolean = false, label: String? = null, placeholder: String? = null, helper: String? = null, leadingContent: @Composable AddonScope.() -> Unit? = null, trailingContent: @Composable AddonScope.() -> Unit? = null, state: TextFieldState? = null, stateMessage: String? = null, visualTransformation: VisualTransformation = VisualTransformation.None, keyboardOptions: KeyboardOptions = KeyboardOptions.Default.copy(capitalization = KeyboardCapitalization.Sentences), keyboardActions: KeyboardActions = KeyboardActions.Default, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() })
fun TextField(value: String, onValueChange: (String) -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, readOnly: Boolean = false, required: Boolean = false, label: String? = null, placeholder: String? = null, helper: String? = null, leadingContent: @Composable AddonScope.() -> Unit? = null, trailingContent: @Composable AddonScope.() -> Unit? = null, state: TextFieldState? = null, stateMessage: String? = null, visualTransformation: VisualTransformation = VisualTransformation.None, keyboardOptions: KeyboardOptions = KeyboardOptions.Default.copy(capitalization = KeyboardCapitalization.Sentences), keyboardActions: KeyboardActions = KeyboardActions.Default, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() })

Outlined text input to get an input value from the user.